winrt: Move EGL surface to window.
Fixes GPU memory leak when window is created/deleted dynamically and repeatedly. EGL context used to own EGL surface, but the context outlives the surface if window is created/deleted dynamically. The EGL surface is now owned by the window and destroyed with it. Change-Id: Ib949261ef6e77217018e60aad3e36e4a6d2eaba0 Reviewed-by: Andrew Knight <andrew.knight@intopalo.com>bb10
parent
fe1ba87961
commit
f3fd7b3d96
|
|
@ -56,7 +56,6 @@ public:
|
|||
EGLDisplay eglDisplay;
|
||||
EGLConfig eglConfig;
|
||||
EGLContext eglContext;
|
||||
QHash<QPlatformSurface *, EGLSurface> surfaceForWindow;
|
||||
};
|
||||
|
||||
QWinRTEGLContext::QWinRTEGLContext(QOpenGLContext *context)
|
||||
|
|
@ -70,8 +69,6 @@ QWinRTEGLContext::QWinRTEGLContext(QOpenGLContext *context)
|
|||
QWinRTEGLContext::~QWinRTEGLContext()
|
||||
{
|
||||
Q_D(QWinRTEGLContext);
|
||||
foreach (const EGLSurface &surface, d->surfaceForWindow)
|
||||
eglDestroySurface(d->eglDisplay, surface);
|
||||
if (d->eglContext != EGL_NO_CONTEXT)
|
||||
eglDestroyContext(d->eglDisplay, d->eglContext);
|
||||
if (d->eglDisplay != EGL_NO_DISPLAY)
|
||||
|
|
@ -112,23 +109,13 @@ bool QWinRTEGLContext::makeCurrent(QPlatformSurface *windowSurface)
|
|||
Q_D(QWinRTEGLContext);
|
||||
Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface);
|
||||
|
||||
EGLSurface surface = d->surfaceForWindow.value(windowSurface);
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
QWinRTWindow *window = static_cast<QWinRTWindow *>(windowSurface);
|
||||
HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d, window, &surface]() {
|
||||
surface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig,
|
||||
reinterpret_cast<EGLNativeWindowType>(window->winId()),
|
||||
nullptr);
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
if (FAILED(hr))
|
||||
return false;
|
||||
d->surfaceForWindow.insert(windowSurface, surface);
|
||||
}
|
||||
QWinRTWindow *window = static_cast<QWinRTWindow *>(windowSurface);
|
||||
if (window->eglSurface() == EGL_NO_SURFACE)
|
||||
window->createEglSurface(d->eglDisplay, d->eglConfig);
|
||||
|
||||
EGLSurface surface = window->eglSurface();
|
||||
if (surface == EGL_NO_SURFACE)
|
||||
return false;
|
||||
|
||||
const bool ok = eglMakeCurrent(d->eglDisplay, surface, surface, d->eglContext);
|
||||
if (!ok) {
|
||||
|
|
@ -153,7 +140,8 @@ void QWinRTEGLContext::swapBuffers(QPlatformSurface *windowSurface)
|
|||
Q_D(QWinRTEGLContext);
|
||||
Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface);
|
||||
|
||||
eglSwapBuffers(d->eglDisplay, d->surfaceForWindow.value(windowSurface));
|
||||
const QWinRTWindow *window = static_cast<QWinRTWindow *>(windowSurface);
|
||||
eglSwapBuffers(d->eglDisplay, window->eglSurface());
|
||||
}
|
||||
|
||||
QSurfaceFormat QWinRTEGLContext::format() const
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ public:
|
|||
QSurfaceFormat surfaceFormat;
|
||||
QString windowTitle;
|
||||
Qt::WindowState state;
|
||||
EGLDisplay display;
|
||||
EGLSurface surface;
|
||||
|
||||
ComPtr<ISwapChainPanel> swapChainPanel;
|
||||
ComPtr<ICanvasStatics> canvas;
|
||||
|
|
@ -100,6 +102,8 @@ QWinRTWindow::QWinRTWindow(QWindow *window)
|
|||
{
|
||||
Q_D(QWinRTWindow);
|
||||
|
||||
d->surface = EGL_NO_SURFACE;
|
||||
d->display = EGL_NO_DISPLAY;
|
||||
d->screen = static_cast<QWinRTScreen *>(screen());
|
||||
setWindowFlags(window->flags());
|
||||
setWindowState(window->windowState());
|
||||
|
|
@ -170,6 +174,11 @@ QWinRTWindow::~QWinRTWindow()
|
|||
return S_OK;
|
||||
});
|
||||
RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down");
|
||||
|
||||
EGLBoolean value = eglDestroySurface(d->display, d->surface);
|
||||
d->surface = EGL_NO_SURFACE;
|
||||
if (value == EGL_FALSE)
|
||||
qCritical("Failed to destroy EGL window surface: 0x%x", eglGetError());
|
||||
}
|
||||
|
||||
QSurfaceFormat QWinRTWindow::format() const
|
||||
|
|
@ -293,4 +302,26 @@ void QWinRTWindow::setWindowState(Qt::WindowState state)
|
|||
d->state = state;
|
||||
}
|
||||
|
||||
EGLSurface QWinRTWindow::eglSurface() const
|
||||
{
|
||||
Q_D(const QWinRTWindow);
|
||||
return d->surface;
|
||||
}
|
||||
|
||||
void QWinRTWindow::createEglSurface(EGLDisplay display, EGLConfig config)
|
||||
{
|
||||
Q_D(QWinRTWindow);
|
||||
if (d->surface == EGL_NO_SURFACE) {
|
||||
d->display = display;
|
||||
QEventDispatcherWinRT::runOnXamlThread([this, d, display, config]() {
|
||||
d->surface = eglCreateWindowSurface(display, config,
|
||||
reinterpret_cast<EGLNativeWindowType>(winId()),
|
||||
nullptr);
|
||||
if (d->surface == EGL_NO_SURFACE)
|
||||
qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include <qpa/qplatformwindow.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -63,6 +64,9 @@ public:
|
|||
qreal devicePixelRatio() const Q_DECL_OVERRIDE;
|
||||
void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
|
||||
|
||||
EGLSurface eglSurface() const;
|
||||
void createEglSurface(EGLDisplay display, EGLConfig config);
|
||||
|
||||
private:
|
||||
QScopedPointer<QWinRTWindowPrivate> d_ptr;
|
||||
Q_DECLARE_PRIVATE(QWinRTWindow)
|
||||
|
|
|
|||
Loading…
Reference in New Issue