From f79d96b486c1dd50876001b9c3f65d103e07a18c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= <srodal@gmail.com> Date: Tue, 4 Nov 2014 20:24:38 +0100 Subject: [PATCH] Fixed QtGui's GL paint engine getting out of sync when using QtOpenGL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to reset the active_engine belonging to QOpenGLContext whenever we make the QtOpenGL paint engine active, to give the OpenGL paint engine in QtGui a chance to sync its state if we've used the QtOpenGL paint engine inbetween. Change-Id: I445ce2f99bfbacf55650c881c4fdf07f2ff85069 Reviewed-by: Jørgen Lind <jorgen.lind@digia.com> --- .../qpaintengineex_opengl2.cpp | 21 ++++++++++++++- .../qpaintengineex_opengl2_p.h | 1 + tests/auto/opengl/qgl/tst_qgl.cpp | 27 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 43df3116364..1fa5723d85a 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 528bfdeeb98..ac1d63df17d 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/tests/auto/opengl/qgl/tst_qgl.cpp b/tests/auto/opengl/qgl/tst_qgl.cpp index d8ad3e1470c..56198ceb650 100644 --- a/tests/auto/opengl/qgl/tst_qgl.cpp +++ b/tests/auto/opengl/qgl/tst_qgl.cpp @@ -1200,6 +1200,33 @@ void tst_QGL::currentFboSync() QCOMPARE(fbo1.toImage(), fbo2Image); } + + { + QGLFramebufferObject fbo1(512, 512, QGLFramebufferObject::CombinedDepthStencil); + + QOpenGLFramebufferObjectPaintDevice fbo2(256, 256); + + QImage sourceImage(256, 256, QImage::Format_ARGB32_Premultiplied); + QPainter sourcePainter(&sourceImage); + qt_opengl_draw_test_pattern(&sourcePainter, 256, 256); + + QPainter fbo2Painter(&fbo2); + fbo2Painter.drawImage(0, 0, sourceImage); + QImage fbo2Image1 = fbo2.toImage(); + fbo2Painter.fillRect(0, 0, 256, 256, Qt::white); + + QPainter fbo1Painter(&fbo1); + fbo1Painter.drawImage(0, 0, sourceImage); + fbo1Painter.end(); + + // check that the OpenGL paint engine now knows it needs to sync + fbo2Painter.drawImage(0, 0, sourceImage); + QImage fbo2Image2 = fbo2.toImage(); + + fbo2Painter.end(); + + QCOMPARE(fbo2Image1, fbo2Image2); + } } // Tests multiple QPainters active on different FBOs at the same time, with -- GitLab