src/opengl/qglframebufferobject.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
   338 
   338 
   339     if (QGLContextPrivate::contextGroup(fboContext) == QGLContextPrivate::contextGroup(currentContext))
   339     if (QGLContextPrivate::contextGroup(fboContext) == QGLContextPrivate::contextGroup(currentContext))
   340         return currentContext;
   340         return currentContext;
   341     else
   341     else
   342         return fboContext;
   342         return fboContext;
   343 }
       
   344 
       
   345 void QGLFBOGLPaintDevice::ensureActiveTarget()
       
   346 {
       
   347     if (QGLContext::currentContext() != context())
       
   348         context()->makeCurrent();
       
   349 
       
   350     QGLContext* ctx = const_cast<QGLContext*>(QGLContext::currentContext());
       
   351     Q_ASSERT(ctx);
       
   352     const GLuint fboId = fbo->d_func()->fbo();
       
   353     if (ctx->d_func()->current_fbo != fboId) {
       
   354         ctx->d_func()->current_fbo = fboId;
       
   355         glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
       
   356     }
       
   357 }
       
   358 
       
   359 void QGLFBOGLPaintDevice::beginPaint()
       
   360 {
       
   361     if (QGLContext::currentContext() != context())
       
   362         context()->makeCurrent();
       
   363 
       
   364     // We let QFBO track the previously bound FBO rather than doing it
       
   365     // ourselves here. This has the advantage that begin/release & bind/end
       
   366     // work as expected.
       
   367     wasBound = fbo->isBound();
       
   368     if (!wasBound)
       
   369         fbo->bind();
       
   370 }
       
   371 
       
   372 void QGLFBOGLPaintDevice::endPaint()
       
   373 {
       
   374     if (!wasBound)
       
   375         fbo->release();
       
   376 }
   343 }
   377 
   344 
   378 bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const
   345 bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const
   379 {
   346 {
   380     QGL_FUNCP_CONTEXT;
   347     QGL_FUNCP_CONTEXT;
   628     sample per pixel for primitives to be antialiased when drawing using a
   595     sample per pixel for primitives to be antialiased when drawing using a
   629     QPainter. To create a multisample framebuffer object you should use one of
   596     QPainter. To create a multisample framebuffer object you should use one of
   630     the constructors that take a QGLFramebufferObject parameter, and set the
   597     the constructors that take a QGLFramebufferObject parameter, and set the
   631     QGLFramebufferObject::samples() property to a non-zero value.
   598     QGLFramebufferObject::samples() property to a non-zero value.
   632 
   599 
       
   600     When painting to a QGLFramebufferObject using QPainter, the state of
       
   601     the current GL context will be altered by the paint engine to reflect
       
   602     its needs.  Applications should not rely upon the GL state being reset
       
   603     to its original conditions, particularly the current shader program,
       
   604     GL viewport, texture units, and drawing modes.
       
   605 
   633     For multisample framebuffer objects a color render buffer is created,
   606     For multisample framebuffer objects a color render buffer is created,
   634     otherwise a texture with the specified texture target is created.
   607     otherwise a texture with the specified texture target is created.
   635     The color render buffer or texture will have the specified internal
   608     The color render buffer or texture will have the specified internal
   636     format, and will be bound to the \c GL_COLOR_ATTACHMENT0
   609     format, and will be bound to the \c GL_COLOR_ATTACHMENT0
   637     attachment in the framebuffer object.
   610     attachment in the framebuffer object.
   877 
   850 
   878     Switches rendering from the default, windowing system provided
   851     Switches rendering from the default, windowing system provided
   879     framebuffer to this framebuffer object.
   852     framebuffer to this framebuffer object.
   880     Returns true upon success, false otherwise.
   853     Returns true upon success, false otherwise.
   881 
   854 
   882     Since 4.6: if another QGLFramebufferObject instance was already bound
       
   883     to the current context, then its handle() will be remembered and
       
   884     automatically restored when release() is called.  This allows multiple
       
   885     framebuffer rendering targets to be stacked up.  It is important that
       
   886     release() is called on the stacked framebuffer objects in the reverse
       
   887     order of the calls to bind().
       
   888 
       
   889     \sa release()
   855     \sa release()
   890 */
   856 */
   891 bool QGLFramebufferObject::bind()
   857 bool QGLFramebufferObject::bind()
   892 {
   858 {
   893     if (!isValid())
   859     if (!isValid())
   894 	return false;
   860 	return false;
   895     Q_D(QGLFramebufferObject);
   861     Q_D(QGLFramebufferObject);
   896     QGL_FUNC_CONTEXT;
   862     QGL_FUNC_CONTEXT;
   897     if (!ctx)
   863     if (!ctx)
   898         return false;   // Context no longer exists.
   864         return false;   // Context no longer exists.
       
   865     const QGLContext *current = QGLContext::currentContext();
       
   866 #ifdef QT_DEBUG
       
   867     if (!current ||
       
   868         QGLContextPrivate::contextGroup(current) != QGLContextPrivate::contextGroup(ctx))
       
   869     {
       
   870         qWarning("QGLFramebufferObject::bind() called from incompatible context");
       
   871     }
       
   872 #endif
   899     glBindFramebuffer(GL_FRAMEBUFFER_EXT, d->fbo());
   873     glBindFramebuffer(GL_FRAMEBUFFER_EXT, d->fbo());
   900     d->valid = d->checkFramebufferStatus();
   874     d->valid = d->checkFramebufferStatus();
   901     const QGLContext *context = QGLContext::currentContext();
   875     if (d->valid && current)
   902     if (d->valid && context) {
   876         current->d_ptr->current_fbo = d->fbo();
   903         Q_ASSERT(QGLContextPrivate::contextGroup(context) == QGLContextPrivate::contextGroup(ctx));
       
   904         // Save the previous setting to automatically restore in release().
       
   905         if (context->d_ptr->current_fbo != d->fbo()) {
       
   906             d->previous_fbo = context->d_ptr->current_fbo;
       
   907             context->d_ptr->current_fbo = d->fbo();
       
   908         }
       
   909     }
       
   910     return d->valid;
   877     return d->valid;
   911 }
   878 }
   912 
   879 
   913 /*!
   880 /*!
   914     \fn bool QGLFramebufferObject::release()
   881     \fn bool QGLFramebufferObject::release()
   915 
   882 
   916     Switches rendering back to the default, windowing system provided
   883     Switches rendering back to the default, windowing system provided
   917     framebuffer.
   884     framebuffer.
   918     Returns true upon success, false otherwise.
   885     Returns true upon success, false otherwise.
   919 
   886 
   920     Since 4.6: if another QGLFramebufferObject instance was already bound
       
   921     to the current context when bind() was called, then this function will
       
   922     automatically re-bind it to the current context.
       
   923 
       
   924     \sa bind()
   887     \sa bind()
   925 */
   888 */
   926 bool QGLFramebufferObject::release()
   889 bool QGLFramebufferObject::release()
   927 {
   890 {
   928     if (!isValid())
   891     if (!isValid())
   929 	return false;
   892 	return false;
   930     Q_D(QGLFramebufferObject);
       
   931     QGL_FUNC_CONTEXT;
   893     QGL_FUNC_CONTEXT;
   932     if (!ctx)
   894     if (!ctx)
   933         return false;   // Context no longer exists.
   895         return false;   // Context no longer exists.
   934 
   896 
   935     const QGLContext *context = QGLContext::currentContext();
   897     const QGLContext *current = QGLContext::currentContext();
   936     if (context) {
   898 
   937         Q_ASSERT(QGLContextPrivate::contextGroup(context) == QGLContextPrivate::contextGroup(ctx));
   899 #ifdef QT_DEBUG
   938         // Restore the previous setting for stacked framebuffer objects.
   900     if (!current ||
   939         if (d->previous_fbo != context->d_ptr->current_fbo) {
   901         QGLContextPrivate::contextGroup(current) != QGLContextPrivate::contextGroup(ctx))
   940             context->d_ptr->current_fbo = d->previous_fbo;
   902     {
   941             glBindFramebuffer(GL_FRAMEBUFFER_EXT, d->previous_fbo);
   903         qWarning("QGLFramebufferObject::release() called from incompatible context");
   942         }
   904     }
   943         d->previous_fbo = 0;
   905 #endif
       
   906 
       
   907     if (current) {
       
   908         current->d_ptr->current_fbo = current->d_ptr->default_fbo;
       
   909         glBindFramebuffer(GL_FRAMEBUFFER_EXT, current->d_ptr->default_fbo);
   944     }
   910     }
   945 
   911 
   946     return true;
   912     return true;
   947 }
   913 }
   948 
   914