Update QSurfaceFormat when creating a GL context in the cocoa qpa

Task-number: QTBUG-34471
Change-Id: I99f643280b8a4aaa8d63329232c0c3f4b2faed4b
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
bb10
Sean Harmer 2013-11-04 15:59:55 +00:00 committed by The Qt Project
parent 20981e2953
commit 038b0dae83
2 changed files with 140 additions and 0 deletions

View File

@ -77,6 +77,7 @@ public:
private:
void setActiveWindow(QWindow *window);
void updateSurfaceFormat();
NSOpenGLContext *m_context;
NSOpenGLContext *m_shareContext;

View File

@ -48,6 +48,74 @@
#import <Cocoa/Cocoa.h>
static inline QByteArray getGlString(GLenum param)
{
if (const GLubyte *s = glGetString(param))
return QByteArray(reinterpret_cast<const char*>(s));
return QByteArray();
}
#if !defined(GL_CONTEXT_FLAGS)
#define GL_CONTEXT_FLAGS 0x821E
#endif
#if !defined(GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
#endif
#if !defined(GL_CONTEXT_PROFILE_MASK)
#define GL_CONTEXT_PROFILE_MASK 0x9126
#endif
#if !defined(GL_CONTEXT_CORE_PROFILE_BIT)
#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
#endif
#if !defined(GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
#endif
static void updateFormatFromContext(QSurfaceFormat *format)
{
Q_ASSERT(format);
// Update the version, profile, and context bit of the format
int major = 0, minor = 0;
QByteArray versionString(getGlString(GL_VERSION));
if (QPlatformOpenGLContext::parseOpenGLVersion(versionString, major, minor)) {
format->setMajorVersion(major);
format->setMinorVersion(minor);
}
format->setProfile(QSurfaceFormat::NoProfile);
Q_ASSERT(format->renderableType() == QSurfaceFormat::OpenGL);
if (format->version() < qMakePair(3, 0)) {
format->setOption(QSurfaceFormat::DeprecatedFunctions);
return;
}
// Version 3.0 onwards - check if it includes deprecated functionality
GLint value = 0;
glGetIntegerv(GL_CONTEXT_FLAGS, &value);
if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
format->setOption(QSurfaceFormat::DeprecatedFunctions);
// Debug context option not supported on OS X
if (format->version() < qMakePair(3, 2))
return;
// Version 3.2 and newer have a profile
value = 0;
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
if (value & GL_CONTEXT_CORE_PROFILE_BIT)
format->setProfile(QSurfaceFormat::CoreProfile);
else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
format->setProfile(QSurfaceFormat::CompatibilityProfile);
}
QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
: m_context(nil),
m_shareContext(nil),
@ -82,6 +150,8 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo
int zeroOpacity = 0;
[m_context setValues:&zeroOpacity forParameter:NSOpenGLCPSurfaceOpacity];
}
updateSurfaceFormat();
}
QCocoaGLContext::~QCocoaGLContext()
@ -137,6 +207,75 @@ void QCocoaGLContext::setActiveWindow(QWindow *window)
[(QNSView *) cocoaWindow->contentView() setQCocoaGLContext:this];
}
void QCocoaGLContext::updateSurfaceFormat()
{
// At present it is impossible to turn an option off on a QSurfaceFormat (see
// https://codereview.qt-project.org/#change,70599). So we have to populate
// the actual surface format from scratch
QSurfaceFormat requestedFormat = m_format;
m_format = QSurfaceFormat();
m_format.setRenderableType(QSurfaceFormat::OpenGL);
// CoreGL doesn't require a drawable to make the context current
CGLContextObj oldContext = CGLGetCurrentContext();
CGLContextObj ctx = static_cast<CGLContextObj>([m_context CGLContextObj]);
CGLSetCurrentContext(ctx);
// Get the data that OpenGL provides
updateFormatFromContext(&m_format);
// Get the data contained within the pixel format
CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>(CGLGetPixelFormat(ctx));
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithCGLPixelFormatObj:cglPixelFormat];
int colorSize = -1;
[pixelFormat getValues:&colorSize forAttribute:NSOpenGLPFAColorSize forVirtualScreen:0];
if (colorSize > 0) {
// This seems to return the total color buffer depth, including alpha
m_format.setRedBufferSize(colorSize / 4);
m_format.setGreenBufferSize(colorSize / 4);
m_format.setBlueBufferSize(colorSize / 4);
}
// The pixel format always seems to return 8 for alpha. However, the framebuffer only
// seems to have alpha enabled if we requested it explicitly. I can't find any other
// attribute to check explicitly for this so we use our best guess for alpha.
int alphaSize = -1;
[pixelFormat getValues:&alphaSize forAttribute:NSOpenGLPFAAlphaSize forVirtualScreen:0];
qDebug() << "alphaSize =" << alphaSize;
if (alphaSize > 0 && requestedFormat.alphaBufferSize() > 0)
m_format.setAlphaBufferSize(alphaSize);
int depthSize = -1;
[pixelFormat getValues:&depthSize forAttribute:NSOpenGLPFADepthSize forVirtualScreen:0];
if (depthSize > 0)
m_format.setDepthBufferSize(depthSize);
int stencilSize = -1;
[pixelFormat getValues:&stencilSize forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:0];
if (stencilSize > 0)
m_format.setStencilBufferSize(stencilSize);
int samples = -1;
[pixelFormat getValues:&samples forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
if (samples > 0)
m_format.setSamples(samples);
int doubleBuffered = -1;
[pixelFormat getValues:&doubleBuffered forAttribute:NSOpenGLPFADoubleBuffer forVirtualScreen:0];
m_format.setSwapBehavior(doubleBuffered == 1 ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::SingleBuffer);
int steroBuffers = -1;
[pixelFormat getValues:&steroBuffers forAttribute:NSOpenGLPFAStereo forVirtualScreen:0];
if (steroBuffers == 1)
m_format.setOption(QSurfaceFormat::StereoBuffers);
[pixelFormat release];
// Restore the original context
CGLSetCurrentContext(oldContext);
}
void QCocoaGLContext::doneCurrent()
{
if (m_currentWindow && m_currentWindow.data()->handle())