From 8669823d5a5c0f26ff3909ad9c83fa99a63a89f3 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 23 Apr 2010 15:08:17 +0200 Subject: Force full-screen updates for QGLWindowSurface If the back buffer is destroyed when swap buffers is called, we must tell the backing store any update needs to invalidate the entire window surface, so everything gets re-drawn. Task-number: QTBUG-9978 Reviewed-By: Trond --- src/opengl/qwindowsurface_gl.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index b693245..bcb96fa 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -82,7 +82,7 @@ #define GLX_SAMPLES_ARB 100001 #endif -#ifdef QT_OPENGL_ES +#ifndef QT_NO_EGL #include #endif @@ -354,6 +354,11 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) QGLContext *ctx = new QGLContext(surfaceFormat, widget); ctx->create(qt_gl_share_widget()->context()); +#ifndef QT_NO_EGL + if (ctx->d_func()->eglContext->configAttrib(EGL_SWAP_BEHAVIOR) != EGL_BUFFER_PRESERVED) + setPartialUpdateSupport(false); // Force full-screen updates +#endif + widgetPrivate->extraData()->glContext = ctx; union { QGLContext **ctxPtr; void **voidPtr; }; -- cgit v0.12 From 372392153a2c1de69d9257753ba84f44cbbd9cf1 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 23 Apr 2010 15:24:19 +0200 Subject: Enable QX11GLWindowSurface using "-graphicssystem x11gl" option When the OpenGL graphics system is in X11GL mode, it will use the QX11GLWindowSurface for all widgets except QGraphicsViews with the FullViewportUpdate update mode set, where it will use the regular QGLWindowSurface, as this is probabbly faster. QX11GLWindowSurface differs from QGLWindowSurface because it allows accelerated scrolling and partial updates, while still being using opengl to do rendering. Task-number: QT-280 Task-number: QT-2625 Reviewed-By: Trond --- src/opengl/qgraphicssystem_gl.cpp | 22 ++++++++++++++-------- src/opengl/qgraphicssystem_gl_p.h | 4 +++- src/opengl/qpixmapdata_x11gl_egl.cpp | 16 +++++++--------- src/opengl/qwindowsurface_gl.cpp | 4 ++-- src/plugins/graphicssystems/opengl/main.cpp | 14 +++++++++++--- 5 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/opengl/qgraphicssystem_gl.cpp b/src/opengl/qgraphicssystem_gl.cpp index a282e4c..58cc28a 100644 --- a/src/opengl/qgraphicssystem_gl.cpp +++ b/src/opengl/qgraphicssystem_gl.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qgraphicssystem_gl_p.h" +#include #include "private/qpixmap_raster_p.h" #include "private/qpixmapdata_gl_p.h" @@ -47,7 +48,7 @@ #include "private/qgl_p.h" #include -#if defined(Q_WS_X11) && defined(QT_OPENGL_ES) +#if defined(Q_WS_X11) && !defined(QT_NO_EGL) #include "private/qpixmapdata_x11gl_p.h" #include "private/qwindowsurface_x11gl_p.h" #endif @@ -58,10 +59,6 @@ extern QGLWidget *qt_gl_getShareWidget(); QPixmapData *QGLGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const { -#if defined(Q_WS_X11) && defined(QT_OPENGL_ES) - if (type == QPixmapData::PixmapType && QX11GLPixmapData::hasX11GLPixmaps()) - return new QX11GLPixmapData(); -#endif return new QGLPixmapData(type); } @@ -75,9 +72,18 @@ QWindowSurface *QGLGraphicsSystem::createWindowSurface(QWidget *widget) const return new QRasterWindowSurface(widget); #endif -#if defined(Q_WS_X11) && defined(QT_OPENGL_ES) - if (QX11GLPixmapData::hasX11GLPixmaps()) - return new QX11GLWindowSurface(widget); +#if defined(Q_WS_X11) && !defined(QT_NO_EGL) + if (m_useX11GL && QX11GLPixmapData::hasX11GLPixmaps()) { + // If the widget is a QGraphicsView which will be re-drawing the entire + // scene each frame anyway, we should use QGLWindowSurface as this may + // provide proper buffer flipping, which should be faster than QX11GL's + // blitting approach: + QGraphicsView* qgv = qobject_cast(widget); + if (qgv && qgv->viewportUpdateMode() == QGraphicsView::FullViewportUpdate) + return new QGLWindowSurface(widget); + else + return new QX11GLWindowSurface(widget); + } #endif return new QGLWindowSurface(widget); diff --git a/src/opengl/qgraphicssystem_gl_p.h b/src/opengl/qgraphicssystem_gl_p.h index ff47854..9d2d506 100644 --- a/src/opengl/qgraphicssystem_gl_p.h +++ b/src/opengl/qgraphicssystem_gl_p.h @@ -62,10 +62,12 @@ QT_BEGIN_NAMESPACE class Q_OPENGL_EXPORT QGLGraphicsSystem : public QGraphicsSystem { public: - QGLGraphicsSystem(); + QGLGraphicsSystem(bool useX11GL); QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QWindowSurface *createWindowSurface(QWidget *widget) const; +private: + bool m_useX11GL; }; QT_END_NAMESPACE diff --git a/src/opengl/qpixmapdata_x11gl_egl.cpp b/src/opengl/qpixmapdata_x11gl_egl.cpp index 58d34fc..e0c274a 100644 --- a/src/opengl/qpixmapdata_x11gl_egl.cpp +++ b/src/opengl/qpixmapdata_x11gl_egl.cpp @@ -216,18 +216,16 @@ QX11GLSharedContexts* QX11GLPixmapData::sharedContexts() bool QX11GLPixmapData::hasX11GLPixmaps() { - static bool checkedForX11Pixmaps = false; - static bool haveX11Pixmaps = false; + static bool checkedForX11GLPixmaps = false; + static bool haveX11GLPixmaps = false; - if (checkedForX11Pixmaps) - return haveX11Pixmaps; + if (checkedForX11GLPixmaps) + return haveX11GLPixmaps; - checkedForX11Pixmaps = true; + checkedForX11GLPixmaps = true; + haveX11GLPixmaps = sharedContexts()->isValid(); - if (!qgetenv("QT_USE_X11GL_PIXMAPS").isEmpty() && sharedContexts()->isValid()) - haveX11Pixmaps = true; - - return haveX11Pixmaps; + return haveX11GLPixmaps; } QX11GLPixmapData::QX11GLPixmapData() diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index bcb96fa..92a347b 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -94,8 +94,8 @@ QT_BEGIN_NAMESPACE #ifdef Q_WS_WIN extern Q_GUI_EXPORT bool qt_win_owndc_required; #endif -QGLGraphicsSystem::QGLGraphicsSystem() - : QGraphicsSystem() +QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL) + : QGraphicsSystem(), m_useX11GL(useX11GL) { QGLWindowSurface::surfaceFormat.setSampleBuffers(true); #if defined(Q_WS_X11) && !defined(QT_OPENGL_ES) diff --git a/src/plugins/graphicssystems/opengl/main.cpp b/src/plugins/graphicssystems/opengl/main.cpp index abcfb7f..4c740ca 100644 --- a/src/plugins/graphicssystems/opengl/main.cpp +++ b/src/plugins/graphicssystems/opengl/main.cpp @@ -59,6 +59,9 @@ QStringList QGLGraphicsSystemPlugin::keys() const #if !defined(QT_OPENGL_ES_1) list << QLatin1String("OpenGL2"); #endif +#if defined(Q_WS_X11) && !defined(QT_NO_EGL) + list << QLatin1String("X11GL"); +#endif return list; } @@ -66,18 +69,23 @@ QGraphicsSystem* QGLGraphicsSystemPlugin::create(const QString& system) { if (system.toLower() == QLatin1String("opengl1")) { QGL::setPreferredPaintEngine(QPaintEngine::OpenGL); - return new QGLGraphicsSystem; + return new QGLGraphicsSystem(false); } #if !defined(QT_OPENGL_ES_1) if (system.toLower() == QLatin1String("opengl2")) { QGL::setPreferredPaintEngine(QPaintEngine::OpenGL2); - return new QGLGraphicsSystem; + return new QGLGraphicsSystem(false); } #endif +#if defined(Q_WS_X11) && !defined(QT_NO_EGL) + if (system.toLower() == QLatin1String("x11gl")) + return new QGLGraphicsSystem(true); +#endif + if (system.toLower() == QLatin1String("opengl")) - return new QGLGraphicsSystem; + return new QGLGraphicsSystem(false); return 0; } -- cgit v0.12 From bdd7372edf4cb64177e97ef6087a6ec2a4903225 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 23 Apr 2010 17:21:39 +0200 Subject: Don't leak objects if QX11GLSharedContexts is instanciated twice If two threads call the Q_GLOBAL_STATIC accessor at the same time, two QX11GLSharedContexts objects can be created with one being destroyed. Reviewed-By: TrustMe --- src/opengl/qpixmapdata_x11gl_egl.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/opengl/qpixmapdata_x11gl_egl.cpp b/src/opengl/qpixmapdata_x11gl_egl.cpp index e0c274a..2c11a0b 100644 --- a/src/opengl/qpixmapdata_x11gl_egl.cpp +++ b/src/opengl/qpixmapdata_x11gl_egl.cpp @@ -74,7 +74,6 @@ public: EGLint rgbConfigId; EGLint argbConfigId; - do { EGLConfig rgbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, QEgl::Renderable); EGLConfig argbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, @@ -138,6 +137,7 @@ public: valid = argbContext->makeCurrent(argbPixmapSurface); argbContext->doneCurrent(); eglDestroySurface(QEgl::display(), argbPixmapSurface); + argbPixmapData->gl_surface = 0; } if (!valid) { @@ -150,7 +150,6 @@ public: QGLTextureCache::instance(); } while(0); - if (!valid) cleanup(); else @@ -158,6 +157,10 @@ public: } + ~QX11GLSharedContexts() { + cleanup(); + } + void cleanup() { if (sharedQGLContext) { delete sharedQGLContext; @@ -222,8 +225,8 @@ bool QX11GLPixmapData::hasX11GLPixmaps() if (checkedForX11GLPixmaps) return haveX11GLPixmaps; + haveX11GLPixmaps = qt_x11gl_share_contexts()->isValid(); checkedForX11GLPixmaps = true; - haveX11GLPixmaps = sharedContexts()->isValid(); return haveX11GLPixmaps; } -- cgit v0.12