diff options
Diffstat (limited to 'src/opengl/qwindowsurface_gl.cpp')
-rw-r--r-- | src/opengl/qwindowsurface_gl.cpp | 95 |
1 files changed, 84 insertions, 11 deletions
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 21b2f09..2ccbc50 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -181,17 +181,15 @@ QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL) // // QGLWindowSurface // - #ifndef Q_WS_QPA class QGLGlobalShareWidget { public: - QGLGlobalShareWidget() : widget(0), initializing(false) {} + QGLGlobalShareWidget() : firstPixmap(0), widgetRefCount(0), widget(0), initializing(false) {} QGLWidget *shareWidget() { if (!initializing && !widget && !cleanedUp) { initializing = true; - widget = new QGLWidget(QGLFormat(QGL::SingleBuffer | QGL::NoDepthBuffer | QGL::NoStencilBuffer)); widget->resize(1, 1); @@ -227,6 +225,9 @@ public: static bool cleanedUp; + QGLPixmapData *firstPixmap; + int widgetRefCount; + private: QGLWidget *widget; bool initializing; @@ -274,6 +275,43 @@ const QGLContext *qt_gl_share_context() #endif } +#ifdef QGL_USE_TEXTURE_POOL +void qt_gl_register_pixmap(QGLPixmapData *pd) +{ + QGLGlobalShareWidget *shared = _qt_gl_share_widget(); + pd->next = shared->firstPixmap; + pd->prev = 0; + if (shared->firstPixmap) + shared->firstPixmap->prev = pd; + shared->firstPixmap = pd; +} + +void qt_gl_unregister_pixmap(QGLPixmapData *pd) +{ + if (pd->next) + pd->next->prev = pd->prev; + if (pd->prev) { + pd->prev->next = pd->next; + } else { + QGLGlobalShareWidget *shared = _qt_gl_share_widget(); + if (shared) + shared->firstPixmap = pd->next; + } +} + +void qt_gl_hibernate_pixmaps() +{ + QGLGlobalShareWidget *shared = _qt_gl_share_widget(); + + // Scan all QGLPixmapData objects in the system and hibernate them. + QGLPixmapData *pd = shared->firstPixmap; + while (pd != 0) { + pd->hibernate(); + pd = pd->next; + } +} +#endif + struct QGLWindowSurfacePrivate { QGLFramebufferObject *fbo; @@ -299,6 +337,8 @@ struct QGLWindowSurfacePrivate QList<QImage> buffers; QGLWindowSurfaceGLPaintDevice glDevice; QGLWindowSurface* q_ptr; + + bool partialUpdateSupport; }; QGLFormat QGLWindowSurface::surfaceFormat; @@ -351,6 +391,7 @@ QGLWindowSurface::QGLWindowSurface(QWidget *window) d_ptr->q_ptr = this; d_ptr->geometry_updated = false; d_ptr->did_paint = false; + d_ptr->partialUpdateSupport = false; } QGLWindowSurface::~QGLWindowSurface() @@ -366,6 +407,27 @@ QGLWindowSurface::~QGLWindowSurface() delete d_ptr->pb; delete d_ptr->fbo; delete d_ptr; + + if (QGLGlobalShareWidget::cleanedUp) + return; + + --(_qt_gl_share_widget()->widgetRefCount); + +#ifdef QGL_USE_TEXTURE_POOL + if (_qt_gl_share_widget()->widgetRefCount <= 0) { + // All of the widget window surfaces have been destroyed + // but we still have GL pixmaps active. Ask them to hibernate + // to free up GPU resources until a widget is shown again. + // This may eventually cause the EGLContext to be destroyed + // because nothing in the system needs a context, which will + // free up even more GPU resources. + qt_gl_hibernate_pixmaps(); + + // Destroy the context if necessary. + if (!qt_gl_share_widget()->context()->isSharing()) + qt_destroy_gl_share_widget(); + } +#endif } void QGLWindowSurface::deleted(QObject *object) @@ -415,6 +477,9 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) ctx->create(qt_gl_share_context()); + if (widget != qt_gl_share_widget()) + ++(_qt_gl_share_widget()->widgetRefCount); + #ifndef QT_NO_EGL static bool checkedForNOKSwapRegion = false; static bool haveNOKSwapRegion = false; @@ -426,14 +491,14 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) if (haveNOKSwapRegion) qDebug() << "Found EGL_NOK_swap_region2 extension. Using partial updates."; } - - if (ctx->d_func()->eglContext->configAttrib(EGL_SWAP_BEHAVIOR) != EGL_BUFFER_PRESERVED && - ! haveNOKSwapRegion) - setPartialUpdateSupport(false); // Force full-screen updates + bool swapBehaviourPreserved = (ctx->d_func()->eglContext->configAttrib(EGL_SWAP_BEHAVIOR) != EGL_BUFFER_PRESERVED) + || (ctx->d_func()->eglContext->configAttrib(EGL_SURFACE_TYPE)&EGL_SWAP_BEHAVIOR_PRESERVED_BIT); + if (!swapBehaviourPreserved && !haveNOKSwapRegion) + d_ptr->partialUpdateSupport = false; // Force full-screen updates else - setPartialUpdateSupport(true); + d_ptr->partialUpdateSupport = true; #else - setPartialUpdateSupport(false); + d_ptr->partialUpdateSupport = false; #endif widgetPrivate->extraData()->glContext = ctx; @@ -444,7 +509,9 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) voidPtrPtr = &widgetPrivate->extraData()->glContext; d_ptr->contexts << ctxPtrPtr; +#ifndef Q_OS_SYMBIAN qDebug() << "hijackWindow() context created for" << widget << d_ptr->contexts.size(); +#endif } QGLContext *QGLWindowSurface::context() const @@ -943,8 +1010,9 @@ void QGLWindowSurface::updateGeometry() { if (d_ptr->destructive_swap_buffers) initializeOffscreenTexture(surfSize); #endif - - qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this;; +#ifndef Q_OS_SYMBIAN + qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this; +#endif d_ptr->ctx = ctx; d_ptr->ctx->d_ptr->internal_context = true; } @@ -1081,6 +1149,11 @@ QImage *QGLWindowSurface::buffer(const QWidget *widget) return &d_ptr->buffers.last(); } +bool QGLWindowSurface::hasPartialUpdateSupport() const +{ + return d_ptr->partialUpdateSupport; +} + QT_END_NAMESPACE |