Example #1
0
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;
}
Example #2
0
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;
}
Example #3
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;
}
Example #5
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();
}
Example #6
0
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;
}
Example #7
0
/*****************************************************************************
  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;
}