Improve wxGLCanvas to be more type safe and better support modern OpenGL
Add wxGLAttribsBase, wxGLAttributes and wxGLContextAttrs replacing the old untyped "int attributes[]". Don't use global object for creating OpenGL > 3.0 contexts. Closes #16909.
This commit is contained in:
committed by
Vadim Zeitlin
parent
fb5ff50eda
commit
bdc95f5766
@@ -34,14 +34,367 @@
|
||||
|
||||
#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
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxGLCanvas
|
||||
// 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)
|
||||
wxGLContext::wxGLContext(wxGLCanvas *win,
|
||||
const wxGLContext *other,
|
||||
const wxGLContextAttrs *ctxAttrs)
|
||||
{
|
||||
m_glContext = WXGLCreateContext(win->GetWXGLPixelFormat(),
|
||||
other ? other->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()
|
||||
@@ -61,6 +414,18 @@ 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,
|
||||
@@ -73,6 +438,58 @@ wxGLCanvas::wxGLCanvas(wxWindow *parent,
|
||||
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,
|
||||
@@ -128,23 +545,36 @@ bool wxGLCanvas::IsAGLMultiSampleAvailable()
|
||||
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)
|
||||
{
|
||||
WXGLPixelFormat glFormat = WXGLChoosePixelFormat(attribList);
|
||||
wxGLAttributes dispAttrs;
|
||||
ParseAttribList(attribList, dispAttrs);
|
||||
|
||||
if ( !glFormat )
|
||||
return false;
|
||||
|
||||
WXGLDestroyPixelFormat(glFormat);
|
||||
|
||||
return true;
|
||||
return IsDisplaySupported(dispAttrs);
|
||||
}
|
||||
|
||||
bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
|
||||
{
|
||||
// we need a valid context to query for extensions.
|
||||
WXGLPixelFormat fmt = WXGLChoosePixelFormat(NULL);
|
||||
// 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;
|
||||
|
Reference in New Issue
Block a user