void setSwapInterval(QGLWidget const &glWidget, int *interval) { typedef void (* PFNGLXQUERYDRAWABLEPROC)(Display *, GLXDrawable, int, unsigned int *); typedef void (* PFNGLXSWAPINTERVALEXTPROC)(Display *, GLXDrawable, int); typedef int (* PFNGLXGETSWAPINTERVALMESAPROC)(void); typedef int (* PFNGLXSWAPINTERVALMESAPROC)(unsigned); typedef int (* PFNGLXSWAPINTERVALSGIPROC)(int); PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT; PFNGLXQUERYDRAWABLEPROC glXQueryDrawable; PFNGLXGETSWAPINTERVALMESAPROC glXGetSwapIntervalMESA; PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA; PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI; QGLContext const &context = *glWidget.context(); QX11Info const &xinfo = glWidget.x11Info(); glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) context.getProcAddress("glXSwapIntervalEXT"); glXQueryDrawable = (PFNGLXQUERYDRAWABLEPROC) context.getProcAddress("glXQueryDrawable"); if (glXSwapIntervalEXT && glXQueryDrawable) { unsigned clampedInterval; if (*interval < 0) { *interval = 0; } glXSwapIntervalEXT(xinfo.display(), glWidget.winId(), *interval); glXQueryDrawable(xinfo.display(), glWidget.winId(), GLX_SWAP_INTERVAL_EXT, &clampedInterval); *interval = clampedInterval; return; } glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) context.getProcAddress("glXSwapIntervalMESA"); glXGetSwapIntervalMESA = (PFNGLXGETSWAPINTERVALMESAPROC) context.getProcAddress("glXGetSwapIntervalMESA"); if (glXSwapIntervalMESA && glXGetSwapIntervalMESA) { if (*interval < 0) { *interval = 0; } glXSwapIntervalMESA(*interval); *interval = glXGetSwapIntervalMESA(); return; } glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) context.getProcAddress("glXSwapIntervalSGI"); if (glXSwapIntervalSGI) { if (*interval < 1) { *interval = 1; } if (glXSwapIntervalSGI(*interval)) { // Error, revert to default *interval = 1; glXSwapIntervalSGI(1); } return; } *interval = -1; }
bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) { QGLWidget dmy; dmy.makeCurrent(); // needed for wglGetProcAddress() to succeed PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC) wglGetProcAddress("wglCreatePbufferARB"); PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC) wglGetProcAddress("wglGetPbufferDCARB"); PFNWGLQUERYPBUFFERARBPROC wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC) wglGetProcAddress("wglQueryPbufferARB"); PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB"); if (!wglCreatePbufferARB) // assumes that if one can be resolved, all of them can return false; dc = GetDC(dmy.winId()); Q_ASSERT(dc); PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB"); if (wglGetExtensionsStringARB) { QString extensions(QLatin1String(wglGetExtensionsStringARB(dc))); has_render_texture = extensions.contains(QLatin1String("WGL_ARB_render_texture")); } int attribs[40]; qt_format_to_attrib_list(has_render_texture, f, attribs); // Find pbuffer capable pixel format. unsigned int num_formats = 0; int pixel_format; wglChoosePixelFormatARB(dc, attribs, 0, 1, &pixel_format, &num_formats); // some GL implementations don't support pbuffers with accum // buffers, so try that before we give up if (num_formats == 0 && f.accum()) { QGLFormat tmp = f; tmp.setAccum(false); qt_format_to_attrib_list(has_render_texture, tmp, attribs); wglChoosePixelFormatARB(dc, attribs, 0, 1, &pixel_format, &num_formats); } if (num_formats == 0) { qWarning("QGLPixelBuffer: Unable to find a pixel format with pbuffer - giving up."); ReleaseDC(dmy.winId(), dc); return false; } format = pfiToQGLFormat(dc, pixel_format); // NB! The below ONLY works if the width/height are powers of 2. // Set some pBuffer attributes so that we can use this pBuffer as // a 2D RGBA texture target. int pb_attribs[] = {WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB, WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB, 0}; pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(), has_render_texture ? pb_attribs : 0); if(!pbuf) { // try again without the render_texture extension pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(), 0); has_render_texture = false; if (!pbuf) { qWarning("QGLPixelBuffer: Unable to create pbuffer [w=%d, h=%d] - giving up.", size.width(), size.height()); ReleaseDC(dmy.winId(), dc); return false; } } ReleaseDC(dmy.winId(), dc); dc = wglGetPbufferDCARB(pbuf); ctx = wglCreateContext(dc); if (!dc || !ctx) { qWarning("QGLPixelBuffer: Unable to create pbuffer context - giving up."); return false; } HGLRC share_ctx = shareWidget ? shareWidget->d_func()->glcx->d_func()->rc : 0; if (share_ctx && !wglShareLists(share_ctx, ctx)) qWarning("QGLPixelBuffer: Unable to share display lists - with share widget."); int width, height; wglQueryPbufferARB(pbuf, WGL_PBUFFER_WIDTH_ARB, &width); wglQueryPbufferARB(pbuf, WGL_PBUFFER_HEIGHT_ARB, &height); return true; }