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 <lorn.potter@gmail.com>
This commit is contained in:
Morten Johan Sørvig 2019-04-29 00:35:42 +02:00 committed by Jani Heikkinen
parent 4e0f262892
commit c8c4819b7b
9 changed files with 51 additions and 3 deletions

View File

@ -55,6 +55,12 @@ QWasmBackingStore::~QWasmBackingStore()
{
}
void QWasmBackingStore::destroy()
{
if (m_texture->isCreated())
m_texture->destroy();
}
QPaintDevice *QWasmBackingStore::paintDevice()
{
return &m_image;

View File

@ -44,6 +44,7 @@ class QWasmBackingStore : public QPlatformBackingStore
public:
QWasmBackingStore(QWasmCompositor *compositor, QWindow *window);
~QWasmBackingStore();
void destroy();
QPaintDevice *paintDevice() override;

View File

@ -37,6 +37,7 @@
#include <QtGui/qopenglcontext.h>
#include <QtGui/qopenglfunctions.h>
#include <QtGui/qopengltextureblitter.h>
#include <QtGui/qoffscreensurface.h>
#include <QtGui/qpainter.h>
#include <private/qpixmapcache_p.h>
@ -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();

View File

@ -64,6 +64,7 @@ class QWasmCompositor : public QObject
public:
QWasmCompositor(QWasmScreen *screen);
~QWasmCompositor();
void destroy();
enum QWasmSubControl {
SC_None = 0x00000000,

View File

@ -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)

View File

@ -57,7 +57,12 @@ QWasmScreen::QWasmScreen(const QString &canvasId)
QWasmScreen::~QWasmScreen()
{
destroy();
}
void QWasmScreen::destroy()
{
m_compositor->destroy();
}
QWasmScreen *QWasmScreen::get(QPlatformScreen *screen)

View File

@ -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);

View File

@ -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();

View File

@ -58,6 +58,7 @@ public:
QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore);
~QWasmWindow();
void destroy();
void initialize() override;