From b7763c4cfab8df6ae9445f791442c14f1ae739ba Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 3 Dec 2013 14:55:40 +0100 Subject: Release GL resources of ShaderEffectSource while we still have GL. When a Window element is used, the QML window item is deleted before the ShaderEffectSource component and the deleteLater to delete the texture gets handled too late. We now register for the sceneGraphInvalidated signal and release resources synchronously while shutting down. Task-number: QTBUG-35294 Change-Id: Id83b669ddc16723551e5612264ccbad6d3a9bbcb Reviewed-by: Laszlo Agocs Reviewed-by: J-P Nurmi --- src/quick/items/qquickshadereffectsource.cpp | 15 ++++++++++++--- src/quick/items/qquickshadereffectsource_p.h | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index e076a342df..98203c51e5 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -158,16 +158,24 @@ QQuickShaderEffectTexture::QQuickShaderEffectTexture(QQuickItem *shaderSource) QQuickShaderEffectTexture::~QQuickShaderEffectTexture() { - if (m_renderer) - disconnect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture())); + invalidated(); +} + +void QQuickShaderEffectTexture::invalidated() +{ delete m_renderer; + m_renderer = 0; delete m_fbo; delete m_secondaryFbo; + m_fbo = m_secondaryFbo = 0; #ifdef QSG_DEBUG_FBO_OVERLAY delete m_debugOverlay; + m_debugOverlay = 0; #endif - if (m_transparentTexture) + if (m_transparentTexture) { glDeleteTextures(1, &m_transparentTexture); + m_transparentTexture = 0; + } } int QQuickShaderEffectTexture::textureId() const @@ -609,6 +617,7 @@ void QQuickShaderEffectSource::ensureTexture() "Cannot be used outside the rendering thread"); m_texture = new QQuickShaderEffectTexture(this); + connect(QQuickItemPrivate::get(this)->window, SIGNAL(sceneGraphInvalidated()), m_texture, SLOT(invalidated()), Qt::DirectConnection); connect(m_texture, SIGNAL(updateRequested()), this, SLOT(update())); connect(m_texture, SIGNAL(scheduledUpdateCompleted()), this, SIGNAL(scheduledUpdateCompleted())); } diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h index 6218775700..efa963fe64 100644 --- a/src/quick/items/qquickshadereffectsource_p.h +++ b/src/quick/items/qquickshadereffectsource_p.h @@ -124,6 +124,7 @@ Q_SIGNALS: public Q_SLOTS: void markDirtyTexture(); + void invalidated(); private: void grab(); -- cgit v1.2.3 From 568c575b97940e6afa5015ef2566d8316aa22cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 3 Dec 2013 14:34:05 +0100 Subject: Revert "Load "@2x" images on high-dpi "retina" systems." MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 707bbe5dea9d7398b205124a54422f2fafb6f151. By itself this is completely broken and the image will display at twice the size. We need to add code to handle the @2x image but revert for now to get sane behavior. Change-Id: Iccdb26e9d19930b5d0ef4b6c7f596c5766f77a8a Reviewed-by: Tor Arne Vestbø --- src/quick/util/qquickpixmapcache.cpp | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'src/quick') diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index 26258fdc5f..082d640ab9 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -1033,17 +1033,6 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q if (localFile.isEmpty()) return 0; - // check for "retina" high-dpi and use @2x file if it exixts - if (qApp->devicePixelRatio() > 1) { - const int dotIndex = localFile.lastIndexOf(QLatin1Char('.')); - if (dotIndex != -1) { - QString retinaFile = localFile; - retinaFile.insert(dotIndex, QStringLiteral("@2x")); - if (QFile(retinaFile).exists()) - localFile = retinaFile; - } - } - QFile f(localFile); QSize readSize; QString errorString; -- cgit v1.2.3 From 5006158e4d20ac35d64bc7a581c9966401254002 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 4 Dec 2013 10:20:22 +0100 Subject: Don't leave the GL context current after cleanup. When shutting down, we left the gl context current on the window even when it was hidden. On mac this was a problem as it would optimize away our makeCurrent when the surface was made visible again, leading to nothing being rendered. So we call doneCurrent regardless during invalidateGL(). We also check and verify that makeCurrent in invalidateGL() actually succeeds. This lead to another problem which is that closing the app using [x] will call QWindow::destroy() on all windows, removing their platform windows and causing makeCurrent to fail. To still gracefully clean up resources, we introduced the concept of an offscreen fallback surface which is temporarirly used during the cleanup when needed. The problem is still present on QWindow+QOpenGLContext level, and I've opened QTBUG-35363 to fix this. Task-number: QTBUG-35234 Change-Id: Ie76dbe5fd4ab935db3da34f3ff63d217a3ba5013 Reviewed-by: Laszlo Agocs --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 52 +++++++++++++++++--------- 1 file changed, 34 insertions(+), 18 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index acd07cf6cd..d6a3881086 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -48,6 +48,7 @@ #include #include +#include #include #include @@ -205,12 +206,14 @@ public: class WMTryReleaseEvent : public WMWindowEvent { public: - WMTryReleaseEvent(QQuickWindow *win, bool destroy) + WMTryReleaseEvent(QQuickWindow *win, bool destroy, QOffscreenSurface *fallback) : WMWindowEvent(win, WM_TryRelease) , inDestructor(destroy) + , fallbackSurface(fallback) {} bool inDestructor; + QOffscreenSurface *fallbackSurface; }; class WMExposeEvent : public WMWindowEvent @@ -295,7 +298,7 @@ public: delete sgrc; } - void invalidateOpenGL(QQuickWindow *window, bool inDestructor); + void invalidateOpenGL(QQuickWindow *window, bool inDestructor, QOffscreenSurface *backupSurface); void initializeOpenGL(); bool event(QEvent *); @@ -362,17 +365,9 @@ bool QSGRenderThread::event(QEvent *e) case WM_Expose: { QSG_RT_DEBUG("WM_Expose"); WMExposeEvent *se = static_cast(e); - - pendingUpdate |= RepaintRequest; - Q_ASSERT(!window || window == se->window); - + pendingUpdate |= RepaintRequest; windowSize = se->size; - if (window) { - QSG_RT_DEBUG(" - window already added..."); - return true; - } - window = se->window; return true; } @@ -383,7 +378,7 @@ bool QSGRenderThread::event(QEvent *e) mutex.lock(); if (window) { - QSG_RT_DEBUG(" - removed one..."); + QSG_RT_DEBUG(" - removed window..."); window = 0; } waitCondition.wakeOne(); @@ -405,7 +400,7 @@ bool QSGRenderThread::event(QEvent *e) WMTryReleaseEvent *wme = static_cast(e); if (!window || wme->inDestructor) { QSG_RT_DEBUG(" - setting exit flag and invalidating GL"); - invalidateOpenGL(wme->window, wme->inDestructor); + invalidateOpenGL(wme->window, wme->inDestructor, wme->fallbackSurface); active = gl; if (sleeping) stopEventProcessing = true; @@ -453,7 +448,7 @@ bool QSGRenderThread::event(QEvent *e) return QThread::event(e); } -void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor) +void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor, QOffscreenSurface *fallback) { QSG_RT_DEBUG("invalidateOpenGL()"); @@ -469,7 +464,13 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor) bool wipeSG = inDestructor || !window->isPersistentSceneGraph(); bool wipeGL = inDestructor || (wipeSG && !window->isPersistentOpenGLContext()); - gl->makeCurrent(window); + bool current = gl->makeCurrent(fallback ? static_cast(fallback) : static_cast(window)); + if (!current) { +#ifndef QT_NO_DEBUG + qWarning() << "Scene Graph failed to acquire GL context during cleanup"; +#endif + return; + } // The canvas nodes must be cleaned up regardless if we are in the destructor.. if (wipeSG) { @@ -477,6 +478,7 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor) dd->cleanupNodesOnShutdown(); } else { QSG_RT_DEBUG(" - persistent SG, avoiding cleanup"); + gl->doneCurrent(); return; } @@ -510,7 +512,6 @@ void QSGRenderThread::sync() if (windowSize.width() > 0 && windowSize.height() > 0) current = gl->makeCurrent(window); if (current) { - gl->makeCurrent(window); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); bool hadRenderer = d->renderer != 0; d->syncSceneGraph(); @@ -528,7 +529,6 @@ void QSGRenderThread::sync() QSG_RT_DEBUG(" - window has bad size, waiting..."); } - QSG_RT_DEBUG(" - window has bad size, waiting..."); waitCondition.wakeOne(); mutex.unlock(); } @@ -1036,9 +1036,25 @@ void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestru w->thread->mutex.lock(); if (w->thread->isRunning() && w->thread->active) { + + // The platform window might have been destroyed before + // hide/release/windowDestroyed is called, so we need to have a + // fallback surface to perform the cleanup of the scene graph + // and the OpenGL resources. + // QOffscreenSurface must be created on the GUI thread, so we + // create it here and pass it on to QSGRenderThread::invalidateGL() + QOffscreenSurface *fallback = 0; + if (!window->handle()) { + QSG_GUI_DEBUG(w->window, " - using fallback surface"); + fallback = new QOffscreenSurface(); + fallback->create(); + } + QSG_GUI_DEBUG(w->window, " - posting release request to render thread"); - w->thread->postEvent(new WMTryReleaseEvent(window, inDestructor)); + w->thread->postEvent(new WMTryReleaseEvent(window, inDestructor, fallback)); w->thread->waitCondition.wait(&w->thread->mutex); + + delete fallback; } w->thread->mutex.unlock(); } -- cgit v1.2.3 From 9baa5dac228607c91685bbd74b3f5f069cb374bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 5 Dec 2013 15:22:56 +0100 Subject: Fix broken visibility property assignment after d0644b040e Task-number: QTBUG-35412 Change-Id: I09feca09030a2eb07aa1abebf65481d68b880c79 Reviewed-by: Simon Hausmann --- src/quick/items/qquickwindowmodule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp index cd1b68991d..44a4bf3db6 100644 --- a/src/quick/items/qquickwindowmodule.cpp +++ b/src/quick/items/qquickwindowmodule.cpp @@ -82,7 +82,7 @@ public: if (!m_complete) m_visibility = visibility; else - QQuickWindow::setVisibility(m_visibility); + QQuickWindow::setVisibility(visibility); } Q_SIGNALS: -- cgit v1.2.3 From f95fdacb3a12e4f0d37d3c32b34326f2bd1536de Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 5 Dec 2013 14:53:27 +0100 Subject: Set the format for the fallback offscreen surface Ie76dbe5fd4ab935db3da34f3ff63d217a3ba5013 fails to set the format for the QOffscreenSurface, resulting in BAD_MATCH failures when trying to make it current. Task-number: QTBUG-35410 Change-Id: I1d420556fad4df96a1893cb3513e398eeb6e71aa Reviewed-by: Lars Knoll --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index d6a3881086..47c2d36d2c 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -1047,6 +1047,7 @@ void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestru if (!window->handle()) { QSG_GUI_DEBUG(w->window, " - using fallback surface"); fallback = new QOffscreenSurface(); + fallback->setFormat(window->requestedFormat()); fallback->create(); } -- cgit v1.2.3