static PIXELFORMATDESCRIPTOR qPixelFormatFromSurfaceFormat(const QSurfaceFormat &format, const QWindowsOpenGLAdditionalFormat &additional) { PIXELFORMATDESCRIPTOR pfd; initPixelFormatDescriptor(&pfd); pfd.iPixelType = PFD_TYPE_RGBA; pfd.iLayerType = PFD_MAIN_PLANE; pfd.dwFlags = PFD_SUPPORT_OPENGL; if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) pfd.dwFlags = PFD_SUPPORT_COMPOSITION; const bool isPixmap = (additional.formatFlags & QWindowsGLRenderToPixmap) != 0; pfd.dwFlags |= isPixmap ? PFD_DRAW_TO_BITMAP : PFD_DRAW_TO_WINDOW; if (!(additional.formatFlags & QWindowsGLDirectRendering)) pfd.dwFlags |= PFD_GENERIC_FORMAT; if (format.stereo()) pfd.dwFlags |= PFD_STEREO; if (format.swapBehavior() == QSurfaceFormat::DoubleBuffer && !isPixmap) pfd.dwFlags |= PFD_DOUBLEBUFFER; pfd.cDepthBits = format.depthBufferSize() >= 0 ? format.depthBufferSize() : 32; pfd.cAlphaBits = format.alphaBufferSize() > 0 ? format.alphaBufferSize() : 8; pfd.cStencilBits = format.stencilBufferSize() > 0 ? format.stencilBufferSize() : 8; if (additional.formatFlags & QWindowsGLAccumBuffer) pfd.cAccumRedBits = pfd.cAccumGreenBits = pfd.cAccumBlueBits = pfd.cAccumAlphaBits = 16; return pfd; }
QT_BEGIN_NAMESPACE /*! Returns an OpenGL format for the window format specified by \a format. */ QGLFormat QGLFormat::fromSurfaceFormat(const QSurfaceFormat &format) { QGLFormat retFormat; if (format.alphaBufferSize() >= 0) retFormat.setAlphaBufferSize(format.alphaBufferSize()); if (format.blueBufferSize() >= 0) retFormat.setBlueBufferSize(format.blueBufferSize()); if (format.greenBufferSize() >= 0) retFormat.setGreenBufferSize(format.greenBufferSize()); if (format.redBufferSize() >= 0) retFormat.setRedBufferSize(format.redBufferSize()); if (format.depthBufferSize() >= 0) retFormat.setDepthBufferSize(format.depthBufferSize()); if (format.samples() > 1) { retFormat.setSampleBuffers(format.samples()); retFormat.setSamples(true); } if (format.stencilBufferSize() > 0) { retFormat.setStencil(true); retFormat.setStencilBufferSize(format.stencilBufferSize()); } retFormat.setDoubleBuffer(format.swapBehavior() != QSurfaceFormat::SingleBuffer); retFormat.setStereo(format.stereo()); return retFormat; }
QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced) { QSurfaceFormat retFormat = format; *reduced = true; if (retFormat.redBufferSize() > 1) { retFormat.setRedBufferSize(1); } else if (retFormat.greenBufferSize() > 1) { retFormat.setGreenBufferSize(1); } else if (retFormat.blueBufferSize() > 1) { retFormat.setBlueBufferSize(1); } else if (retFormat.samples() > 1) { retFormat.setSamples(qMin(retFormat.samples() / 2, 16)); } else if (retFormat.stereo()) { retFormat.setStereo(false); }else if (retFormat.stencilBufferSize() > 0) { retFormat.setStencilBufferSize(0); }else if (retFormat.hasAlpha()) { retFormat.setAlphaBufferSize(0); }else if (retFormat.depthBufferSize() > 0) { retFormat.setDepthBufferSize(0); }else if (retFormat.swapBehavior() != QSurfaceFormat::SingleBuffer) { retFormat.setSwapBehavior(QSurfaceFormat::SingleBuffer); }else{ *reduced = false; } return retFormat; }
// Choose a suitable pixelformat using GDI WinAPI in case ARB // functions cannot be found. First tries to find a suitable // format using GDI function ChoosePixelFormat(). Since that // does not handle overlay and direct-rendering requests, manually loop // over the available formats to find the best one. // Note: As of Windows 7, it seems direct-rendering is handled, so, // the code might be obsolete? static int choosePixelFormat(HDC hdc, const QSurfaceFormat &format, const QWindowsOpenGLAdditionalFormat &additional, PIXELFORMATDESCRIPTOR *obtainedPfd) { // 1) Try ChoosePixelFormat(). PIXELFORMATDESCRIPTOR requestedPfd = qPixelFormatFromSurfaceFormat(format, QWindowsGLDirectRendering); initPixelFormatDescriptor(obtainedPfd); int pixelFormat = ChoosePixelFormat(hdc, &requestedPfd); if (pixelFormat >= 0) { DescribePixelFormat(hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), obtainedPfd); if (isAcceptableFormat(additional, *obtainedPfd)) return pixelFormat; } // 2) No matching format found, manual search loop. const int pfiMax = DescribePixelFormat(hdc, 0, 0, NULL); int bestScore = -1; int bestPfi = -1; const bool stereoRequested = format.stereo(); const bool accumBufferRequested = testFlag(additional.formatFlags, QWindowsGLAccumBuffer); const bool doubleBufferRequested = format.swapBehavior() == QSurfaceFormat::DoubleBuffer; const bool directRenderingRequested = testFlag(additional.formatFlags, QWindowsGLDirectRendering); for (int pfi = 1; pfi <= pfiMax; pfi++) { PIXELFORMATDESCRIPTOR checkPfd; initPixelFormatDescriptor(&checkPfd); DescribePixelFormat(hdc, pfi, sizeof(PIXELFORMATDESCRIPTOR), &checkPfd); if (isAcceptableFormat(additional, checkPfd)) { int score = checkPfd.cColorBits + checkPfd.cAlphaBits + checkPfd.cStencilBits; if (accumBufferRequested) score += checkPfd.cAccumBits; if (doubleBufferRequested == testFlag(checkPfd.dwFlags, PFD_DOUBLEBUFFER)) score += 1000; if (stereoRequested == testFlag(checkPfd.dwFlags, PFD_STEREO)) score += 2000; if (directRenderingRequested == isDirectRendering(checkPfd)) score += 4000; if (checkPfd.iPixelType == PFD_TYPE_RGBA) score += 8000; if (score > bestScore) { bestScore = score; bestPfi = pfi; *obtainedPfd = checkPfd; } if (QWindowsContext::verboseGL) qDebug() << __FUNCTION__ << " checking " << pfi << '/' << pfiMax << " score=" << score << " (best " << bestPfi << '/' << bestScore << ") " << checkPfd; } } // for if (bestPfi > 0) pixelFormat = bestPfi; return pixelFormat; }
QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit) { QVector<int> spec(48); int i = 0; spec[i++] = GLX_LEVEL; spec[i++] = 0; spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = drawableBit; spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT; spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize(); spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize(); spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize(); if (format.hasAlpha()) { spec[i++] = GLX_ALPHA_SIZE; spec[i++] = format.alphaBufferSize(); } spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.swapBehavior() != QSurfaceFormat::SingleBuffer ? True : False; spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False; if (format.depthBufferSize() > 0) { spec[i++] = GLX_DEPTH_SIZE; spec[i++] = format.depthBufferSize(); } if (format.stencilBufferSize() > 0) { spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize(); } if (format.samples() > 1) { spec[i++] = GLX_SAMPLE_BUFFERS_ARB; spec[i++] = 1; spec[i++] = GLX_SAMPLES_ARB; spec[i++] = format.samples(); } spec[i++] = XNone; return spec; }
// Choose a suitable pixelformat using ARB extension functions. static int choosePixelFormat(HDC hdc, const QOpenGLStaticContext &staticContext, const QSurfaceFormat &format, const QWindowsOpenGLAdditionalFormat &additional, PIXELFORMATDESCRIPTOR *obtainedPfd) { enum { attribSize =40 }; if ((additional.formatFlags & QWindowsGLRenderToPixmap) || !staticContext.hasExtensions()) return 0; int iAttributes[attribSize]; qFill(iAttributes, iAttributes + attribSize, int(0)); int i = 0; iAttributes[i++] = WGL_ACCELERATION_ARB; iAttributes[i++] = testFlag(additional.formatFlags, QWindowsGLDirectRendering) ? WGL_FULL_ACCELERATION_ARB : WGL_NO_ACCELERATION_ARB; iAttributes[i++] = WGL_SUPPORT_OPENGL_ARB; iAttributes[i++] = TRUE; iAttributes[i++] = WGL_DRAW_TO_WINDOW_ARB; iAttributes[i++] = TRUE; iAttributes[i++] = WGL_COLOR_BITS_ARB; iAttributes[i++] = 24; switch (format.swapBehavior()) { case QSurfaceFormat::DefaultSwapBehavior: break; case QSurfaceFormat::SingleBuffer: iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; iAttributes[i++] = FALSE; break; case QSurfaceFormat::DoubleBuffer: case QSurfaceFormat::TripleBuffer: iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; iAttributes[i++] = TRUE; break; } if (format.stereo()) { iAttributes[i++] = WGL_STEREO_ARB; iAttributes[i++] = TRUE; } if (format.depthBufferSize() >= 0) { iAttributes[i++] = WGL_DEPTH_BITS_ARB; iAttributes[i++] = format.depthBufferSize(); } iAttributes[i++] = WGL_PIXEL_TYPE_ARB; iAttributes[i++] = WGL_TYPE_RGBA_ARB; if (format.redBufferSize() >= 0) { iAttributes[i++] = WGL_RED_BITS_ARB; iAttributes[i++] = format.redBufferSize(); } if (format.greenBufferSize() >= 0) { iAttributes[i++] = WGL_GREEN_BITS_ARB; iAttributes[i++] = format.greenBufferSize(); } if (format.blueBufferSize() >= 0) { iAttributes[i++] = WGL_BLUE_BITS_ARB; iAttributes[i++] = format.blueBufferSize(); } iAttributes[i++] = WGL_ALPHA_BITS_ARB; iAttributes[i++] = format.alphaBufferSize() >= 0 ? format.alphaBufferSize() : 8; if (additional.formatFlags & QWindowsGLAccumBuffer) { iAttributes[i++] = WGL_ACCUM_BITS_ARB; iAttributes[i++] = 16; } iAttributes[i++] = WGL_STENCIL_BITS_ARB; iAttributes[i++] = 8; if (additional.formatFlags & QWindowsGLOverlay) { iAttributes[i++] = WGL_NUMBER_OVERLAYS_ARB; iAttributes[i++] = 1; } const int samples = format.samples(); const bool sampleBuffersRequested = samples > 1 && testFlag(staticContext.extensions, QOpenGLStaticContext::SampleBuffers); int samplesValuePosition = 0; if (sampleBuffersRequested) { iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; iAttributes[i++] = TRUE; iAttributes[i++] = WGL_SAMPLES_ARB; samplesValuePosition = i; iAttributes[i++] = format.samples(); } else if (samples == 0 || samples == 1 ) { iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; iAttributes[i++] = FALSE; } // If sample buffer request cannot be satisfied, reduce request. int pixelFormat = 0; uint numFormats = 0; while (true) { const bool valid = staticContext.wglChoosePixelFormatARB(hdc, iAttributes, 0, 1, &pixelFormat, &numFormats) && numFormats >= 1; if (valid || !sampleBuffersRequested) break; if (iAttributes[samplesValuePosition] > 1) { iAttributes[samplesValuePosition] /= 2; } else { break; } } // Verify if format is acceptable. Note that the returned // formats have been observed to not contain PFD_SUPPORT_OPENGL, ignore. initPixelFormatDescriptor(obtainedPfd); DescribePixelFormat(hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), obtainedPfd); if (!isAcceptableFormat(additional, *obtainedPfd, true)) { if (QWindowsContext::verboseGL) qDebug() << __FUNCTION__ << " obtained px #" << pixelFormat << " not acceptable=" << *obtainedPfd; pixelFormat = 0; } #ifndef QT_NO_DEBUG_OUTPUT if (QWindowsContext::verboseGL) { QDebug nsp = qDebug().nospace(); nsp << __FUNCTION__; if (sampleBuffersRequested) nsp << " samples=" << iAttributes[samplesValuePosition]; nsp << " Attributes: " << hex << showbase; for (int ii = 0; ii < i; ++ii) nsp << iAttributes[ii] << ','; nsp << noshowbase << dec << "\n obtained px #" << pixelFormat << " of " << numFormats << "\n " << *obtainedPfd; } // Debug #endif return pixelFormat; }