dolphin-emulator/Externals/wxWidgets3/src/osx/glcanvas_osx.cpp

610 lines
16 KiB
C++
Raw Normal View History

///////////////////////////////////////////////////////////////////////////////
// Name: src/osx/glcanvas_osx.cpp
// Purpose: wxGLCanvas, for using OpenGL with wxWidgets under Macintosh
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "wx/wxprec.h"
#if defined(__BORLANDC__)
#pragma hdrstop
#endif
#if wxUSE_GLCANVAS
#include "wx/glcanvas.h"
#ifndef WX_PRECOMP
#include "wx/frame.h"
#include "wx/log.h"
#include "wx/settings.h"
#endif
#include "wx/osx/private.h"
// These 'WX' values are the same as 'NS' ones
// Source: https://developer.apple.com/library/mac/documentation/
// Cocoa/Reference/ApplicationKit/Classes/NSOpenGLPixelFormat_Class/index.html
#define WXOpenGLPFAAllRenderers 1
#define WXOpenGLPFATripleBuffer 3
#define WXOpenGLPFADoubleBuffer 5
#define WXOpenGLPFAStereo 6
#define WXOpenGLPFAAuxBuffers 7
#define WXOpenGLPFAColorSize 8
#define WXOpenGLPFAAlphaSize 11
#define WXOpenGLPFADepthSize 12
#define WXOpenGLPFAStencilSize 13
#define WXOpenGLPFAAccumSize 14
#define WXOpenGLPFAMinimumPolicy 51
#define WXOpenGLPFAMaximumPolicy 52
#define WXOpenGLPFAOffScreen 53
#define WXOpenGLPFAFullScreen 54
#define WXOpenGLPFASampleBuffers 55
#define WXOpenGLPFASamples 56
#define WXOpenGLPFAAuxDepthStencil 57
#define WXOpenGLPFAColorFloat 58
#define WXOpenGLPFAMultisample 59
#define WXOpenGLPFASupersample 60
#define WXOpenGLPFASampleAlpha 61
#define WXOpenGLPFARendererID 70
#define WXOpenGLPFASingleRenderer 71
#define WXOpenGLPFANoRecovery 72
#define WXOpenGLPFAAccelerated 73
#define WXOpenGLPFAClosestPolicy 74
#define WXOpenGLPFARobust 75
#define WXOpenGLPFABackingStore 76
#define WXOpenGLPFAMPSafe 78
#define WXOpenGLPFAWindow 80
#define WXOpenGLPFAMultiScreen 81
#define WXOpenGLPFACompliant 83
#define WXOpenGLPFAScreenMask 84
#define WXOpenGLPFAPixelBuffer 90
#define WXOpenGLPFARemotePixelBuffer 91
#define WXOpenGLPFAAllowOfflineRenderers 96
#define WXOpenGLPFAAcceleratedCompute 97
#define WXOpenGLPFAOpenGLProfile 99
#define WXOpenGLPFAVirtualScreenCount 128
#define WXOpenGLProfileVersionLegacy 0x1000
#define WXOpenGLProfileVersion3_2Core 0x3200
// ----------------------------------------------------------------------------
// wxGLContextAttrs: OpenGL rendering context attributes
// ----------------------------------------------------------------------------
// OSX specific values
wxGLContextAttrs& wxGLContextAttrs::CoreProfile()
{
AddAttribute(WXOpenGLPFAOpenGLProfile);
AddAttribute(WXOpenGLProfileVersion3_2Core);
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::MajorVersion(int val)
{
// No effect
wxUnusedVar(val);
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::MinorVersion(int val)
{
// No effect
wxUnusedVar(val);
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::CompatibilityProfile()
{
AddAttribute(WXOpenGLPFAOpenGLProfile);
AddAttribute(WXOpenGLProfileVersionLegacy);
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::ForwardCompatible()
{
// No effect
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::ES2()
{
// No effect
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::DebugCtx()
{
// No effect
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::Robust()
{
// No effect. Somehow similar flag (NSOpenGLPFARobust) is deprecated in OS X v10.5
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::NoResetNotify()
{
// No effect
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::LoseOnReset()
{
// No effect
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::ResetIsolation()
{
// No effect
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::ReleaseFlush(int val)
{
// No effect
wxUnusedVar(val);
return *this;
}
wxGLContextAttrs& wxGLContextAttrs::PlatformDefaults()
{
// No OSX specific defaults
return *this;
}
void wxGLContextAttrs::EndList()
{
AddAttribute(0);
}
// ----------------------------------------------------------------------------
// wxGLAttributes: pixel format attributes
// ----------------------------------------------------------------------------
// OSX specific values
wxGLAttributes& wxGLAttributes::RGBA()
{
AddAttribute(WXOpenGLPFAColorSize);
AddAttribute(24);
AddAttribute(WXOpenGLPFAAlphaSize);
AddAttribute(8);
return *this;
}
wxGLAttributes& wxGLAttributes::BufferSize(int val)
{
// No effect
wxUnusedVar(val);
return *this;
}
wxGLAttributes& wxGLAttributes::Level(int val)
{
// No effect
wxUnusedVar(val);
return *this;
}
wxGLAttributes& wxGLAttributes::DoubleBuffer()
{
AddAttribute(WXOpenGLPFADoubleBuffer);
return *this;
}
wxGLAttributes& wxGLAttributes::Stereo()
{
AddAttribute(WXOpenGLPFAStereo);
return *this;
}
wxGLAttributes& wxGLAttributes::AuxBuffers(int val)
{
if ( val >= 0 )
{
AddAttribute(WXOpenGLPFAAuxBuffers);
AddAttribute(val);
}
return *this;
}
wxGLAttributes& wxGLAttributes::MinRGBA(int mRed, int mGreen, int mBlue, int mAlpha)
{
int minColorBits = 0;
if ( mRed > minColorBits )
minColorBits = mRed;
if ( mGreen > minColorBits )
minColorBits = mGreen;
if ( mBlue > minColorBits )
minColorBits = mBlue;
if ( minColorBits > 0 )
{
AddAttribute(WXOpenGLPFAColorSize);
AddAttribute(minColorBits);
}
if ( mAlpha >= 0 )
{
AddAttribute(WXOpenGLPFAAlphaSize);
AddAttribute(mAlpha);
}
return *this;
}
wxGLAttributes& wxGLAttributes::Depth(int val)
{
if ( val >= 0 )
{
AddAttribute(WXOpenGLPFADepthSize);
AddAttribute(val);
}
return *this;
}
wxGLAttributes& wxGLAttributes::Stencil(int val)
{
if ( val >= 0 )
{
AddAttribute(WXOpenGLPFAStencilSize);
AddAttribute(val);
}
return *this;
}
wxGLAttributes& wxGLAttributes::MinAcumRGBA(int mRed, int mGreen, int mBlue, int mAlpha)
{
int minAcumBits = 0;
if ( mRed > minAcumBits )
minAcumBits = mRed;
if ( mGreen > minAcumBits )
minAcumBits = mGreen;
if ( mBlue > minAcumBits )
minAcumBits = mBlue;
if ( minAcumBits > 0 )
{
AddAttribute(WXOpenGLPFAAccumSize);
AddAttribute(minAcumBits);
}
// No effect for Alpha in accumulation buffer
wxUnusedVar(mAlpha);
return *this;
}
wxGLAttributes& wxGLAttributes::SampleBuffers(int val)
{
if ( val >= 0 )
{
AddAttribute(WXOpenGLPFASampleBuffers);
AddAttribute(val);
// Don't use software fallback
AddAttribute(WXOpenGLPFANoRecovery);
}
return *this;
}
wxGLAttributes& wxGLAttributes::Samplers(int val)
{
if ( val >= 0 )
{
AddAttribute(WXOpenGLPFASamples);
AddAttribute(val);
}
return *this;
}
wxGLAttributes& wxGLAttributes::FrameBuffersRGB()
{
// No effect
return *this;
}
void wxGLAttributes::EndList()
{
AddAttribute(0);
}
wxGLAttributes& wxGLAttributes::PlatformDefaults()
{
AddAttribute(WXOpenGLPFAMinimumPolicy); // use _SIZE tags as minimum sizes
// Test if we support hardware acceleration, we always want to use it if it
// is available and, apparently, in spite of the Apple docs explicitly
// saying the contrary:
//
// If present, this attribute indicates that only hardware-accelerated
// renderers are considered. If not present, accelerated renderers are
// still preferred.
//
// hardware acceleration is not always used without it, so we do need to
// specify it. But we shouldn't do it if acceleration is really not
// available.
const int attrsAccel[] = { WXOpenGLPFAAccelerated, 0 };
WXGLPixelFormat testFormat = WXGLChoosePixelFormat(attrsAccel, 2);
if ( testFormat )
{
// Hardware acceleration is available, use it.
AddAttribute(WXOpenGLPFAAccelerated);
WXGLDestroyPixelFormat(testFormat);
}
return *this;
}
wxGLAttributes& wxGLAttributes::Defaults()
{
RGBA().Depth(16).DoubleBuffer().SampleBuffers(1).Samplers(4);
return *this;
}
// ----------------------------------------------------------------------------
// wxGLContext
// ----------------------------------------------------------------------------
wxGLContext::wxGLContext(wxGLCanvas *win,
const wxGLContext *other,
const wxGLContextAttrs *ctxAttrs)
: m_glContext(NULL)
{
const int* contextAttribs = NULL;
int ctxSize = 0;
if ( ctxAttrs )
{
contextAttribs = ctxAttrs->GetGLAttrs();
ctxSize = ctxAttrs->GetSize();
}
else if ( win->GetGLCTXAttrs().GetGLAttrs() )
{
// If OpenGL context parameters were set at wxGLCanvas ctor, get them now
contextAttribs = win->GetGLCTXAttrs().GetGLAttrs();
ctxSize = win->GetGLCTXAttrs().GetSize();
}
// else use GPU driver defaults
// Join canvas attributes and context attributes to ask for a pixel format
WXGLPixelFormat pf = WXGLChoosePixelFormat(win->GetGLDispAttrs().GetGLAttrs(),
win->GetGLDispAttrs().GetSize(),
contextAttribs, ctxSize);
m_isOk = false;
if ( pf )
{
m_glContext = WXGLCreateContext(pf, other ? other->m_glContext : NULL);
if ( m_glContext )
{
m_isOk = true;
}
WXGLDestroyPixelFormat(pf);
}
if ( !m_isOk )
wxLogMessage(_("Couldn't create OpenGL context"));
}
wxGLContext::~wxGLContext()
{
if ( m_glContext )
{
WXGLDestroyContext(m_glContext);
}
}
// ----------------------------------------------------------------------------
// wxGLCanvas
// ----------------------------------------------------------------------------
wxIMPLEMENT_CLASS(wxGLCanvas, wxWindow);
wxBEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
wxEND_EVENT_TABLE()
wxGLCanvas::wxGLCanvas(wxWindow *parent,
const wxGLAttributes& dispAttrs,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const wxPalette& palette)
{
Create(parent, dispAttrs, id, pos, size, style, name, palette);
}
wxGLCanvas::wxGLCanvas(wxWindow *parent,
wxWindowID id,
const int *attribList,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const wxPalette& palette)
{
Create(parent, id, pos, size, style, name, attribList, palette);
}
bool wxGLCanvas::Create(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& palette)
{
// Separate 'pixel format' attributes.
// Also store context attributes for wxGLContext ctor
// If 'attribList' is NULL, ParseAttribList() will set defaults.
wxGLAttributes dispAttrs;
if ( ! ParseAttribList(attribList, dispAttrs, &m_GLCTXAttrs) )
return false;
return Create(parent, dispAttrs, id, pos, size, style, name, palette);
}
bool wxGLCanvas::Create(wxWindow *parent,
const wxGLAttributes& dispAttrs,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const wxPalette& WXUNUSED(palette))
{
m_glFormat = NULL;
// Don't allow an empty list
if ( !dispAttrs.GetGLAttrs() )
{
wxFAIL_MSG("wxGLAttributes object is empty.");
return false;
}
// Return false if any attribute is unsupported
if ( ! IsDisplaySupported(dispAttrs) )
{
wxFAIL_MSG("Can't find a pixel format for the requested attributes");
return false;
}
// Make a copy of attributes. Will use at wxGLContext ctor
m_GLAttrs = dispAttrs;
if ( !wxWindow::Create(parent, id, pos, size, style, name) )
return false;
return true;
}
#if WXWIN_COMPATIBILITY_2_8
wxGLCanvas::wxGLCanvas(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& palette)
{
if ( Create(parent, id, pos, size, style, name, attribList, palette) )
m_glContext = new wxGLContext(this);
}
wxGLCanvas::wxGLCanvas(wxWindow *parent,
const wxGLContext *shared,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& palette)
{
if ( Create(parent, id, pos, size, style, name, attribList, palette) )
m_glContext = new wxGLContext(this, shared);
}
wxGLCanvas::wxGLCanvas(wxWindow *parent,
const wxGLCanvas *shared,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name,
const int *attribList,
const wxPalette& palette)
{
if ( Create(parent, id, pos, size, style, name, attribList, palette) )
m_glContext = new wxGLContext(this, shared ? shared->m_glContext : NULL);
}
#endif // WXWIN_COMPATIBILITY_2_8
/* static */
bool wxGLCanvas::IsAGLMultiSampleAvailable()
{
static int s_isMultiSampleAvailable = -1;
if ( s_isMultiSampleAvailable == -1 )
s_isMultiSampleAvailable = IsExtensionSupported("GL_ARB_multisample");
return s_isMultiSampleAvailable != 0;
}
/* static */
bool wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs)
{
WXGLPixelFormat testFormat = WXGLChoosePixelFormat(dispAttrs.GetGLAttrs(), dispAttrs.GetSize());
if ( testFormat )
{
WXGLDestroyPixelFormat(testFormat);
}
else
{
return false;
}
return true;
}
/* static */
bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
{
wxGLAttributes dispAttrs;
ParseAttribList(attribList, dispAttrs);
return IsDisplaySupported(dispAttrs);
}
bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
{
// We need a valid context to query for extensions. Use a default one.
wxGLAttributes dispAttrs;
ParseAttribList(NULL, dispAttrs); // Sets defaults
WXGLPixelFormat fmt = WXGLChoosePixelFormat(dispAttrs.GetGLAttrs(), dispAttrs.GetSize());
WXGLContext ctx = WXGLCreateContext(fmt, NULL);
if ( !ctx )
return false;
WXGLContext ctxOld = WXGLGetCurrentContext();
WXGLSetCurrentContext(ctx);
wxString extensions = wxString::FromAscii(glGetString(GL_EXTENSIONS));
WXGLSetCurrentContext(ctxOld);
WXGLDestroyPixelFormat(fmt);
WXGLDestroyContext(ctx);
return IsExtensionInList(extensions.ToAscii(), extension);
}
// ----------------------------------------------------------------------------
// wxGLApp
// ----------------------------------------------------------------------------
bool wxGLApp::InitGLVisual(const int *attribList)
{
WXGLPixelFormat fmt = WXGLChoosePixelFormat(attribList);
if ( !fmt )
return false;
WXGLDestroyPixelFormat(fmt);
return true;
}
#endif // wxUSE_GLCANVAS