diff options
Diffstat (limited to 'src/opengl/qwindowsurface_gl.cpp')
-rw-r--r-- | src/opengl/qwindowsurface_gl.cpp | 85 |
1 files changed, 73 insertions, 12 deletions
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index cdd3eb9..93e720c 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; @@ -366,6 +404,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 +474,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,9 +488,9 @@ 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) + bool swapBehaviourPreserved = (ctx->d_func()->eglContext->configAttrib(EGL_SWAP_BEHAVIOR) + || (ctx->d_func()->eglContext->configAttrib(EGL_SURFACE_TYPE)&EGL_SWAP_BEHAVIOR_PRESERVED_BIT)); + if (!swapBehaviourPreserved && !haveNOKSwapRegion) setPartialUpdateSupport(false); // Force full-screen updates else setPartialUpdateSupport(true); @@ -444,7 +506,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 @@ -825,11 +889,7 @@ void QGLWindowSurface::updateGeometry() { ctx->updatePaintDevice(); #endif -#ifdef Q_WS_QPA - QSize surfSize = size(); -#else QSize surfSize = geometry().size(); -#endif if (surfSize.width() <= 0 || surfSize.height() <= 0) return; @@ -947,8 +1007,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; } |