diff --git a/libraries/gl/src/gl/Context.cpp b/libraries/gl/src/gl/Context.cpp index d4ecbaa5ba..7b92548916 100644 --- a/libraries/gl/src/gl/Context.cpp +++ b/libraries/gl/src/gl/Context.cpp @@ -29,6 +29,9 @@ using namespace gl; +#if defined(GL_CUSTOM_CONTEXT) +bool Context::USE_CUSTOM_CONTEXT { true }; +#endif bool Context::enableDebugLogger() { #if defined(Q_OS_MAC) @@ -75,24 +78,24 @@ Context::Context(QWindow* window) { void Context::release() { doneCurrent(); -#ifdef GL_CUSTOM_CONTEXT - if (_wrappedContext) { - destroyContext(_wrappedContext); - _wrappedContext = nullptr; + if (_qglContext) { + destroyContext(_qglContext); + _qglContext = nullptr; } + +#ifdef GL_CUSTOM_CONTEXT if (_hglrc) { - destroyWin32Context(_hglrc); + wglDeleteContext(_hglrc); _hglrc = 0; } + if (_hdc) { ReleaseDC(_hwnd, _hdc); _hdc = 0; } _hwnd = 0; -#else - destroyContext(_context); - _context = nullptr; #endif + _window = nullptr; updateSwapchainMemoryCounter(); } @@ -135,15 +138,6 @@ void Context::clear() { #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) { // FIXME build the PFD based on the 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 #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 #define WGL_DRAW_TO_WINDOW_ARB 0x2001 @@ -229,9 +203,17 @@ typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShare GLAPI PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; GLAPI PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; +#endif + + Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); void Context::create(QOpenGLContext* shareContext) { + if (!shareContext) { + shareContext = qt_gl_global_share_context(); + } + +#if defined(GL_CUSTOM_CONTEXT) assert(0 != _hwnd); assert(0 == _hdc); auto hwnd = _hwnd; @@ -250,104 +232,114 @@ void Context::create(QOpenGLContext* shareContext) { wglMakeCurrent(0, 0); wglDeleteContext(glrc); ReleaseDC(hwnd, hdc); + if (!wglChoosePixelFormatARB || !wglCreateContextAttribsARB) { + USE_CUSTOM_CONTEXT = false; + } }); - _hdc = GetDC(_hwnd); + if (USE_CUSTOM_CONTEXT) { + _hdc = GetDC(_hwnd); #if defined(USE_GLES) - _version = 0x0200; + _version = 0x0302; #else - if (gl::disableGl45()) { - _version = 0x0401; - } else if (GLAD_GL_VERSION_4_5) { - _version = 0x0405; - } else if (GLAD_GL_VERSION_4_3) { - _version = 0x0403; - } else { - _version = 0x0401; - } + if (gl::disableGl45()) { + _version = 0x0401; + } else if (GLAD_GL_VERSION_4_5) { + _version = 0x0405; + } else if (GLAD_GL_VERSION_4_3) { + _version = 0x0403; + } else { + _version = 0x0401; + } #endif - static int pixelFormat = 0; - static PIXELFORMATDESCRIPTOR pfd; - if (!pixelFormat) { - memset(&pfd, 0, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - std::vector formatAttribs; - formatAttribs.push_back(WGL_DRAW_TO_WINDOW_ARB); - formatAttribs.push_back(GL_TRUE); - formatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB); - formatAttribs.push_back(GL_TRUE); - formatAttribs.push_back(WGL_DOUBLE_BUFFER_ARB); - formatAttribs.push_back(GL_TRUE); - formatAttribs.push_back(WGL_PIXEL_TYPE_ARB); - formatAttribs.push_back(WGL_TYPE_RGBA_ARB); - formatAttribs.push_back(WGL_COLOR_BITS_ARB); - formatAttribs.push_back(32); - formatAttribs.push_back(WGL_DEPTH_BITS_ARB); - formatAttribs.push_back(24); - formatAttribs.push_back(WGL_STENCIL_BITS_ARB); - formatAttribs.push_back(8); + static int pixelFormat = 0; + static PIXELFORMATDESCRIPTOR pfd; + if (!pixelFormat) { + memset(&pfd, 0, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + std::vector formatAttribs; + formatAttribs.push_back(WGL_DRAW_TO_WINDOW_ARB); + formatAttribs.push_back(GL_TRUE); + formatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB); + formatAttribs.push_back(GL_TRUE); + formatAttribs.push_back(WGL_DOUBLE_BUFFER_ARB); + formatAttribs.push_back(GL_TRUE); + formatAttribs.push_back(WGL_PIXEL_TYPE_ARB); + formatAttribs.push_back(WGL_TYPE_RGBA_ARB); + formatAttribs.push_back(WGL_COLOR_BITS_ARB); + formatAttribs.push_back(32); + formatAttribs.push_back(WGL_DEPTH_BITS_ARB); + formatAttribs.push_back(24); + formatAttribs.push_back(WGL_STENCIL_BITS_ARB); + formatAttribs.push_back(8); #ifdef NATIVE_SRGB_FRAMEBUFFER - // formatAttribs.push_back(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB); - // formatAttribs.push_back(GL_TRUE); + // formatAttribs.push_back(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB); + // formatAttribs.push_back(GL_TRUE); #endif - // terminate the list - formatAttribs.push_back(0); - UINT numFormats; - wglChoosePixelFormatARB(_hdc, &formatAttribs[0], NULL, 1, &pixelFormat, &numFormats); - DescribePixelFormat(_hdc, pixelFormat, sizeof(pfd), &pfd); + // terminate the list + formatAttribs.push_back(0); + UINT numFormats; + wglChoosePixelFormatARB(_hdc, &formatAttribs[0], NULL, 1, &pixelFormat, &numFormats); + 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 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 - // 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; +#else + // For platforms where we don't prefer custom context creation, always rely on the Qt context creation + qtCreate(shareContext); +#endif + updateSwapchainMemoryCounter(); - SetPixelFormat(_hdc, pixelFormat, &pfd); - { - std::vector 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()) { - throw std::runtime_error("Could not make context current"); + qCWarning(glLogging) << "Could not make context current"; + return; } if (enableDebugLogger()) { - glDebugMessageCallback(debugMessageCallback, NULL); - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + setupDebugLogging(_qglContext); } doneCurrent(); } -#endif - OffscreenContext::~OffscreenContext() { _window->deleteLater(); } diff --git a/libraries/gl/src/gl/Context.h b/libraries/gl/src/gl/Context.h index 05cb361725..bab9156010 100644 --- a/libraries/gl/src/gl/Context.h +++ b/libraries/gl/src/gl/Context.h @@ -23,7 +23,8 @@ class QOpenGLContext; class QThread; class QOpenGLDebugMessage; -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) && defined(USE_GLES) +//#if defined(Q_OS_WIN) #define GL_CUSTOM_CONTEXT #endif namespace gl { @@ -33,18 +34,21 @@ namespace gl { QWindow* _window { nullptr }; static void destroyContext(QOpenGLContext* context); #if defined(GL_CUSTOM_CONTEXT) + static bool USE_CUSTOM_CONTEXT; + uint32_t _version { 0x0401 }; HWND _hwnd { 0 }; HDC _hdc { 0 }; HGLRC _hglrc { 0 }; - static void destroyWin32Context(HGLRC hglrc); - QOpenGLContext* _wrappedContext { nullptr }; -#else - QOpenGLContext* _context { nullptr }; #endif + QOpenGLContext* _qglContext { nullptr }; private: Context(const Context& other); + void qtCreate(QOpenGLContext* shareContext); +#if defined(GL_CUSTOM_CONTEXT) + void createWrapperContext(); +#endif public: static bool enableDebugLogger(); @@ -63,7 +67,7 @@ namespace gl { void swapBuffers(); void doneCurrent(); virtual void create(QOpenGLContext* shareContext = nullptr); - QOpenGLContext* qglContext(); + QOpenGLContext* qglContext() const { return _qglContext; } void moveToThread(QThread* thread); static size_t evalSurfaceMemoryUsage(uint32_t width, uint32_t height, uint32_t pixelSize); diff --git a/libraries/gl/src/gl/ContextQt.cpp b/libraries/gl/src/gl/ContextQt.cpp index f554877b2a..b6b6ad3596 100644 --- a/libraries/gl/src/gl/ContextQt.cpp +++ b/libraries/gl/src/gl/ContextQt.cpp @@ -6,12 +6,15 @@ // 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 "Config.h" -#include #include +#include "QOpenGLContextWrapper.h" #ifdef Q_OS_WIN #include @@ -24,29 +27,28 @@ using namespace gl; void Context::destroyContext(QOpenGLContext* context) { - delete context; + context->deleteLater(); } void Context::makeCurrent(QOpenGLContext* context, QSurface* surface) { context->makeCurrent(surface); } -QOpenGLContext* Context::qglContext() { -#ifdef GL_CUSTOM_CONTEXT - if (!_wrappedContext) { - _wrappedContext = new QOpenGLContext(); - _wrappedContext->setNativeHandle(QVariant::fromValue(QWGLNativeContext(_hglrc, _hwnd))); - _wrappedContext->create(); +#if defined(GL_CUSTOM_CONTEXT) +void Context::createWrapperContext() { + if (0 != _hglrc && nullptr == _qglContext) { + _qglContext = new QOpenGLContext(); + _qglContext->setNativeHandle(QVariant::fromValue(QWGLNativeContext(_hglrc, _hwnd))); + _qglContext->create(); } - return _wrappedContext; -#else - - return _context; -#endif } +#endif + void Context::moveToThread(QThread* thread) { - qglContext()->moveToThread(thread); + if (_qglContext) { + _qglContext->moveToThread(thread); + } } void Context::debugMessageHandler(const QOpenGLDebugMessage& debugMessage) { @@ -75,47 +77,36 @@ void Context::setupDebugLogging(QOpenGLContext *context) { } } -#ifndef GL_CUSTOM_CONTEXT bool Context::makeCurrent() { updateSwapchainMemoryCounter(); - bool result = _context->makeCurrent(_window); + bool result = _qglContext->makeCurrent(_window); gl::initModuleGl(); return result; } void Context::swapBuffers() { - _context->swapBuffers(_window); + qglContext()->swapBuffers(_window); } void Context::doneCurrent() { - if (_context) { - _context->doneCurrent(); + if (_qglContext) { + _qglContext->doneCurrent(); } } Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); const QSurfaceFormat& getDefaultOpenGLSurfaceFormat(); -void Context::create(QOpenGLContext* shareContext) { - _context = new QOpenGLContext(); - _context->setFormat(_window->format()); +void Context::qtCreate(QOpenGLContext* shareContext) { + _qglContext = new QOpenGLContext(); + _qglContext->setFormat(_window->format()); if (!shareContext) { shareContext = qt_gl_global_share_context(); } - _context->setShareContext(shareContext); - _context->create(); - _swapchainPixelSize = evalGLFormatSwapchainPixelSize(_context->format()); - updateSwapchainMemoryCounter(); - - if (!makeCurrent()) { - throw std::runtime_error("Could not make context current"); + if (shareContext) { + _qglContext->setShareContext(shareContext); } - if (enableDebugLogger()) { - setupDebugLogging(_context); - } - doneCurrent(); - + _qglContext->create(); + _swapchainPixelSize = evalGLFormatSwapchainPixelSize(_qglContext->format()); } - -#endif