bool QGLPixelBuffer::hasOpenGLPbuffers() { bool ret = qt_resolve_pbuffer_extensions(); if (!ret) return false; int attribs[40]; int num_configs = 0; qt_format_to_attrib_list(QGLFormat::defaultFormat(), attribs); GLXFBConfig *configs = glXChooseFBConfig(X11->display, X11->defaultScreen, attribs, &num_configs); GLXPbuffer pbuf = 0; GLXContext ctx = 0; if (configs && num_configs) { int pb_attribs[] = {GLX_PBUFFER_WIDTH, 128, GLX_PBUFFER_HEIGHT, 128, XNone}; pbuf = glXCreatePbuffer(X11->display, configs[0], pb_attribs); ctx = glXCreateNewContext(X11->display, configs[0], GLX_RGBA_TYPE, 0, true); XFree(configs); glXDestroyContext(X11->display, ctx); glXDestroyPbuffer(X11->display, pbuf); } return pbuf && ctx; }
bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) { QGLTemporaryContext tempContext; 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 = wglGetCurrentDC(); Q_ASSERT(dc); has_render_texture = false; // sample buffers doesn't work in conjunction with the render_texture extension if (!f.sampleBuffers()) { 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."); 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}; int pb_attribs_null[] = {0}; pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(), has_render_texture ? pb_attribs : pb_attribs_null); if (!pbuf) { // try again without the render_texture extension pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(), pb_attribs_null); has_render_texture = false; if (!pbuf) { qWarning("QGLPixelBuffer: Unable to create pbuffer [w=%d, h=%d] - giving up.", size.width(), size.height()); return false; } } dc = wglGetPbufferDCARB(pbuf); ctx = wglCreateContext(dc); if (!dc || !ctx) { qWarning("QGLPixelBuffer: Unable to create pbuffer context - giving up."); return false; } // Explicitly disable the render_texture extension if we have a // multi-sampled pbuffer context. This seems to be a problem only with // ATI cards if multi-sampling is forced globally in the driver. wglMakeCurrent(dc, ctx); GLint samples = 0; glGetIntegerv(GL_SAMPLES_ARB, &samples); if (has_render_texture && samples != 0) has_render_texture = 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; }
bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) { if (!qt_resolve_pbuffer_extensions()) { qWarning("QGLPixelBuffer: pbuffers are not supported on this system."); return false; } int attribs[40]; int num_configs = 0; qt_format_to_attrib_list(f, attribs); int screen = X11->defaultScreen; if (shareWidget) screen = shareWidget->x11Info().screen(); GLXFBConfig *configs = glXChooseFBConfig(X11->display, screen, attribs, &num_configs); if (configs && num_configs) { int res; glXGetFBConfigAttrib(X11->display, configs[0], GLX_LEVEL, &res); format.setPlane(res); glXGetFBConfigAttrib(X11->display, configs[0], GLX_DOUBLEBUFFER, &res); format.setDoubleBuffer(res); glXGetFBConfigAttrib(X11->display, configs[0], GLX_DEPTH_SIZE, &res); format.setDepth(res); if (format.depth()) format.setDepthBufferSize(res); glXGetFBConfigAttrib(X11->display, configs[0], GLX_RGBA, &res); format.setRgba(res); glXGetFBConfigAttrib(X11->display, configs[0], GLX_RED_SIZE, &res); format.setRedBufferSize(res); glXGetFBConfigAttrib(X11->display, configs[0], GLX_GREEN_SIZE, &res); format.setGreenBufferSize(res); glXGetFBConfigAttrib(X11->display, configs[0], GLX_BLUE_SIZE, &res); format.setBlueBufferSize(res); glXGetFBConfigAttrib(X11->display, configs[0], GLX_ALPHA_SIZE, &res); format.setAlpha(res); if (format.alpha()) format.setAlphaBufferSize(res); glXGetFBConfigAttrib(X11->display, configs[0], GLX_ACCUM_RED_SIZE, &res); format.setAccum(res); if (format.accum()) format.setAccumBufferSize(res); glXGetFBConfigAttrib(X11->display, configs[0], GLX_STENCIL_SIZE, &res); format.setStencil(res); if (format.stencil()) format.setStencilBufferSize(res); glXGetFBConfigAttrib(X11->display, configs[0], GLX_STEREO, &res); format.setStereo(res); glXGetFBConfigAttrib(X11->display, configs[0], GLX_SAMPLE_BUFFERS_ARB, &res); format.setSampleBuffers(res); if (format.sampleBuffers()) { glXGetFBConfigAttrib(X11->display, configs[0], GLX_SAMPLES_ARB, &res); format.setSamples(res); } int pb_attribs[] = {GLX_PBUFFER_WIDTH, size.width(), GLX_PBUFFER_HEIGHT, size.height(), XNone}; GLXContext shareContext = 0; if (shareWidget && shareWidget->d_func()->glcx) shareContext = (GLXContext) shareWidget->d_func()->glcx->d_func()->cx; pbuf = glXCreatePbuffer(QX11Info::display(), configs[0], pb_attribs); ctx = glXCreateNewContext(QX11Info::display(), configs[0], GLX_RGBA_TYPE, shareContext, true); XFree(configs); if (!pbuf || !ctx) { qWarning("QGLPixelBuffer: Unable to create a pbuffer/context - giving up."); return false; } return true; } else { qWarning("QGLPixelBuffer: Unable to find a context/format match - giving up."); return false; } }
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; }