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 |