9#include <QtCore/qdebug.h>
10#include <QtCore/qsysinfo.h>
11#include <QtGui/qcolorspace.h>
12#include <QtGui/qguiapplication.h>
13#include <qpa/qplatformnativeinterface.h>
14#include <private/qsystemlibrary_p.h>
23#ifndef WGL_ARB_multisample
24#define WGL_SAMPLE_BUFFERS_ARB 0x2041
25#define WGL_SAMPLES_ARB 0x2042
28#ifndef WGL_ARB_pixel_format
29#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
30#define WGL_DRAW_TO_WINDOW_ARB 0x2001
31#define WGL_DRAW_TO_BITMAP_ARB 0x2002
32#define WGL_ACCELERATION_ARB 0x2003
33#define WGL_NEED_PALETTE_ARB 0x2004
34#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
35#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
36#define WGL_SWAP_METHOD_ARB 0x2007
37#define WGL_NUMBER_OVERLAYS_ARB 0x2008
38#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
39#define WGL_TRANSPARENT_ARB 0x200A
40#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
41#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
42#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
43#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
44#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
45#define WGL_SHARE_DEPTH_ARB 0x200C
46#define WGL_SHARE_STENCIL_ARB 0x200D
47#define WGL_SHARE_ACCUM_ARB 0x200E
48#define WGL_SUPPORT_GDI_ARB 0x200F
49#define WGL_SUPPORT_OPENGL_ARB 0x2010
50#define WGL_DOUBLE_BUFFER_ARB 0x2011
51#define WGL_STEREO_ARB 0x2012
52#define WGL_PIXEL_TYPE_ARB 0x2013
53#define WGL_COLOR_BITS_ARB 0x2014
54#define WGL_RED_BITS_ARB 0x2015
55#define WGL_RED_SHIFT_ARB 0x2016
56#define WGL_GREEN_BITS_ARB 0x2017
57#define WGL_GREEN_SHIFT_ARB 0x2018
58#define WGL_BLUE_BITS_ARB 0x2019
59#define WGL_BLUE_SHIFT_ARB 0x201A
60#define WGL_ALPHA_BITS_ARB 0x201B
61#define WGL_ALPHA_SHIFT_ARB 0x201C
62#define WGL_ACCUM_BITS_ARB 0x201D
63#define WGL_ACCUM_RED_BITS_ARB 0x201E
64#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
65#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
66#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
67#define WGL_DEPTH_BITS_ARB 0x2022
68#define WGL_STENCIL_BITS_ARB 0x2023
69#define WGL_AUX_BUFFERS_ARB 0x2024
70#define WGL_NO_ACCELERATION_ARB 0x2025
71#define WGL_GENERIC_ACCELERATION_ARB 0x2026
72#define WGL_FULL_ACCELERATION_ARB 0x2027
73#define WGL_SWAP_EXCHANGE_ARB 0x2028
74#define WGL_SWAP_COPY_ARB 0x2029
75#define WGL_SWAP_UNDEFINED_ARB 0x202A
76#define WGL_TYPE_RGBA_ARB 0x202B
77#define WGL_TYPE_COLORINDEX_ARB 0x202C
80#ifndef WGL_ARB_create_context
81#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
82#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
83#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
84#define WGL_CONTEXT_FLAGS_ARB 0x2094
85#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
86#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
87#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
88#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x0001
89#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x0002
91#define ERROR_INVALID_VERSION_ARB 0x2095
92#define ERROR_INVALID_PROFILE_ARB 0x2096
96#define GL_CONTEXT_PROFILE_MASK 0x9126
97#define GL_MAJOR_VERSION 0x821B
98#define GL_MINOR_VERSION 0x821C
99#define GL_NUM_EXTENSIONS 0x821D
100#define GL_CONTEXT_FLAGS 0x821E
101#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
105#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
109#define RESET_NOTIFICATION_STRATEGY_ARB 0x8256
110#define LOSE_CONTEXT_ON_RESET_ARB 0x8252
112#ifndef WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT
113#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9
118QWindowsOpengl32DLL QOpenGLStaticContext::opengl32;
123 ?
reinterpret_cast<QFunctionPointer>(::GetProcAddress(m_lib, name))
129 const QByteArray opengl32 = QByteArrayLiteral(
"opengl32");
130 const QByteArray swopengl = QByteArrayLiteral(
"opengl32sw");
131 bool useSystemLib =
false;
133 QByteArray openglDll = qgetenv(
"QT_OPENGL_DLL");
134 if (openglDll.isEmpty()) {
135 openglDll = softwareRendering ? swopengl : opengl32;
136 useSystemLib = !softwareRendering;
139 openglDll = openglDll.toLower();
140 m_nonOpengl32 = openglDll != opengl32;
142 qCDebug(lcQpaGl) <<
"Qt: Using WGL and OpenGL from" << openglDll;
145 m_lib = QSystemLibrary::load((
wchar_t*)(QString::fromLatin1(openglDll).utf16()));
147 m_lib = LoadLibraryA(openglDll.constData());
149 qErrnoWarning(::GetLastError(),
"Failed to load %s", openglDll.constData());
157 QSystemLibrary::load(L"opengl32");
160 wglCreateContext =
reinterpret_cast<HGLRC (WINAPI *)(HDC)>(resolve(
"wglCreateContext"));
161 wglDeleteContext =
reinterpret_cast<BOOL (WINAPI *)(HGLRC)>(resolve(
"wglDeleteContext"));
162 wglGetCurrentContext =
reinterpret_cast<HGLRC (WINAPI *)()>(resolve(
"wglGetCurrentContext"));
163 wglGetCurrentDC =
reinterpret_cast<HDC (WINAPI *)()>(resolve(
"wglGetCurrentDC"));
164 wglGetProcAddress =
reinterpret_cast<PROC (WINAPI *)(LPCSTR)>(resolve(
"wglGetProcAddress"));
165 wglMakeCurrent =
reinterpret_cast<BOOL (WINAPI *)(HDC, HGLRC)>(resolve(
"wglMakeCurrent"));
166 wglShareLists =
reinterpret_cast<BOOL (WINAPI *)(HGLRC, HGLRC)>(resolve(
"wglShareLists"));
167 wglSwapBuffers =
reinterpret_cast<BOOL (WINAPI *)(HDC)>(resolve(
"wglSwapBuffers"));
168 wglSetPixelFormat =
reinterpret_cast<BOOL (WINAPI *)(HDC,
int,
const PIXELFORMATDESCRIPTOR *)>(resolve(
"wglSetPixelFormat"));
169 wglDescribePixelFormat =
reinterpret_cast<
int (WINAPI *)(HDC,
int, UINT, PIXELFORMATDESCRIPTOR *)>(resolve(
"wglDescribePixelFormat"));
171 glGetError =
reinterpret_cast<GLenum (
APIENTRY *)()>(resolve(
"glGetError"));
172 glGetIntegerv =
reinterpret_cast<
void (
APIENTRY *)(GLenum , GLint *)>(resolve(
"glGetIntegerv"));
173 glGetString =
reinterpret_cast<
const GLubyte * (
APIENTRY *)(GLenum )>(resolve(
"glGetString"));
175 return wglCreateContext && glGetError && glGetString;
190 return moduleIsNotOpengl32() ? wglDescribePixelFormat(dc, pf, size, pfd) : DescribePixelFormat(dc, pf, size, pfd);
203template <
class MaskType,
class FlagType>
inline bool testFlag(MaskType mask, FlagType flag)
205 return (mask & MaskType(flag)) != 0;
209{
return (pd.bReserved & 0x0f) != 0; }
212{
return (pfd.dwFlags & PFD_GENERIC_ACCELERATED) || !(pfd.dwFlags & PFD_GENERIC_FORMAT); }
216 memset(d, 0,
sizeof(PIXELFORMATDESCRIPTOR));
217 d->nSize =
sizeof(PIXELFORMATDESCRIPTOR);
221#ifndef QT_NO_DEBUG_STREAM
222QDebug operator<<(QDebug d,
const PIXELFORMATDESCRIPTOR &pd)
224 QDebugStateSaver saver(d);
226 d <<
"PIXELFORMATDESCRIPTOR "
227 <<
"dwFlags=" << Qt::hex << Qt::showbase << pd.dwFlags << Qt::dec << Qt::noshowbase;
228 if (pd.dwFlags & PFD_DRAW_TO_WINDOW) d <<
" PFD_DRAW_TO_WINDOW";
229 if (pd.dwFlags & PFD_DRAW_TO_BITMAP) d <<
" PFD_DRAW_TO_BITMAP";
230 if (pd.dwFlags & PFD_SUPPORT_GDI) d <<
" PFD_SUPPORT_GDI";
231 if (pd.dwFlags & PFD_SUPPORT_OPENGL) d <<
" PFD_SUPPORT_OPENGL";
232 if (pd.dwFlags & PFD_GENERIC_ACCELERATED) d <<
" PFD_GENERIC_ACCELERATED";
233 if (pd.dwFlags & PFD_SUPPORT_DIRECTDRAW) d <<
" PFD_SUPPORT_DIRECTDRAW";
234 if (pd.dwFlags & PFD_DIRECT3D_ACCELERATED) d <<
" PFD_DIRECT3D_ACCELERATED";
235 if (pd.dwFlags & PFD_SUPPORT_COMPOSITION) d <<
" PFD_SUPPORT_COMPOSITION";
236 if (pd.dwFlags & PFD_GENERIC_FORMAT) d <<
" PFD_GENERIC_FORMAT";
237 if (pd.dwFlags & PFD_NEED_PALETTE) d <<
" PFD_NEED_PALETTE";
238 if (pd.dwFlags & PFD_NEED_SYSTEM_PALETTE) d <<
" PFD_NEED_SYSTEM_PALETTE";
239 if (pd.dwFlags & PFD_DOUBLEBUFFER) d <<
" PFD_DOUBLEBUFFER";
240 if (pd.dwFlags & PFD_STEREO) d <<
" PFD_STEREO";
241 if (pd.dwFlags & PFD_SWAP_LAYER_BUFFERS) d <<
" PFD_SWAP_LAYER_BUFFERS";
242 if (hasGLOverlay(pd)) d <<
" overlay";
243 d <<
" iPixelType=" << pd.iPixelType <<
" cColorBits=" << pd.cColorBits
244 <<
" cRedBits=" << pd.cRedBits <<
" cRedShift=" << pd.cRedShift
245 <<
" cGreenBits=" << pd.cGreenBits <<
" cGreenShift=" << pd.cGreenShift
246 <<
" cBlueBits=" << pd.cBlueBits <<
" cBlueShift=" << pd.cBlueShift;
247 d <<
" cDepthBits=" << pd.cDepthBits;
249 d <<
" cStencilBits=" << pd.cStencilBits;
251 d <<
" cAuxBuffers=" << pd.cAuxBuffers;
252 d <<
" iLayerType=" << pd.iLayerType;
253 if (pd.dwVisibleMask)
254 d <<
" dwVisibleMask=" << pd.dwVisibleMask;
256 d <<
" cAlphaBits=" << pd.cAlphaBits <<
" cAlphaShift=" << pd.cAlphaShift;
258 d <<
" cAccumBits=" << pd.cAccumBits <<
" cAccumRedBits=" << pd.cAccumRedBits
259 <<
" cAccumGreenBits=" << pd.cAccumGreenBits <<
" cAccumBlueBits=" << pd.cAccumBlueBits
260 <<
" cAccumAlphaBits=" << pd.cAccumAlphaBits;
266 QDebugStateSaver saver(d);
268 d <<
"OpenGL: " << s.vendor <<
',' << s.renderer <<
" default "
271 d <<
",SampleBuffers";
273 d <<
", Extension-API present";
274 d <<
"\nExtensions: " << (s.extensionNames.count(
' ') + 1);
276 d << s.extensionNames;
282 QDebugStateSaver saver(d);
285 <<
" profile: " << f.profile <<
" options: " << f.options;
293 const PIXELFORMATDESCRIPTOR &pfd,
294 bool ignoreGLSupport =
false)
297 const bool pixmapOk = !pixmapRequested || testFlag(pfd.dwFlags, PFD_DRAW_TO_BITMAP);
298 const bool colorOk = !pixmapRequested || pfd.cColorBits == additional
.pixmapDepth;
299 const bool glOk = ignoreGLSupport || testFlag(pfd.dwFlags, PFD_SUPPORT_OPENGL);
300 const bool overlayOk = hasGLOverlay(pfd) == testFlag(additional.formatFlags, QWindowsGLOverlay);
301 return pixmapOk && glOk && overlayOk && colorOk;
307 for (
int i = 1; i <= pfiMax; i++) {
308 PIXELFORMATDESCRIPTOR pfd;
309 initPixelFormatDescriptor(&pfd);
310 QOpenGLStaticContext::opengl32.describePixelFormat(hdc, i,
sizeof(PIXELFORMATDESCRIPTOR), &pfd);
311 qCDebug(lcQpaGl) <<
'#' << i <<
'/' << pfiMax <<
':' << pfd;
321 QSurfaceFormat format;
322 format.setRenderableType(QSurfaceFormat::OpenGL);
323 if (pfd.dwFlags & PFD_DOUBLEBUFFER)
324 format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
325 format.setDepthBufferSize(pfd.cDepthBits);
327 if (pfd.iPixelType == PFD_TYPE_RGBA)
328 format.setAlphaBufferSize(pfd.cAlphaBits);
329 format.setRedBufferSize(pfd.cRedBits);
330 format.setGreenBufferSize(pfd.cGreenBits);
331 format.setBlueBufferSize(pfd.cBlueBits);
332 format.setStencilBufferSize(pfd.cStencilBits);
333 format.setStereo(pfd.dwFlags & PFD_STEREO);
336 if (isDirectRendering(pfd))
338 if (hasGLOverlay(pfd))
340 if (pfd.cAccumRedBits)
342 if (testFlag(pfd.dwFlags, PFD_DRAW_TO_BITMAP)) {
346 *additionalIn = additional;
355 PIXELFORMATDESCRIPTOR pfd;
356 initPixelFormatDescriptor(&pfd);
357 pfd.iPixelType = PFD_TYPE_RGBA;
358 pfd.iLayerType = PFD_MAIN_PLANE;
359 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_SUPPORT_COMPOSITION;
361 pfd.dwFlags |= isPixmap ? PFD_DRAW_TO_BITMAP : PFD_DRAW_TO_WINDOW;
362 if (!(additional.formatFlags & QWindowsGLDirectRendering))
363 pfd.dwFlags |= PFD_GENERIC_FORMAT;
366 pfd.dwFlags |= PFD_STEREO;
367 if (format.swapBehavior() != QSurfaceFormat::SingleBuffer && !isPixmap)
368 pfd.dwFlags |= PFD_DOUBLEBUFFER;
370 format.depthBufferSize() >= 0 ? format.depthBufferSize() : 32;
371 const int redBufferSize = format.redBufferSize();
372 if (redBufferSize != -1)
373 pfd.cRedBits = BYTE(redBufferSize);
374 const int greenBufferSize = format.greenBufferSize();
375 if (greenBufferSize != -1)
376 pfd.cGreenBits = BYTE(greenBufferSize);
377 const int blueBufferSize = format.blueBufferSize();
378 if (blueBufferSize != -1)
379 pfd.cBlueBits = BYTE(blueBufferSize);
380 pfd.cAlphaBits = format.alphaBufferSize() > 0 ? format.alphaBufferSize() : 8;
381 pfd.cStencilBits = format.stencilBufferSize() > 0 ? format.stencilBufferSize() : 8;
383 pfd.cAccumRedBits = pfd.cAccumGreenBits = pfd.cAccumBlueBits = pfd.cAccumAlphaBits = 16;
404 PIXELFORMATDESCRIPTOR *obtainedPfd)
407 qWarning(
"Attempted to use GDI functions with a non-opengl32.dll library");
412 PIXELFORMATDESCRIPTOR requestedPfd = qPixelFormatFromSurfaceFormat(format, QWindowsGLDirectRendering);
413 initPixelFormatDescriptor(obtainedPfd);
414 int pixelFormat = ChoosePixelFormat(hdc, &requestedPfd);
415 if (pixelFormat >= 0) {
416 DescribePixelFormat(hdc, pixelFormat,
sizeof(PIXELFORMATDESCRIPTOR), obtainedPfd);
417 if (isAcceptableFormat(additional, *obtainedPfd))
421 const int pfiMax = DescribePixelFormat(hdc, 0, 0,
nullptr);
424 const bool stereoRequested = format.stereo();
426 const bool doubleBufferRequested = format.swapBehavior() == QSurfaceFormat::DoubleBuffer;
428 for (
int pfi = 1; pfi <= pfiMax; pfi++) {
429 PIXELFORMATDESCRIPTOR checkPfd;
430 initPixelFormatDescriptor(&checkPfd);
431 DescribePixelFormat(hdc, pfi,
sizeof(PIXELFORMATDESCRIPTOR), &checkPfd);
432 if (isAcceptableFormat(additional, checkPfd)) {
433 int score = checkPfd.cColorBits + checkPfd.cAlphaBits + checkPfd.cStencilBits;
434 if (accumBufferRequested)
435 score += checkPfd.cAccumBits;
436 if (doubleBufferRequested == testFlag(checkPfd.dwFlags, PFD_DOUBLEBUFFER))
438 if (stereoRequested == testFlag(checkPfd.dwFlags, PFD_STEREO))
440 if (directRenderingRequested == isDirectRendering(checkPfd))
442 if (checkPfd.iPixelType == PFD_TYPE_RGBA)
444 if (score > bestScore) {
447 *obtainedPfd = checkPfd;
449 qCDebug(lcQpaGl) <<
__FUNCTION__ <<
" checking " << pfi <<
'/' << pfiMax
450 <<
" score=" << score <<
" (best " << bestPfi <<
'/' << bestScore <<
") " << checkPfd;
454 pixelFormat = bestPfi;
462 qErrnoWarning(
"%s: wglCreateContext failed.",
__FUNCTION__);
466 qErrnoWarning(
"%s: wglShareLists() failed.",
__FUNCTION__);
476 const QSurfaceFormat &format,
478 PIXELFORMATDESCRIPTOR *obtainedPfd)
480 enum { attribSize = 42 };
484 int iAttributes[attribSize];
485 std::fill(iAttributes, iAttributes + attribSize,
int(0));
491 iAttributes[i++] = TRUE;
493 iAttributes[i++] = TRUE;
496 iAttributes[i++] = (format.redBufferSize() > 0)
497 && (format.greenBufferSize() > 0)
498 && (format.blueBufferSize() > 0) ?
499 format.redBufferSize() + format.greenBufferSize() + format.blueBufferSize() :
501 switch (format.swapBehavior()) {
502 case QSurfaceFormat::SingleBuffer:
504 iAttributes[i++] = FALSE;
506 case QSurfaceFormat::DefaultSwapBehavior:
507 case QSurfaceFormat::DoubleBuffer:
508 case QSurfaceFormat::TripleBuffer:
510 iAttributes[i++] = TRUE;
513 if (format.stereo()) {
515 iAttributes[i++] = TRUE;
517 if (format.depthBufferSize() >= 0) {
519 iAttributes[i++] = format.depthBufferSize();
523 if (format.redBufferSize() >= 0) {
525 iAttributes[i++] = format.redBufferSize();
527 if (format.greenBufferSize() >= 0) {
529 iAttributes[i++] = format.greenBufferSize();
531 if (format.blueBufferSize() >= 0) {
533 iAttributes[i++] = format.blueBufferSize();
536 iAttributes[i++] = format.alphaBufferSize() >= 0 ? format.alphaBufferSize() : 8;
539 iAttributes[i++] = 16;
542 iAttributes[i++] = 8;
545 iAttributes[i++] = 1;
548 const int samples = format.samples();
549 const bool sampleBuffersRequested = samples > 1
551 int sampleBuffersKeyPosition = 0;
552 int samplesValuePosition = 0;
553 if (sampleBuffersRequested) {
554 sampleBuffersKeyPosition = i;
556 iAttributes[i++] = TRUE;
558 samplesValuePosition = i;
559 iAttributes[i++] = format.samples();
562 iAttributes[i++] = FALSE;
565 bool srgbRequested = format.colorSpace() == QColorSpace::SRgb;
566 int srgbCapableKeyPosition = 0;
568 srgbCapableKeyPosition = i;
570 iAttributes[i++] = TRUE;
577 staticContext.wglChoosePixelFormatARB(hdc, iAttributes,
nullptr, 1,
578 &pixelFormat, &numFormats)
580 if (valid || (!sampleBuffersRequested && !srgbRequested))
584 iAttributes[srgbCapableKeyPosition] = 0;
585 srgbRequested =
false;
586 }
else if (sampleBuffersRequested) {
587 if (iAttributes[samplesValuePosition] > 1) {
588 iAttributes[samplesValuePosition] /= 2;
589 }
else if (iAttributes[samplesValuePosition] == 1) {
592 iAttributes[sampleBuffersKeyPosition] = 0;
593 iAttributes[samplesValuePosition] = 0;
601 initPixelFormatDescriptor(obtainedPfd);
602 QOpenGLStaticContext::opengl32.describePixelFormat(hdc, pixelFormat,
sizeof(PIXELFORMATDESCRIPTOR), obtainedPfd);
603 if (!isAcceptableFormat(additional, *obtainedPfd,
true)) {
604 qCDebug(lcQpaGl) <<
__FUNCTION__ <<
" obtained px #" << pixelFormat
605 <<
" not acceptable=" << *obtainedPfd;
609#ifndef QT_NO_DEBUG_OUTPUT
610 if (lcQpaGl().isDebugEnabled()) {
612 QDebug nsp(&message);
614 if (sampleBuffersRequested)
615 nsp <<
" samples=" << iAttributes[samplesValuePosition];
616 nsp <<
" Attributes: " << Qt::hex << Qt::showbase;
617 for (
int ii = 0; ii < i; ++ii)
618 nsp << iAttributes[ii] <<
',';
619 nsp << Qt::noshowbase << Qt::dec <<
"\n obtained px #" << pixelFormat
620 <<
" of " << numFormats <<
"\n " << *obtainedPfd;
621 qCDebug(lcQpaGl) << message;
630 HDC hdc,
int pixelFormat,
633 enum { attribSize = 42 };
635 QSurfaceFormat result;
636 result.setRenderableType(QSurfaceFormat::OpenGL);
639 int iAttributes[attribSize];
640 int iValues[attribSize];
641 std::fill(iAttributes, iAttributes + attribSize,
int(0));
642 std::fill(iValues, iValues + attribSize,
int(0));
660 if (hasSampleBuffers) {
667 if (!staticContext.wglGetPixelFormatAttribIVARB(hdc, pixelFormat, 0, i,
668 iAttributes, iValues)) {
669 qErrnoWarning(
"%s: wglGetPixelFormatAttribIVARB() failed for basic parameters.",
__FUNCTION__);
672 result.setSwapBehavior(iValues[0] ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::SingleBuffer);
673 result.setDepthBufferSize(iValues[1]);
674 result.setRedBufferSize(iValues[3]);
675 result.setGreenBufferSize(iValues[4]);
676 result.setBlueBufferSize(iValues[5]);
677 result.setAlphaBufferSize(iValues[6]);
678 result.setStencilBufferSize(iValues[8]);
680 result.setOption(QSurfaceFormat::StereoBuffers);
682 if (hasSampleBuffers) {
683 result.setSamples(iValues[13]);
684 if (hasSrgbSupport && iValues[14])
685 result.setColorSpace(QColorSpace::SRgb);
687 if (hasSrgbSupport && iValues[12])
688 result.setColorSpace(QColorSpace::SRgb);
703 const QSurfaceFormat &format,
705 HGLRC shared =
nullptr)
707 enum { attribSize = 11 };
711 int attributes[attribSize];
713 std::fill(attributes, attributes + attribSize,
int(0));
719 const int requestedVersion = qMin((format.majorVersion() << 8) + format.minorVersion(),
720 staticContext.defaultFormat.version);
721 const int majorVersion = requestedVersion >> 8;
722 const int minorVersion = requestedVersion & 0xFF;
724 if (requestedVersion > 0x0101) {
726 attributes[attribIndex++] = majorVersion;
728 attributes[attribIndex++] = minorVersion;
732 if (format.testOption(QSurfaceFormat::DebugContext))
734 if (requestedVersion >= 0x0300) {
735 if (!format.testOption(QSurfaceFormat::DeprecatedFunctions))
739 attributes[attribIndex++] = flags;
741 if (requestedVersion >= 0x0302) {
742 switch (format.profile()) {
743 case QSurfaceFormat::NoProfile:
745 case QSurfaceFormat::CoreProfile:
749 case QSurfaceFormat::CompatibilityProfile:
756 if (format.testOption(QSurfaceFormat::ResetNotification)) {
761 qCDebug(lcQpaGl) <<
__FUNCTION__ <<
"Creating context version"
762 << majorVersion <<
'.' << minorVersion << attribIndex / 2 <<
"attributes";
765 staticContext.wglCreateContextAttribsARB(hdc, shared, attributes);
768 QDebug(&message).nospace() <<
__FUNCTION__ <<
": wglCreateContextAttribsARB() failed (GL error code: 0x"
769 << Qt::hex << staticContext.opengl32.glGetError() << Qt::dec <<
") for format: " << format <<
", shared context: " << shared;
770 qErrnoWarning(
"%s", qPrintable(message));
780 return QWindowsContext::instance()->
781 createDummyWindow(QStringLiteral(
"OpenGLDummyWindow"),
782 L"OpenGLDummyWindow",
nullptr, WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
790 PIXELFORMATDESCRIPTOR pixelFormDescriptor;
791 initPixelFormatDescriptor(&pixelFormDescriptor);
792 pixelFormDescriptor.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_GENERIC_FORMAT;
793 pixelFormDescriptor.iPixelType = PFD_TYPE_RGBA;
795 const int pixelFormat = ChoosePixelFormat(dc, &pixelFormDescriptor);
797 qErrnoWarning(
"%s: ChoosePixelFormat failed.",
__FUNCTION__);
801 qErrnoWarning(
"%s: SetPixelFormat failed.",
__FUNCTION__);
806 qErrnoWarning(
"%s: wglCreateContext failed.",
__FUNCTION__);
823 result.hwnd = createDummyGLWindow();
824 result.hdc = GetDC(result.hwnd);
825 result.renderingContext = createDummyGLContext(result.hdc);
831
832
833
834
835
836
837
842 const QByteArray version = QOpenGLStaticContext::getGlString(GL_VERSION);
844 if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor))
845 result
.version = (major << 8) + minor;
848 result.profile = QSurfaceFormat::NoProfile;
850 result.options |= QSurfaceFormat::DeprecatedFunctions;
857 result.options |= QSurfaceFormat::DeprecatedFunctions;
859 result.options |= QSurfaceFormat::DebugContext;
866 result.profile = QSurfaceFormat::CoreProfile;
868 result.profile = QSurfaceFormat::CompatibilityProfile;
874 format->setMajorVersion(
version >> 8);
875 format->setMinorVersion(
version & 0xFF);
876 format->setProfile(profile);
877 if (options & QSurfaceFormat::DebugContext)
878 format->setOption(QSurfaceFormat::DebugContext);
879 if (options & QSurfaceFormat::DeprecatedFunctions)
880 format->setOption(QSurfaceFormat::DeprecatedFunctions);
884
885
886
887
888
889
890
891
906 m_previous(currentOpenGLContextData()),
907 m_current(createDummyWindowOpenGLContextData())
909 QOpenGLStaticContext::opengl32.wglMakeCurrent(m_current.hdc, m_current.renderingContext);
914 QOpenGLStaticContext::opengl32.wglMakeCurrent(m_previous.hdc, m_previous.renderingContext);
915 ReleaseDC(m_current.hwnd, m_current.hdc);
916 DestroyWindow(m_current.hwnd);
917 QOpenGLStaticContext::opengl32.wglDeleteContext(m_current.renderingContext);
921
922
923
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
942#define SAMPLE_BUFFER_EXTENSION "GL_ARB_multisample"
943#define ROBUSTNESS_EXTENSION "GL_ARB_robustness"
946 vendor(QOpenGLStaticContext::getGlString(GL_VENDOR)),
947 renderer(QOpenGLStaticContext::getGlString(GL_RENDERER)),
948 extensionNames(QOpenGLStaticContext::getGlString(GL_EXTENSIONS)),
950 defaultFormat(QWindowsOpenGLContextFormat::current()),
951 wglGetPixelFormatAttribIVARB(
reinterpret_cast<WglGetPixelFormatAttribIVARB>(
952 reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(
"wglGetPixelFormatAttribivARB")))),
953 wglChoosePixelFormatARB(
reinterpret_cast<WglChoosePixelFormatARB>(
954 reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(
"wglChoosePixelFormatARB")))),
955 wglCreateContextAttribsARB(
reinterpret_cast<WglCreateContextAttribsARB>(
956 reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(
"wglCreateContextAttribsARB")))),
957 wglSwapInternalExt(
reinterpret_cast<WglSwapInternalExt>(
958 reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(
"wglSwapIntervalEXT")))),
959 wglGetSwapInternalExt(
reinterpret_cast<WglGetSwapInternalExt>(
960 reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(
"wglGetSwapIntervalEXT")))),
961 wglGetExtensionsStringARB(
reinterpret_cast<WglGetExtensionsStringARB>(
962 reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(
"wglGetExtensionsStringARB"))))
964 if (defaultFormat.version < 0x0300) {
972 typedef const GLubyte * (
APIENTRY *glGetStringi_t)(GLenum, GLuint);
973 auto glGetStringi =
reinterpret_cast<glGetStringi_t>(
978 for (GLint i = 0; i < n; ++i) {
979 const char *p =
reinterpret_cast<
const char *>(glGetStringi(GL_EXTENSIONS, i));
993 if (
const GLubyte *s =
opengl32.glGetString(which))
994 return QByteArray(
reinterpret_cast<
const char*>(s));
1001 qWarning(
"Failed to load and resolve WGL/OpenGL functions");
1006 QScopedPointer<QOpenGLTemporaryContext> temporaryContext;
1010 qCDebug(lcQpaGl) <<
__FUNCTION__ << *result;
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1029 QOpenGLContext *context) :
1030 m_staticContext(staticContext)
1032 if (!m_staticContext)
1035 QSurfaceFormat format = context->format();
1036 if (format.renderableType() == QSurfaceFormat::DefaultRenderableType)
1037 format.setRenderableType(QSurfaceFormat::OpenGL);
1038 if (format.renderableType() != QSurfaceFormat::OpenGL)
1043 static bool opengl32dll =
false;
1046 staticContext
->opengl32.glGetIntegerv(GL_DEPTH_BITS, ¶ms);
1054 HWND dummyWindow =
nullptr;
1056 bool tryExtensions =
false;
1057 int obtainedSwapInterval = -1;
1059 dummyWindow = createDummyGLWindow();
1062 hdc = GetDC(dummyWindow);
1067 describeFormats(hdc);
1072 tryExtensions = m_staticContext->hasExtensions()
1073 && !testFlag(requestedAdditional.formatFlags, QWindowsGLRenderToPixmap)
1074 && !(QWindowsIntegration::instance()->options() & QWindowsIntegration::DisableArb);
1076 if (tryExtensions) {
1077 if (m_staticContext->wglGetExtensionsStringARB) {
1078 const char *exts = m_staticContext->wglGetExtensionsStringARB(hdc);
1080 qCDebug(lcQpaGl) <<
__FUNCTION__ <<
"WGL extensions:" << exts;
1081 if (strstr(exts,
"WGL_EXT_framebuffer_sRGB"))
1086 ARB::choosePixelFormat(hdc, *m_staticContext, format,
1087 requestedAdditional, &m_obtainedPixelFormatDescriptor);
1088 if (m_pixelFormat > 0) {
1090 ARB::qSurfaceFormatFromHDC(*m_staticContext, hdc, m_pixelFormat,
1091 &obtainedAdditional);
1092 m_extensionsUsed =
true;
1095 if (!m_pixelFormat) {
1096 m_pixelFormat = GDI::choosePixelFormat(hdc, format, requestedAdditional,
1097 &m_obtainedPixelFormatDescriptor);
1100 GDI::qSurfaceFormatFromPixelFormat(m_obtainedPixelFormatDescriptor,
1101 &obtainedAdditional);
1103 if (!m_pixelFormat) {
1104 qWarning(
"%s: Unable find a suitable pixel format.",
__FUNCTION__);
1107 if (!QOpenGLStaticContext::opengl32.setPixelFormat(hdc, m_pixelFormat, &m_obtainedPixelFormatDescriptor)) {
1108 qErrnoWarning(
"SetPixelFormat failed.");
1112 HGLRC sharingRenderingContext =
nullptr;
1113 if (
const QPlatformOpenGLContext *sc = context->shareHandle())
1114 sharingRenderingContext =
static_cast<
const QWindowsGLContext *>(sc)->renderingContext();
1116 if (m_extensionsUsed)
1117 m_renderingContext =
1118 ARB::createContext(*m_staticContext, hdc,
1120 requestedAdditional,
1121 sharingRenderingContext);
1122 if (!m_renderingContext)
1123 m_renderingContext = GDI::createContext(hdc, sharingRenderingContext);
1125 if (!m_renderingContext) {
1126 qWarning(
"Unable to create a GL Context.");
1131 if (!updateObtainedParams(hdc, &obtainedSwapInterval))
1137 ReleaseDC(dummyWindow, hdc);
1139 DestroyWindow(dummyWindow);
1141 qCDebug(lcQpaGl) <<
__FUNCTION__ <<
this << (tryExtensions ?
"ARB" :
"GDI")
1142 <<
" requested: " << context->format()
1143 <<
"\n obtained #" << m_pixelFormat << (m_extensionsUsed ?
"ARB" :
"GDI") << m_obtainedFormat
1144 <<
"\n " << m_obtainedPixelFormatDescriptor <<
" swap interval: " << obtainedSwapInterval
1145 <<
"\n default: " << m_staticContext->defaultFormat
1146 <<
"\n HGLRC=" << m_renderingContext;
1150 : m_staticContext(staticContext)
1152 if (!m_staticContext)
1155 HDC dc = GetDC(wnd);
1158 m_pixelFormat = GetPixelFormat(dc);
1159 bool ok = m_pixelFormat != 0;
1161 qWarning(
"QWindowsGLContext: Failed to get pixel format");
1162 ok = DescribePixelFormat(dc, m_pixelFormat,
sizeof(PIXELFORMATDESCRIPTOR), &m_obtainedPixelFormatDescriptor);
1164 qWarning(
"QWindowsGLContext: Failed to describe pixel format");
1167 m_obtainedFormat = GDI::qSurfaceFormatFromPixelFormat(m_obtainedPixelFormatDescriptor, &obtainedAdditional);
1168 m_renderingContext = wglcontext;
1169 ok = updateObtainedParams(dc);
1175 m_ownsContext =
false;
1177 m_renderingContext =
nullptr;
1182 if (m_renderingContext && m_ownsContext)
1183 QOpenGLStaticContext::opengl32.wglDeleteContext(m_renderingContext);
1192 if (!QOpenGLStaticContext::opengl32.wglMakeCurrent(hdc, m_renderingContext)) {
1193 qWarning(
"Failed to make context current.");
1197 QWindowsOpenGLContextFormat::current().apply(&m_obtainedFormat);
1199 if (m_staticContext->wglGetSwapInternalExt && obtainedSwapInterval)
1200 *obtainedSwapInterval = m_staticContext->wglGetSwapInternalExt();
1206 m_obtainedFormat.setOption(QSurfaceFormat::ResetNotification);
1207 m_getGraphicsResetStatus =
reinterpret_cast<GlGetGraphicsResetStatusArbType>(
1208 reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(
"glGetGraphicsResetStatusARB")));
1217 for (
const auto &e : m_windowContexts)
1218 ReleaseDC(e.hwnd, e.hdc);
1219 m_windowContexts.clear();
1229 return glWindowOf(s)->handle();
1234 findByHWND(
const std::vector<QOpenGLContextData> &data, HWND hwnd)
1236 for (
const auto &e : data) {
1245 if (QWindowsContext::verbose > 1)
1246 qCDebug(lcQpaGl) <<
__FUNCTION__ << surface;
1248 if (
const QOpenGLContextData *contextData = findByHWND(m_windowContexts, handleOf(surface)))
1251 qWarning(
"%s: Cannot find window %p",
__FUNCTION__, handleOf(surface));
1257 if (QWindowsContext::verbose > 1)
1258 qCDebug(lcQpaGl) <<
__FUNCTION__ <<
this << m_windowContexts.size() <<
"contexts";
1261 Q_ASSERT(surface->surface()->supportsOpenGL());
1265 const HWND hwnd = window->handle();
1276 qErrnoWarning(
"%s: wglMakeCurrent() failed for existing context data",
__FUNCTION__);
1281 if (!newContext.hdc)
1286 if (!QOpenGLStaticContext::opengl32.setPixelFormat(newContext.hdc, m_pixelFormat, &m_obtainedPixelFormatDescriptor)) {
1287 qErrnoWarning(
"%s: SetPixelFormat() failed",
__FUNCTION__);
1288 ReleaseDC(newContext.hwnd, newContext.hdc);
1292 if (m_obtainedFormat.swapBehavior() == QSurfaceFormat::DoubleBuffer)
1295 m_windowContexts.push_back(newContext);
1300 if (m_getGraphicsResetStatus && m_getGraphicsResetStatus()) {
1302 qCDebug(lcQpaGl) <<
"makeCurrent(): context loss detected" <<
this;
1304 window->invalidateSurface();
1306 qErrnoWarning(
"%s: wglMakeCurrent() failed",
__FUNCTION__);
1311 if (m_staticContext->wglSwapInternalExt) {
1312 const int interval = surface->format().swapInterval();
1313 if (m_swapInterval != interval)
1314 m_swapInterval = interval;
1316 m_staticContext->wglSwapInternalExt(interval);
1325 if (QWindowsContext::verbose > 1)
1326 qCDebug(lcQpaGl) <<
__FUNCTION__ <<
this << m_windowContexts.size() <<
"contexts";
1344 if (procAddress ==
nullptr ||
reinterpret_cast<quintptr>(procAddress) < 4u
1345 || procAddress ==
reinterpret_cast<QFunctionPointer>(-1)) {
1349 if (QWindowsContext::verbose > 1)
1350 qCDebug(lcQpaGl) <<
__FUNCTION__ << procName << QOpenGLStaticContext::opengl32.wglGetCurrentContext() <<
"returns" << procAddress;
1352 return reinterpret_cast<QFunctionPointer>(procAddress);
Static Open GL context containing version information, extension function pointers,...
QWindowsOpenGLContext * createContext(HGLRC context, HWND window) override
HGLRC(APIENTRY * WglCreateContextAttribsARB)(HDC, HGLRC, const int *)
bool hasExtensions() const
QWindowsOpenGLContext * createContext(QOpenGLContext *context) override
static QOpenGLStaticContext * create(bool softwareRendering=false)
static QWindowsOpengl32DLL opengl32
A temporary context that can be instantiated on the stack.
~QOpenGLTemporaryContext()
Singleton container for all relevant information.
void doneCurrent() override
QWindowsGLContext(QOpenGLStaticContext *staticContext, HGLRC context, HWND window)
QFunctionPointer getProcAddress(const char *procName) override
Reimplement in subclass to allow dynamic querying of OpenGL symbols.
bool makeCurrent(QPlatformSurface *surface) override
QWindowsGLContext(QOpenGLStaticContext *staticContext, QOpenGLContext *context)
void swapBuffers(QPlatformSurface *surface) override
Reimplement in subclass to native swap buffers calls.
~QWindowsGLContext() override
@ OpenGlPixelFormatInitialized
static HGLRC createContext(const QOpenGLStaticContext &staticContext, HDC hdc, const QSurfaceFormat &format, const QWindowsOpenGLAdditionalFormat &, HGLRC shared=nullptr)
static int choosePixelFormat(HDC hdc, const QOpenGLStaticContext &staticContext, const QSurfaceFormat &format, const QWindowsOpenGLAdditionalFormat &additional, PIXELFORMATDESCRIPTOR *obtainedPfd)
static QSurfaceFormat qSurfaceFormatFromHDC(const QOpenGLStaticContext &staticContext, HDC hdc, int pixelFormat, QWindowsOpenGLAdditionalFormat *additionalIn=nullptr)
static PIXELFORMATDESCRIPTOR qPixelFormatFromSurfaceFormat(const QSurfaceFormat &format, const QWindowsOpenGLAdditionalFormat &additional)
static QSurfaceFormat qSurfaceFormatFromPixelFormat(const PIXELFORMATDESCRIPTOR &pfd, QWindowsOpenGLAdditionalFormat *additionalIn=nullptr)
static HGLRC createContext(HDC hdc, HGLRC shared)
static int choosePixelFormat(HDC hdc, const QSurfaceFormat &format, const QWindowsOpenGLAdditionalFormat &additional, PIXELFORMATDESCRIPTOR *obtainedPfd)
#define GL_CONTEXT_PROFILE_MASK
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT
#define GL_CONTEXT_CORE_PROFILE_BIT
#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
#define GL_CONTEXT_FLAG_DEBUG_BIT
#define GL_NUM_EXTENSIONS
#define WGL_CONTEXT_MINOR_VERSION_ARB
#define WGL_STENCIL_BITS_ARB
#define WGL_ACCELERATION_ARB
static const QOpenGLContextData * findByHWND(const std::vector< QOpenGLContextData > &data, HWND hwnd)
static bool isDirectRendering(const PIXELFORMATDESCRIPTOR &pfd)
#define WGL_BLUE_BITS_ARB
#define RESET_NOTIFICATION_STRATEGY_ARB
static QOpenGLContextData currentOpenGLContextData()
#define WGL_GREEN_BITS_ARB
static bool hasGLOverlay(const PIXELFORMATDESCRIPTOR &pd)
#define WGL_ALPHA_BITS_ARB
#define WGL_CONTEXT_MAJOR_VERSION_ARB
#define WGL_CONTEXT_PROFILE_MASK_ARB
#define WGL_NO_ACCELERATION_ARB
#define WGL_PIXEL_TYPE_ARB
#define WGL_DEPTH_BITS_ARB
#define ROBUSTNESS_EXTENSION
static bool isAcceptableFormat(const QWindowsOpenGLAdditionalFormat &additional, const PIXELFORMATDESCRIPTOR &pfd, bool ignoreGLSupport=false)
#define WGL_NUMBER_OVERLAYS_ARB
#define WGL_CONTEXT_DEBUG_BIT_ARB
#define WGL_DOUBLE_BUFFER_ARB
static HGLRC createDummyGLContext(HDC dc)
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB
static void initPixelFormatDescriptor(PIXELFORMATDESCRIPTOR *d)
static QOpenGLContextData createDummyWindowOpenGLContextData()
#define WGL_DRAW_TO_WINDOW_ARB
static HWND handleOf(QPlatformSurface *s)
#define WGL_TYPE_RGBA_ARB
#define LOSE_CONTEXT_ON_RESET_ARB
#define WGL_CONTEXT_FLAGS_ARB
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
static void describeFormats(HDC hdc)
#define SAMPLE_BUFFER_EXTENSION
bool testFlag(MaskType mask, FlagType flag)
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
#define WGL_FULL_ACCELERATION_ARB
#define WGL_SAMPLE_BUFFERS_ARB
static QWindowsWindow * glWindowOf(QPlatformSurface *s)
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT
#define WGL_ACCUM_BITS_ARB
static HWND createDummyGLWindow()
#define WGL_COLOR_BITS_ARB
#define WGL_SUPPORT_OPENGL_ARB
@ QWindowsGLDirectRendering
@ QWindowsGLRenderToPixmap
static QWindowsOpenGLContextFormat current()
void apply(QSurfaceFormat *format) const
bool init(bool softwareRendering)
int describePixelFormat(HDC dc, int pf, UINT size, PIXELFORMATDESCRIPTOR *pfd)
QFunctionPointer resolve(const char *name)
bool moduleIsNotOpengl32() const
BOOL setPixelFormat(HDC dc, int pf, const PIXELFORMATDESCRIPTOR *pfd)