Switch back to Qt for GL context creation by default

This commit is contained in:
Brad Davis 2018-11-01 12:28:21 -07:00
parent 5c78a463de
commit 80c83fb4fb
3 changed files with 145 additions and 158 deletions

View file

@ -29,6 +29,9 @@
using namespace gl; using namespace gl;
#if defined(GL_CUSTOM_CONTEXT)
bool Context::USE_CUSTOM_CONTEXT { true };
#endif
bool Context::enableDebugLogger() { bool Context::enableDebugLogger() {
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
@ -75,24 +78,24 @@ Context::Context(QWindow* window) {
void Context::release() { void Context::release() {
doneCurrent(); doneCurrent();
#ifdef GL_CUSTOM_CONTEXT if (_qglContext) {
if (_wrappedContext) { destroyContext(_qglContext);
destroyContext(_wrappedContext); _qglContext = nullptr;
_wrappedContext = nullptr;
} }
#ifdef GL_CUSTOM_CONTEXT
if (_hglrc) { if (_hglrc) {
destroyWin32Context(_hglrc); wglDeleteContext(_hglrc);
_hglrc = 0; _hglrc = 0;
} }
if (_hdc) { if (_hdc) {
ReleaseDC(_hwnd, _hdc); ReleaseDC(_hwnd, _hdc);
_hdc = 0; _hdc = 0;
} }
_hwnd = 0; _hwnd = 0;
#else
destroyContext(_context);
_context = nullptr;
#endif #endif
_window = nullptr; _window = nullptr;
updateSwapchainMemoryCounter(); updateSwapchainMemoryCounter();
} }
@ -135,15 +138,6 @@ void Context::clear() {
#if defined(GL_CUSTOM_CONTEXT) #if defined(GL_CUSTOM_CONTEXT)
static void debugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) {
if (GL_DEBUG_SEVERITY_NOTIFICATION == severity) {
return;
}
// FIXME For high severity errors, force a sync to the log, since we might crash
// before the log file was flushed otherwise. Performance hit here
qCDebug(glLogging) << "OpenGL: " << message;
}
static void setupPixelFormatSimple(HDC hdc) { static void setupPixelFormatSimple(HDC hdc) {
// FIXME build the PFD based on the // FIXME build the PFD based on the
static const PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be static const PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
@ -177,26 +171,6 @@ static void setupPixelFormatSimple(HDC hdc) {
} }
} }
void Context::destroyWin32Context(HGLRC hglrc) {
wglDeleteContext(hglrc);
}
bool Context::makeCurrent() {
BOOL result = wglMakeCurrent(_hdc, _hglrc);
assert(result);
updateSwapchainMemoryCounter();
return result;
}
void Context::swapBuffers() {
SwapBuffers(_hdc);
}
void Context::doneCurrent() {
wglMakeCurrent(0, 0);
}
// Pixel format arguments // Pixel format arguments
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
#define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
@ -229,9 +203,17 @@ typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShare
GLAPI PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; GLAPI PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
GLAPI PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; GLAPI PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
#endif
Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context();
void Context::create(QOpenGLContext* shareContext) { void Context::create(QOpenGLContext* shareContext) {
if (!shareContext) {
shareContext = qt_gl_global_share_context();
}
#if defined(GL_CUSTOM_CONTEXT)
assert(0 != _hwnd); assert(0 != _hwnd);
assert(0 == _hdc); assert(0 == _hdc);
auto hwnd = _hwnd; auto hwnd = _hwnd;
@ -250,104 +232,114 @@ void Context::create(QOpenGLContext* shareContext) {
wglMakeCurrent(0, 0); wglMakeCurrent(0, 0);
wglDeleteContext(glrc); wglDeleteContext(glrc);
ReleaseDC(hwnd, hdc); ReleaseDC(hwnd, hdc);
if (!wglChoosePixelFormatARB || !wglCreateContextAttribsARB) {
USE_CUSTOM_CONTEXT = false;
}
}); });
_hdc = GetDC(_hwnd); if (USE_CUSTOM_CONTEXT) {
_hdc = GetDC(_hwnd);
#if defined(USE_GLES) #if defined(USE_GLES)
_version = 0x0200; _version = 0x0302;
#else #else
if (gl::disableGl45()) { if (gl::disableGl45()) {
_version = 0x0401; _version = 0x0401;
} else if (GLAD_GL_VERSION_4_5) { } else if (GLAD_GL_VERSION_4_5) {
_version = 0x0405; _version = 0x0405;
} else if (GLAD_GL_VERSION_4_3) { } else if (GLAD_GL_VERSION_4_3) {
_version = 0x0403; _version = 0x0403;
} else { } else {
_version = 0x0401; _version = 0x0401;
} }
#endif #endif
static int pixelFormat = 0; static int pixelFormat = 0;
static PIXELFORMATDESCRIPTOR pfd; static PIXELFORMATDESCRIPTOR pfd;
if (!pixelFormat) { if (!pixelFormat) {
memset(&pfd, 0, sizeof(pfd)); memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd); pfd.nSize = sizeof(pfd);
std::vector<int> formatAttribs; std::vector<int> formatAttribs;
formatAttribs.push_back(WGL_DRAW_TO_WINDOW_ARB); formatAttribs.push_back(WGL_DRAW_TO_WINDOW_ARB);
formatAttribs.push_back(GL_TRUE); formatAttribs.push_back(GL_TRUE);
formatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB); formatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
formatAttribs.push_back(GL_TRUE); formatAttribs.push_back(GL_TRUE);
formatAttribs.push_back(WGL_DOUBLE_BUFFER_ARB); formatAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
formatAttribs.push_back(GL_TRUE); formatAttribs.push_back(GL_TRUE);
formatAttribs.push_back(WGL_PIXEL_TYPE_ARB); formatAttribs.push_back(WGL_PIXEL_TYPE_ARB);
formatAttribs.push_back(WGL_TYPE_RGBA_ARB); formatAttribs.push_back(WGL_TYPE_RGBA_ARB);
formatAttribs.push_back(WGL_COLOR_BITS_ARB); formatAttribs.push_back(WGL_COLOR_BITS_ARB);
formatAttribs.push_back(32); formatAttribs.push_back(32);
formatAttribs.push_back(WGL_DEPTH_BITS_ARB); formatAttribs.push_back(WGL_DEPTH_BITS_ARB);
formatAttribs.push_back(24); formatAttribs.push_back(24);
formatAttribs.push_back(WGL_STENCIL_BITS_ARB); formatAttribs.push_back(WGL_STENCIL_BITS_ARB);
formatAttribs.push_back(8); formatAttribs.push_back(8);
#ifdef NATIVE_SRGB_FRAMEBUFFER #ifdef NATIVE_SRGB_FRAMEBUFFER
// formatAttribs.push_back(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB); // formatAttribs.push_back(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
// formatAttribs.push_back(GL_TRUE); // formatAttribs.push_back(GL_TRUE);
#endif #endif
// terminate the list // terminate the list
formatAttribs.push_back(0); formatAttribs.push_back(0);
UINT numFormats; UINT numFormats;
wglChoosePixelFormatARB(_hdc, &formatAttribs[0], NULL, 1, &pixelFormat, &numFormats); wglChoosePixelFormatARB(_hdc, &formatAttribs[0], NULL, 1, &pixelFormat, &numFormats);
DescribePixelFormat(_hdc, pixelFormat, sizeof(pfd), &pfd); DescribePixelFormat(_hdc, pixelFormat, sizeof(pfd), &pfd);
}
// The swap chain pixel size for swap chains is : rgba32 + depth24stencil8
// We don't apply the length of the swap chain into this pixelSize since it is not vsible for the Process (on windows).
_swapchainPixelSize = 32 + 32;
SetPixelFormat(_hdc, pixelFormat, &pfd);
{
std::vector<int> contextAttribs;
uint32_t majorVersion = _version >> 8;
uint32_t minorVersion = _version & 0xFF;
contextAttribs.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
contextAttribs.push_back(majorVersion);
contextAttribs.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
contextAttribs.push_back(minorVersion);
contextAttribs.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
#if defined(USE_GLES)
contextAttribs.push_back(WGL_CONTEXT_ES2_PROFILE_BIT_EXT);
#else
contextAttribs.push_back(WGL_CONTEXT_CORE_PROFILE_BIT_ARB);
#endif
contextAttribs.push_back(WGL_CONTEXT_FLAGS_ARB);
if (enableDebugLogger()) {
contextAttribs.push_back(WGL_CONTEXT_DEBUG_BIT_ARB);
} else {
contextAttribs.push_back(0);
}
contextAttribs.push_back(0);
HGLRC shareHglrc = (HGLRC)QOpenGLContextWrapper::nativeContext(shareContext);
_hglrc = wglCreateContextAttribsARB(_hdc, shareHglrc, &contextAttribs[0]);
}
if (0 != _hglrc) {
createWrapperContext();
}
}
if (0 == _hglrc) {
// fallback, if the context creation failed, or USE_CUSTOM_CONTEXT is false
qtCreate(shareContext);
} }
// The swap chain pixel size for swap chains is : rgba32 + depth24stencil8 #else
// We don't apply the length of the swap chain into this pixelSize since it is not vsible for the Process (on windows). // For platforms where we don't prefer custom context creation, always rely on the Qt context creation
_swapchainPixelSize = 32 + 32; qtCreate(shareContext);
#endif
updateSwapchainMemoryCounter(); updateSwapchainMemoryCounter();
SetPixelFormat(_hdc, pixelFormat, &pfd);
{
std::vector<int> contextAttribs;
uint32_t majorVersion = _version >> 8;
uint32_t minorVersion = _version & 0xFF;
contextAttribs.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
contextAttribs.push_back(majorVersion);
contextAttribs.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
contextAttribs.push_back(minorVersion);
contextAttribs.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
#if defined(USE_GLES)
contextAttribs.push_back(WGL_CONTEXT_ES2_PROFILE_BIT_EXT);
#else
contextAttribs.push_back(WGL_CONTEXT_CORE_PROFILE_BIT_ARB);
#endif
contextAttribs.push_back(WGL_CONTEXT_FLAGS_ARB);
if (enableDebugLogger()) {
contextAttribs.push_back(WGL_CONTEXT_DEBUG_BIT_ARB);
} else {
contextAttribs.push_back(0);
}
contextAttribs.push_back(0);
if (!shareContext) {
shareContext = qt_gl_global_share_context();
}
HGLRC shareHglrc = (HGLRC)QOpenGLContextWrapper::nativeContext(shareContext);
_hglrc = wglCreateContextAttribsARB(_hdc, shareHglrc, &contextAttribs[0]);
}
if (_hglrc == 0) {
throw std::runtime_error("Could not create GL context");
}
if (!makeCurrent()) { if (!makeCurrent()) {
throw std::runtime_error("Could not make context current"); qCWarning(glLogging) << "Could not make context current";
return;
} }
if (enableDebugLogger()) { if (enableDebugLogger()) {
glDebugMessageCallback(debugMessageCallback, NULL); setupDebugLogging(_qglContext);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
} }
doneCurrent(); doneCurrent();
} }
#endif
OffscreenContext::~OffscreenContext() { OffscreenContext::~OffscreenContext() {
_window->deleteLater(); _window->deleteLater();
} }

View file

@ -23,7 +23,8 @@ class QOpenGLContext;
class QThread; class QThread;
class QOpenGLDebugMessage; class QOpenGLDebugMessage;
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN) && defined(USE_GLES)
//#if defined(Q_OS_WIN)
#define GL_CUSTOM_CONTEXT #define GL_CUSTOM_CONTEXT
#endif #endif
namespace gl { namespace gl {
@ -33,18 +34,21 @@ namespace gl {
QWindow* _window { nullptr }; QWindow* _window { nullptr };
static void destroyContext(QOpenGLContext* context); static void destroyContext(QOpenGLContext* context);
#if defined(GL_CUSTOM_CONTEXT) #if defined(GL_CUSTOM_CONTEXT)
static bool USE_CUSTOM_CONTEXT;
uint32_t _version { 0x0401 }; uint32_t _version { 0x0401 };
HWND _hwnd { 0 }; HWND _hwnd { 0 };
HDC _hdc { 0 }; HDC _hdc { 0 };
HGLRC _hglrc { 0 }; HGLRC _hglrc { 0 };
static void destroyWin32Context(HGLRC hglrc);
QOpenGLContext* _wrappedContext { nullptr };
#else
QOpenGLContext* _context { nullptr };
#endif #endif
QOpenGLContext* _qglContext { nullptr };
private: private:
Context(const Context& other); Context(const Context& other);
void qtCreate(QOpenGLContext* shareContext);
#if defined(GL_CUSTOM_CONTEXT)
void createWrapperContext();
#endif
public: public:
static bool enableDebugLogger(); static bool enableDebugLogger();
@ -63,7 +67,7 @@ namespace gl {
void swapBuffers(); void swapBuffers();
void doneCurrent(); void doneCurrent();
virtual void create(QOpenGLContext* shareContext = nullptr); virtual void create(QOpenGLContext* shareContext = nullptr);
QOpenGLContext* qglContext(); QOpenGLContext* qglContext() const { return _qglContext; }
void moveToThread(QThread* thread); void moveToThread(QThread* thread);
static size_t evalSurfaceMemoryUsage(uint32_t width, uint32_t height, uint32_t pixelSize); static size_t evalSurfaceMemoryUsage(uint32_t width, uint32_t height, uint32_t pixelSize);

View file

@ -6,12 +6,15 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
// Note, `gl::Context is split into two files because a single file cannot include both the GLAD headers
// and the QOpenGLContext definition headers
#include "Context.h" #include "Context.h"
#include "Config.h" #include "Config.h"
#include <QtGui/QOpenGLContext>
#include <QtGui/QWindow> #include <QtGui/QWindow>
#include "QOpenGLContextWrapper.h"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <QtPlatformHeaders/QWGLNativeContext> #include <QtPlatformHeaders/QWGLNativeContext>
@ -24,29 +27,28 @@
using namespace gl; using namespace gl;
void Context::destroyContext(QOpenGLContext* context) { void Context::destroyContext(QOpenGLContext* context) {
delete context; context->deleteLater();
} }
void Context::makeCurrent(QOpenGLContext* context, QSurface* surface) { void Context::makeCurrent(QOpenGLContext* context, QSurface* surface) {
context->makeCurrent(surface); context->makeCurrent(surface);
} }
QOpenGLContext* Context::qglContext() { #if defined(GL_CUSTOM_CONTEXT)
#ifdef GL_CUSTOM_CONTEXT void Context::createWrapperContext() {
if (!_wrappedContext) { if (0 != _hglrc && nullptr == _qglContext) {
_wrappedContext = new QOpenGLContext(); _qglContext = new QOpenGLContext();
_wrappedContext->setNativeHandle(QVariant::fromValue(QWGLNativeContext(_hglrc, _hwnd))); _qglContext->setNativeHandle(QVariant::fromValue(QWGLNativeContext(_hglrc, _hwnd)));
_wrappedContext->create(); _qglContext->create();
} }
return _wrappedContext;
#else
return _context;
#endif
} }
#endif
void Context::moveToThread(QThread* thread) { void Context::moveToThread(QThread* thread) {
qglContext()->moveToThread(thread); if (_qglContext) {
_qglContext->moveToThread(thread);
}
} }
void Context::debugMessageHandler(const QOpenGLDebugMessage& debugMessage) { void Context::debugMessageHandler(const QOpenGLDebugMessage& debugMessage) {
@ -75,47 +77,36 @@ void Context::setupDebugLogging(QOpenGLContext *context) {
} }
} }
#ifndef GL_CUSTOM_CONTEXT
bool Context::makeCurrent() { bool Context::makeCurrent() {
updateSwapchainMemoryCounter(); updateSwapchainMemoryCounter();
bool result = _context->makeCurrent(_window); bool result = _qglContext->makeCurrent(_window);
gl::initModuleGl(); gl::initModuleGl();
return result; return result;
} }
void Context::swapBuffers() { void Context::swapBuffers() {
_context->swapBuffers(_window); qglContext()->swapBuffers(_window);
} }
void Context::doneCurrent() { void Context::doneCurrent() {
if (_context) { if (_qglContext) {
_context->doneCurrent(); _qglContext->doneCurrent();
} }
} }
Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context();
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat(); const QSurfaceFormat& getDefaultOpenGLSurfaceFormat();
void Context::create(QOpenGLContext* shareContext) { void Context::qtCreate(QOpenGLContext* shareContext) {
_context = new QOpenGLContext(); _qglContext = new QOpenGLContext();
_context->setFormat(_window->format()); _qglContext->setFormat(_window->format());
if (!shareContext) { if (!shareContext) {
shareContext = qt_gl_global_share_context(); shareContext = qt_gl_global_share_context();
} }
_context->setShareContext(shareContext); if (shareContext) {
_context->create(); _qglContext->setShareContext(shareContext);
_swapchainPixelSize = evalGLFormatSwapchainPixelSize(_context->format());
updateSwapchainMemoryCounter();
if (!makeCurrent()) {
throw std::runtime_error("Could not make context current");
} }
if (enableDebugLogger()) { _qglContext->create();
setupDebugLogging(_context); _swapchainPixelSize = evalGLFormatSwapchainPixelSize(_qglContext->format());
}
doneCurrent();
} }
#endif