From e7056a8969cf9445ff84c7362137f792ef207ae2 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 23 Jun 2014 16:45:11 +0200 Subject: Add context adoption support for WGL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is trickier than the GLX and EGL implementations due to the way pixel formats, windows and contexts work. Apart from some restrictions, it should be fully functional nonetheless. Add also some proper documentation. Change-Id: Ia6e3eb1ab2701e439b8621b9092c2b0934ff2151 Reviewed-by: Jørgen Lind --- .../platforms/windows/qwindowsglcontext.cpp | 82 ++++++++++++++++++---- src/plugins/platforms/windows/qwindowsglcontext.h | 2 + 2 files changed, 72 insertions(+), 12 deletions(-) (limited to 'src/plugins/platforms/windows') diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index b1152de854..e336c6414e 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include @@ -1038,11 +1039,54 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, m_renderingContext(0), m_pixelFormat(0), m_extensionsUsed(false), - m_swapInterval(-1) + m_swapInterval(-1), + m_ownsContext(true) { if (!m_staticContext) // Something went very wrong. Stop here, isValid() will return false. return; + QVariant nativeHandle = context->nativeHandle(); + if (!nativeHandle.isNull()) { + // Adopt and existing context. + if (!nativeHandle.canConvert()) { + qWarning("QWindowsGLContext: Requires a QWGLNativeContext"); + return; + } + QWGLNativeContext handle = nativeHandle.value(); + HGLRC wglcontext = handle.context(); + HWND wnd = handle.window(); + if (!wglcontext || !wnd) { + qWarning("QWindowsGLContext: No context and window given"); + return; + } + + HDC dc = GetDC(wnd); + // A window with an associated pixel format is mandatory. + // When no SetPixelFormat() call has been made, the following will fail. + m_pixelFormat = GetPixelFormat(dc); + bool ok = m_pixelFormat != 0; + if (!ok) + qWarning("QWindowsGLContext: Failed to get pixel format"); + ok = DescribePixelFormat(dc, m_pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &m_obtainedPixelFormatDescriptor); + if (!ok) { + qWarning("QWindowsGLContext: Failed to describe pixel format"); + } else { + QWindowsOpenGLAdditionalFormat obtainedAdditional; + m_obtainedFormat = GDI::qSurfaceFormatFromPixelFormat(m_obtainedPixelFormatDescriptor, &obtainedAdditional); + m_renderingContext = wglcontext; + ok = updateObtainedParams(dc); + } + + ReleaseDC(wnd, dc); + + if (ok) + m_ownsContext = false; + else + m_renderingContext = 0; + + return; + } + QSurfaceFormat format = context->format(); if (format.renderableType() == QSurfaceFormat::DefaultRenderableType) format.setRenderableType(QSurfaceFormat::OpenGL); @@ -1065,7 +1109,7 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, HWND dummyWindow = 0; HDC hdc = 0; bool tryExtensions = false; - int obtainedSwapInternal = -1; + int obtainedSwapInterval = -1; do { dummyWindow = createDummyGLWindow(); if (!dummyWindow) @@ -1131,18 +1175,16 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, } // Query obtained parameters and apply swap interval. - if (!QOpenGLStaticContext::opengl32.wglMakeCurrent(hdc, m_renderingContext)) { - qWarning("Failed to make context current."); + if (!updateObtainedParams(hdc, &obtainedSwapInterval)) break; - } - QWindowsOpenGLContextFormat::current().apply(&m_obtainedFormat); + } while (false); - if (m_staticContext->wglGetSwapInternalExt) - obtainedSwapInternal = m_staticContext->wglGetSwapInternalExt(); + // Make the HGLRC retrievable via QOpenGLContext::nativeHandle(). + // Do not provide the window since it is the dummy one and it is about to disappear. + if (m_renderingContext) + context->setNativeHandle(QVariant::fromValue(QWGLNativeContext(m_renderingContext, 0))); - QOpenGLStaticContext::opengl32.wglMakeCurrent(0, 0); - } while (false); if (hdc) ReleaseDC(dummyWindow, hdc); if (dummyWindow) @@ -1151,18 +1193,34 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, qCDebug(lcQpaGl) << __FUNCTION__ << this << (tryExtensions ? "ARB" : "GDI") << " requested: " << context->format() << "\n obtained #" << m_pixelFormat << (m_extensionsUsed ? "ARB" : "GDI") << m_obtainedFormat - << "\n " << m_obtainedPixelFormatDescriptor << " swap interval: " << obtainedSwapInternal + << "\n " << m_obtainedPixelFormatDescriptor << " swap interval: " << obtainedSwapInterval << "\n default: " << m_staticContext->defaultFormat << "\n HGLRC=" << m_renderingContext; } QWindowsGLContext::~QWindowsGLContext() { - if (m_renderingContext) + if (m_renderingContext && m_ownsContext) QOpenGLStaticContext::opengl32.wglDeleteContext(m_renderingContext); releaseDCs(); } +bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval) +{ + if (!QOpenGLStaticContext::opengl32.wglMakeCurrent(hdc, m_renderingContext)) { + qWarning("Failed to make context current."); + return false; + } + + QWindowsOpenGLContextFormat::current().apply(&m_obtainedFormat); + + if (m_staticContext->wglGetSwapInternalExt && obtainedSwapInterval) + *obtainedSwapInterval = m_staticContext->wglGetSwapInternalExt(); + + QOpenGLStaticContext::opengl32.wglMakeCurrent(0, 0); + return true; +} + void QWindowsGLContext::releaseDCs() { const QOpenGLContextData *end = m_windowContexts.end(); diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h index dcc31c6197..d92d94aa1a 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.h +++ b/src/plugins/platforms/windows/qwindowsglcontext.h @@ -258,6 +258,7 @@ public: private: inline void releaseDCs(); + bool updateObtainedParams(HDC hdc, int *obtainedSwapInterval = 0); QOpenGLStaticContext *m_staticContext; QOpenGLContext *m_context; @@ -268,6 +269,7 @@ private: int m_pixelFormat; bool m_extensionsUsed; int m_swapInterval; + bool m_ownsContext; }; QT_END_NAMESPACE -- cgit v1.2.3