void QGLPaintDevice::beginPaint() { // Make sure our context is the current one: QGLContext *ctx = context(); ctx->makeCurrent(); ctx->d_func()->refreshCurrentFbo(); // Record the currently bound FBO so we can restore it again // in endPaint() and bind this device's FBO // // Note: m_thisFBO could be zero if the paint device is not // backed by an FBO (e.g. window back buffer). But there could // be a previous FBO bound to the context which we need to // explicitly unbind. Otherwise the painting will go into // the previous FBO instead of to the window. m_previousFBO = ctx->d_func()->current_fbo; if (m_previousFBO != m_thisFBO) { ctx->d_func()->setCurrentFbo(m_thisFBO); ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO); } // Set the default fbo for the context to m_thisFBO so that // if some raw GL code between beginNativePainting() and // endNativePainting() calls QGLFramebufferObject::release(), // painting will revert to the window surface's fbo. ctx->d_ptr->default_fbo = m_thisFBO; }
void QGLPaintDevice::endPaint() { // Make sure the FBO bound at beginPaint is re-bound again here: QGLContext *ctx = context(); ctx->d_func()->refreshCurrentFbo(); if (m_previousFBO != ctx->d_func()->current_fbo) { ctx->d_func()->setCurrentFbo(m_previousFBO); ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_previousFBO); } ctx->d_ptr->default_fbo = 0; }
void QGLPaintDevice::ensureActiveTarget() { QGLContext* ctx = context(); if (ctx != QGLContext::currentContext()) ctx->makeCurrent(); ctx->d_func()->refreshCurrentFbo(); if (ctx->d_ptr->current_fbo != m_thisFBO) { ctx->d_func()->setCurrentFbo(m_thisFBO); ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO); } ctx->d_ptr->default_fbo = m_thisFBO; }
void QGLPaintDevice::endPaint() { // Make sure the FBO bound at beginPaint is re-bound again here: QGLContext *ctx = context(); if (m_previousFBO != ctx->d_func()->current_fbo) { ctx->d_ptr->current_fbo = m_previousFBO; glBindFramebuffer(GL_FRAMEBUFFER, m_previousFBO); } ctx->d_ptr->default_fbo = 0; }
void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext) { Q_D(QGLWidget); if (context == 0) { qWarning("QGLWidget::setContext: Cannot set null context"); return; } if (!context->deviceIsPixmap() && context->device() != this) { qWarning("QGLWidget::setContext: Context must refer to this widget"); return; } if (d->glcx) d->glcx->doneCurrent(); QGLContext* oldcx = d->glcx; d->glcx = context; bool doShow = false; if (oldcx && oldcx->d_func()->win == winId() && !d->glcx->deviceIsPixmap()) { // We already have a context and must therefore create a new // window since Windows does not permit setting a new OpenGL // context for a window that already has one set. doShow = isVisible(); QWidget *pW = static_cast<QWidget *>(parent()); QPoint pos = geometry().topLeft(); setParent(pW, windowFlags()); move(pos); } if (!d->glcx->isValid()) { d->glcx->create(shareContext ? shareContext : oldcx); // the above is a trick to keep disp lists etc when a // QGLWidget has been reparented, so remove the sharing // flag if we don't actually have a sharing context. if (!shareContext) d->glcx->d_ptr->sharing = false; } if (deleteOldContext) delete oldcx; if (doShow) show(); }
bool QGLContext::chooseContext(const QGLContext* shareContext) { Q_D(QGLContext); const QX11Info *xinfo = qt_x11Info(d->paintDevice); Display* disp = xinfo->display(); d->vi = chooseVisual(); if (!d->vi) return false; if (deviceIsPixmap() && (((XVisualInfo*)d->vi)->depth != xinfo->depth() || ((XVisualInfo*)d->vi)->screen != xinfo->screen())) { XFree(d->vi); XVisualInfo appVisInfo; memset(&appVisInfo, 0, sizeof(XVisualInfo)); appVisInfo.visualid = XVisualIDFromVisual((Visual *) xinfo->visual()); appVisInfo.screen = xinfo->screen(); int nvis; d->vi = XGetVisualInfo(disp, VisualIDMask | VisualScreenMask, &appVisInfo, &nvis); if (!d->vi) return false; int useGL; glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_USE_GL, &useGL); if (!useGL) return false; //# Chickening out already... } int res; glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_LEVEL, &res); d->glFormat.setPlane(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_DOUBLEBUFFER, &res); d->glFormat.setDoubleBuffer(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_DEPTH_SIZE, &res); d->glFormat.setDepth(res); if (d->glFormat.depth()) d->glFormat.setDepthBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_RGBA, &res); d->glFormat.setRgba(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_RED_SIZE, &res); d->glFormat.setRedBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_GREEN_SIZE, &res); d->glFormat.setGreenBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_BLUE_SIZE, &res); d->glFormat.setBlueBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_ALPHA_SIZE, &res); d->glFormat.setAlpha(res); if (d->glFormat.alpha()) d->glFormat.setAlphaBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_ACCUM_RED_SIZE, &res); d->glFormat.setAccum(res); if (d->glFormat.accum()) d->glFormat.setAccumBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_STENCIL_SIZE, &res); d->glFormat.setStencil(res); if (d->glFormat.stencil()) d->glFormat.setStencilBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_STEREO, &res); d->glFormat.setStereo(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_SAMPLE_BUFFERS_ARB, &res); d->glFormat.setSampleBuffers(res); if (d->glFormat.sampleBuffers()) { glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_SAMPLES_ARB, &res); d->glFormat.setSamples(res); } Bool direct = format().directRendering() ? True : False; if (shareContext && (!shareContext->isValid() || !shareContext->d_func()->cx)) { qWarning("QGLContext::chooseContext(): Cannot share with invalid context"); shareContext = 0; } // 1. Sharing between rgba and color-index will give wrong colors. // 2. Contexts cannot be shared btw. direct/non-direct renderers. // 3. Pixmaps cannot share contexts that are set up for direct rendering. // 4. If the contexts are not created on the same screen, they can't be shared if (shareContext && (format().rgba() != shareContext->format().rgba() || (deviceIsPixmap() && glXIsDirect(disp, (GLXContext)shareContext->d_func()->cx)) || (shareContext->d_func()->screen != xinfo->screen()))) { shareContext = 0; } d->cx = 0; if (shareContext) { d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, (GLXContext)shareContext->d_func()->cx, direct); d->screen = ((XVisualInfo*)d->vi)->screen; if (d->cx) { QGLContext *share = const_cast<QGLContext *>(shareContext); d->sharing = true; share->d_func()->sharing = true; } } if (!d->cx) { d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, NULL, direct); d->screen = ((XVisualInfo*)d->vi)->screen; } if (!d->cx) return false; d->glFormat.setDirectRendering(glXIsDirect(disp, (GLXContext)d->cx)); if (deviceIsPixmap()) { #if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT) d->gpm = glXCreateGLXPixmapMESA(disp, (XVisualInfo *)d->vi, qt_x11Handle(d->paintDevice), qt_gl_choose_cmap(disp, (XVisualInfo *)d->vi)); #else d->gpm = (quint32)glXCreateGLXPixmap(disp, (XVisualInfo *)d->vi, qt_x11Handle(d->paintDevice)); #endif if (!d->gpm) return false; } QString glxExt = QString(QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS))); if (glxExt.contains(QLatin1String("GLX_SGI_video_sync"))) { if (d->glFormat.swapInterval() == -1) d->glFormat.setSwapInterval(0); } else { d->glFormat.setSwapInterval(-1); } return true; }
/***************************************************************************** QGLContext AGL-specific code *****************************************************************************/ bool QGLContext::chooseContext(const QGLContext* shareContext) { Q_D(QGLContext); d->cx = 0; d->vi = chooseMacVisual(0); if(!d->vi) return false; AGLPixelFormat fmt = (AGLPixelFormat)d->vi; GLint res; aglDescribePixelFormat(fmt, AGL_LEVEL, &res); d->glFormat.setPlane(res); if(deviceIsPixmap()) res = 0; else aglDescribePixelFormat(fmt, AGL_DOUBLEBUFFER, &res); d->glFormat.setDoubleBuffer(res); aglDescribePixelFormat(fmt, AGL_DEPTH_SIZE, &res); d->glFormat.setDepth(res); if (d->glFormat.depth()) d->glFormat.setDepthBufferSize(res); aglDescribePixelFormat(fmt, AGL_RGBA, &res); d->glFormat.setRgba(res); aglDescribePixelFormat(fmt, AGL_RED_SIZE, &res); d->glFormat.setRedBufferSize(res); aglDescribePixelFormat(fmt, AGL_GREEN_SIZE, &res); d->glFormat.setGreenBufferSize(res); aglDescribePixelFormat(fmt, AGL_BLUE_SIZE, &res); d->glFormat.setBlueBufferSize(res); aglDescribePixelFormat(fmt, AGL_ALPHA_SIZE, &res); d->glFormat.setAlpha(res); if (d->glFormat.alpha()) d->glFormat.setAlphaBufferSize(res); aglDescribePixelFormat(fmt, AGL_ACCUM_RED_SIZE, &res); // Bug in Apple OpenGL (rdr://5015603), when we don't have an accumulation // buffer, it still claims that we have a 16-bit one (which is pretty rare). // So, we just assume we can never have a buffer that small. d->glFormat.setAccum(res > 5); if (d->glFormat.accum()) d->glFormat.setAccumBufferSize(res); aglDescribePixelFormat(fmt, AGL_STENCIL_SIZE, &res); d->glFormat.setStencil(res); if (d->glFormat.stencil()) d->glFormat.setStencilBufferSize(res); aglDescribePixelFormat(fmt, AGL_STEREO, &res); d->glFormat.setStereo(res); aglDescribePixelFormat(fmt, AGL_SAMPLE_BUFFERS_ARB, &res); d->glFormat.setSampleBuffers(res); if (d->glFormat.sampleBuffers()) { aglDescribePixelFormat(fmt, AGL_SAMPLES_ARB, &res); d->glFormat.setSamples(res); } if(shareContext && (!shareContext->isValid() || !shareContext->d_func()->cx)) { qWarning("QGLContext::chooseContext(): Cannot share with invalid context"); shareContext = 0; } // sharing between rgba and color-index will give wrong colors if(shareContext && (format().rgba() != shareContext->format().rgba())) shareContext = 0; AGLContext ctx = aglCreateContext(fmt, (AGLContext) (shareContext ? shareContext->d_func()->cx : 0)); if(!ctx) { GLenum err = aglGetError(); if(err == AGL_BAD_MATCH || err == AGL_BAD_CONTEXT) { if(shareContext && shareContext->d_func()->cx) { qWarning("QGLContext::chooseContext(): Context sharing mismatch!"); if(!(ctx = aglCreateContext(fmt, 0))) return false; shareContext = 0; } } if(!ctx) { qWarning("QGLContext::chooseContext(): Unable to create QGLContext"); return false; } } d->cx = ctx; if (shareContext && shareContext->d_func()->cx) { QGLContext *share = const_cast<QGLContext *>(shareContext); d->sharing = true; share->d_func()->sharing = true; } if(deviceIsPixmap()) updatePaintDevice(); // vblank syncing GLint interval = d->reqFormat.swapInterval(); if (interval != -1) { aglSetInteger((AGLContext)d->cx, AGL_SWAP_INTERVAL, &interval); if (interval != 0) aglEnable((AGLContext)d->cx, AGL_SWAP_INTERVAL); else aglDisable((AGLContext)d->cx, AGL_SWAP_INTERVAL); } aglGetInteger((AGLContext)d->cx, AGL_SWAP_INTERVAL, &interval); d->glFormat.setSwapInterval(interval); return true; }