From c8c4819b7b2f20c2972c31c49547ce5b59fe1240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 29 Apr 2019 00:35:42 +0200 Subject: wasm: controlled screen destruction Freeing OpenGL resources requires a current context, which (on wasm) requires a screen. Add a destroy() functions to QWasmScreen, QWasmCompositor, QWasmWindow, and QWasmBackingStore which facilitates OpenGL cleanup before we start deleting screen objects. Task-number: QTBUG-75463 Change-Id: I9954b536416b9147965c74459ccad838d1578778 Reviewed-by: Lorn Potter --- src/plugins/platforms/wasm/qwasmbackingstore.cpp | 6 +++++ src/plugins/platforms/wasm/qwasmbackingstore.h | 1 + src/plugins/platforms/wasm/qwasmcompositor.cpp | 29 ++++++++++++++++++++++-- src/plugins/platforms/wasm/qwasmcompositor.h | 1 + src/plugins/platforms/wasm/qwasmintegration.cpp | 4 +++- src/plugins/platforms/wasm/qwasmscreen.cpp | 5 ++++ src/plugins/platforms/wasm/qwasmscreen.h | 1 + src/plugins/platforms/wasm/qwasmwindow.cpp | 6 +++++ src/plugins/platforms/wasm/qwasmwindow.h | 1 + 9 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.cpp b/src/plugins/platforms/wasm/qwasmbackingstore.cpp index 5b40c44807..e8eda2605f 100644 --- a/src/plugins/platforms/wasm/qwasmbackingstore.cpp +++ b/src/plugins/platforms/wasm/qwasmbackingstore.cpp @@ -55,6 +55,12 @@ QWasmBackingStore::~QWasmBackingStore() { } +void QWasmBackingStore::destroy() +{ + if (m_texture->isCreated()) + m_texture->destroy(); +} + QPaintDevice *QWasmBackingStore::paintDevice() { return &m_image; diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.h b/src/plugins/platforms/wasm/qwasmbackingstore.h index 6ffa262e3d..4bca83c457 100644 --- a/src/plugins/platforms/wasm/qwasmbackingstore.h +++ b/src/plugins/platforms/wasm/qwasmbackingstore.h @@ -44,6 +44,7 @@ class QWasmBackingStore : public QPlatformBackingStore public: QWasmBackingStore(QWasmCompositor *compositor, QWindow *window); ~QWasmBackingStore(); + void destroy(); QPaintDevice *paintDevice() override; diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index 9d99c21195..6d211667be 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -71,6 +72,28 @@ QWasmCompositor::QWasmCompositor(QWasmScreen *screen) QWasmCompositor::~QWasmCompositor() { delete m_frameBuffer; + destroy(); +} + +void QWasmCompositor::destroy() +{ + // Destroy OpenGL resources. This is done here in a separate function + // which can be called while screen() still returns a valid screen + // (which it might not, during destruction). A valid QScreen is + // a requirement for QOffscreenSurface on Wasm since the native + // context is tied to a single canvas. + if (m_context) { + QOffscreenSurface offScreenSurface(screen()->screen()); + offScreenSurface.setFormat(m_context->format()); + offScreenSurface.create(); + m_context->makeCurrent(&offScreenSurface); + for (QWasmWindow *window : m_windowStack) + window->destroy(); + m_blitter.reset(nullptr); + m_context.reset(nullptr); + } + + m_isEnabled = false; // prevent frame() from creating a new m_context } void QWasmCompositor::setEnabled(bool enabled) @@ -653,7 +676,7 @@ void QWasmCompositor::frame() m_needComposit = false; - if (m_windowStack.empty() || !screen()) + if (!m_isEnabled || m_windowStack.empty() || !screen()) return; QWasmWindow *someWindow = nullptr; @@ -676,7 +699,9 @@ void QWasmCompositor::frame() m_context->create(); } - m_context->makeCurrent(someWindow->window()); + bool ok = m_context->makeCurrent(someWindow->window()); + if (!ok) + return; if (!m_blitter->isCreated()) m_blitter->create(); diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h index 3104573073..98f4a79b27 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.h +++ b/src/plugins/platforms/wasm/qwasmcompositor.h @@ -64,6 +64,7 @@ class QWasmCompositor : public QObject public: QWasmCompositor(QWasmScreen *screen); ~QWasmCompositor(); + void destroy(); enum QWasmSubControl { SC_None = 0x00000000, diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp index 0d22d31c25..93d3b5f76d 100644 --- a/src/plugins/platforms/wasm/qwasmintegration.cpp +++ b/src/plugins/platforms/wasm/qwasmintegration.cpp @@ -258,7 +258,9 @@ void QWasmIntegration::addScreen(const QString &canvasId) void QWasmIntegration::removeScreen(const QString &canvasId) { - QWindowSystemInterface::handleScreenRemoved(m_screens.take(canvasId)); + QWasmScreen *exScreen = m_screens.take(canvasId); + exScreen->destroy(); // clean up before deleting the screen + QWindowSystemInterface::handleScreenRemoved(exScreen); } void QWasmIntegration::resizeScreen(const QString &canvasId) diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp index a26cafa900..74d47555fc 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.cpp +++ b/src/plugins/platforms/wasm/qwasmscreen.cpp @@ -57,7 +57,12 @@ QWasmScreen::QWasmScreen(const QString &canvasId) QWasmScreen::~QWasmScreen() { + destroy(); +} +void QWasmScreen::destroy() +{ + m_compositor->destroy(); } QWasmScreen *QWasmScreen::get(QPlatformScreen *screen) diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h index 82d2a83edb..4ad4ffa9ad 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.h +++ b/src/plugins/platforms/wasm/qwasmscreen.h @@ -52,6 +52,7 @@ class QWasmScreen : public QObject, public QPlatformScreen public: QWasmScreen(const QString &canvasId); ~QWasmScreen(); + void destroy(); static QWasmScreen *get(QPlatformScreen *screen); static QWasmScreen *get(QScreen *screen); diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp index 39797cb09d..594db65cfd 100644 --- a/src/plugins/platforms/wasm/qwasmwindow.cpp +++ b/src/plugins/platforms/wasm/qwasmwindow.cpp @@ -65,6 +65,12 @@ QWasmWindow::~QWasmWindow() m_compositor->removeWindow(this); } +void QWasmWindow::destroy() +{ + if (m_backingStore) + m_backingStore->destroy(); +} + void QWasmWindow::initialize() { QRect rect = windowGeometry(); diff --git a/src/plugins/platforms/wasm/qwasmwindow.h b/src/plugins/platforms/wasm/qwasmwindow.h index cbbce99aeb..a098172649 100644 --- a/src/plugins/platforms/wasm/qwasmwindow.h +++ b/src/plugins/platforms/wasm/qwasmwindow.h @@ -58,6 +58,7 @@ public: QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore); ~QWasmWindow(); + void destroy(); void initialize() override; -- cgit v1.2.3