diff options
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 21 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h | 1 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp | 2 | ||||
-rw-r--r-- | src/opengl/qgl.cpp | 29 | ||||
-rw-r--r-- | src/opengl/qgl_p.h | 2 | ||||
-rw-r--r-- | src/opengl/qglframebufferobject.cpp | 31 | ||||
-rw-r--r-- | src/opengl/qglpaintdevice.cpp | 13 | ||||
-rw-r--r-- | src/opengl/qglpixelbuffer.cpp | 2 |
8 files changed, 93 insertions, 8 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 43df311636..1fa5723d85 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -612,6 +612,21 @@ void QGL2PaintEngineExPrivate::resetGLState() #endif } +bool QGL2PaintEngineExPrivate::resetOpenGLContextActiveEngine() +{ + QOpenGLContext *guiGlContext = ctx->contextHandle(); + QOpenGLContextPrivate *guiGlContextPrivate = + guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0; + + if (guiGlContextPrivate && guiGlContextPrivate->active_engine) { + ctx->d_func()->refreshCurrentFbo(); + guiGlContextPrivate->active_engine = 0; + return true; + } + + return false; +} + void QGL2PaintEngineEx::endNativePainting() { Q_D(QGL2PaintEngineEx); @@ -2015,6 +2030,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->ctx = d->device->context(); d->ctx->d_ptr->active_engine = this; + d->resetOpenGLContextActiveEngine(); + const QSize sz = d->device->size(); d->width = sz.width(); d->height = sz.height(); @@ -2080,6 +2097,8 @@ bool QGL2PaintEngineEx::end() ctx->d_ptr->active_engine = 0; + d->resetOpenGLContextActiveEngine(); + d->resetGLState(); delete d->shaderManager; @@ -2105,7 +2124,7 @@ void QGL2PaintEngineEx::ensureActive() Q_D(QGL2PaintEngineEx); QGLContext *ctx = d->ctx; - if (isActive() && ctx->d_ptr->active_engine != this) { + if (isActive() && (ctx->d_ptr->active_engine != this || d->resetOpenGLContextActiveEngine())) { ctx->d_ptr->active_engine = this; d->needsSync = true; } diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 528bfdeeb9..ac1d63df17 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -191,6 +191,7 @@ public: void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1)); void resetGLState(); + bool resetOpenGLContextActiveEngine(); // fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points, // however writeClip can also be thought of as en entry point as it does similar things. diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index 211fad267f..8cd26f1ea4 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -167,6 +167,8 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) // ### the QTextureGlyphCache API needs to be reworked to allow // ### resizeTextureData to fail + ctx->d_ptr->refreshCurrentFbo(); + funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_textureResource->m_fbo); GLuint tmp_texture; diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 1e49d95087..35f08e0092 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -510,6 +510,35 @@ void QGLContextPrivate::setupSharing() { } } +void QGLContextPrivate::refreshCurrentFbo() +{ + QOpenGLContextPrivate *guiGlContextPrivate = + guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0; + + // if QOpenGLFramebufferObjects have been used in the mean-time, we've lost our cached value + if (guiGlContextPrivate && guiGlContextPrivate->qgl_current_fbo_invalid) { + GLint current; + QOpenGLFunctions *funcs = qgl_functions(); + funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤t); + + current_fbo = current; + + guiGlContextPrivate->qgl_current_fbo_invalid = false; + } +} + +void QGLContextPrivate::setCurrentFbo(GLuint fbo) +{ + current_fbo = fbo; + + QOpenGLContextPrivate *guiGlContextPrivate = + guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0; + + if (guiGlContextPrivate) + guiGlContextPrivate->qgl_current_fbo_invalid = false; +} + + /*! \fn bool QGLFormat::doubleBuffer() const diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index c4151a3d34..4cf656fd86 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -238,6 +238,8 @@ public: bool ownContext; void setupSharing(); + void refreshCurrentFbo(); + void setCurrentFbo(GLuint fbo); QGLFormat glFormat; QGLFormat reqFormat; diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 4ef50e9334..4537f5bfae 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -472,6 +472,8 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers)) return; + ctx->d_ptr->refreshCurrentFbo(); + size = sz; target = texture_target; // texture dimensions @@ -1027,7 +1029,7 @@ bool QGLFramebufferObject::bind() d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo()); d->valid = d->checkFramebufferStatus(); if (d->valid && current) - current->d_ptr->current_fbo = d->fbo(); + current->d_ptr->setCurrentFbo(d->fbo()); return d->valid; } @@ -1060,7 +1062,7 @@ bool QGLFramebufferObject::release() #endif if (current) { - current->d_ptr->current_fbo = current->d_ptr->default_fbo; + current->d_ptr->setCurrentFbo(current->d_ptr->default_fbo); d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_ptr->default_fbo); } @@ -1109,6 +1111,20 @@ QGLFramebufferObjectFormat QGLFramebufferObject::format() const Returns the contents of this framebuffer object as a QImage. + The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used + only when internalTextureFormat() is set to \c GL_RGB. + + If the rendering in the framebuffer was not done with premultiplied alpha in mind, + create a wrapper QImage with a non-premultiplied format. This is necessary before + performing operations like QImage::save() because otherwise the image data would get + unpremultiplied, even though it was not premultiplied in the first place. To create + such a wrapper without performing a copy of the pixel data, do the following: + + \code + QImage fboImage(fbo.toImage()); + QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32); + \endcode + On QNX the back buffer is not preserved when a buffer swap occures. So this function might return old content. */ @@ -1173,7 +1189,7 @@ bool QGLFramebufferObject::bindDefault() if (!functions.hasOpenGLFeature(QOpenGLFunctions::Framebuffers)) return false; - ctx->d_ptr->current_fbo = ctx->d_ptr->default_fbo; + ctx->d_ptr->setCurrentFbo(ctx->d_ptr->default_fbo); functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->default_fbo); #ifdef QT_DEBUG } else { @@ -1320,7 +1336,12 @@ bool QGLFramebufferObject::isBound() const { Q_D(const QGLFramebufferObject); const QGLContext *current = QGLContext::currentContext(); - return current ? current->d_ptr->current_fbo == d->fbo() : false; + if (current) { + current->d_ptr->refreshCurrentFbo(); + return current->d_ptr->current_fbo == d->fbo(); + } + + return false; } /*! @@ -1400,6 +1421,8 @@ void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const Q const int ty0 = th - (targetRect.top() + targetRect.height()); const int ty1 = th - targetRect.top(); + ctx->d_ptr->refreshCurrentFbo(); + functions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : 0); functions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : 0); diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp index 40cc7bb71d..c07d0a761b 100644 --- a/src/opengl/qglpaintdevice.cpp +++ b/src/opengl/qglpaintdevice.cpp @@ -74,6 +74,8 @@ void QGLPaintDevice::beginPaint() 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 // @@ -85,7 +87,7 @@ void QGLPaintDevice::beginPaint() m_previousFBO = ctx->d_func()->current_fbo; if (m_previousFBO != m_thisFBO) { - ctx->d_ptr->current_fbo = m_thisFBO; + ctx->d_func()->setCurrentFbo(m_thisFBO); ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO); } @@ -102,8 +104,10 @@ void QGLPaintDevice::ensureActiveTarget() if (ctx != QGLContext::currentContext()) ctx->makeCurrent(); + ctx->d_func()->refreshCurrentFbo(); + if (ctx->d_ptr->current_fbo != m_thisFBO) { - ctx->d_ptr->current_fbo = m_thisFBO; + ctx->d_func()->setCurrentFbo(m_thisFBO); ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO); } @@ -114,8 +118,11 @@ 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_ptr->current_fbo = m_previousFBO; + ctx->d_func()->setCurrentFbo(m_previousFBO); ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_previousFBO); } diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 56bfaebe4f..63b624aea2 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -344,6 +344,8 @@ void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const QOpenGLExtensions extensions(ctx->contextHandle()); + ctx->d_ptr->refreshCurrentFbo(); + if (d->blit_fbo) { QOpenGLFramebufferObject::blitFramebuffer(d->blit_fbo, d->fbo); extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, d->blit_fbo->handle()); |