From 0fc1b9c7e87ab6cdb6bf7c81a1eee0a1d1f74e92 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 22 Aug 2018 13:24:43 +0200 Subject: [PATCH 6/8] ANGLE: Fix flickering on resize when D3D9 is used By reverting ANGLE change d3b84ab51db09de238459b0dff2e8420c09aabf3 we get rid of the flickering that happens on resize when D3D9 is used. The issue that was fixed there is not relevant in Qt's context so it is safe to revert the change. Task-number: QTBUG-59893 Change-Id: I9306314b892612fbd1f7a058a2e606aedc0367bb --- .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 89 ++++++++++++++++++++++ .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.h | 4 + 2 files changed, 93 insertions(+) diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp index ceb022d14c..8d3f44f2ad 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp @@ -38,6 +38,7 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state, mDepthStencilFormat(state.config->depthStencilFormat), mSwapChain(nullptr), mSwapIntervalDirty(true), + mWindowSubclassed(false), mNativeWindow(renderer->createNativeWindow(window, state.config, attribs)), mWidth(static_cast(attribs.get(EGL_WIDTH, 0))), mHeight(static_cast(attribs.get(EGL_HEIGHT, 0))), @@ -45,6 +46,7 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state, mShareHandle(0), mD3DTexture(nullptr) { + subclassWindow(); if (window != nullptr && !mFixedSize) { mWidth = -1; @@ -72,6 +74,7 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state, SurfaceD3D::~SurfaceD3D() { + unsubclassWindow(); releaseSwapChain(); SafeDelete(mNativeWindow); SafeRelease(mD3DTexture); @@ -256,6 +259,92 @@ egl::Error SurfaceD3D::swapRect(const gl::Context *context, return egl::NoError(); } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) +#define kSurfaceProperty _TEXT("Egl::SurfaceOwner") +#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") +#define kDisplayProperty _TEXT("Egl::Display") + +static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) +{ + if (message == WM_SIZE) + { + SurfaceD3D* surf = reinterpret_cast(GetProp(hwnd, kSurfaceProperty)); + if(surf) + { + egl::Display *display = reinterpret_cast(GetProp(hwnd, kDisplayProperty)); + surf->checkForOutOfDateSwapChain(display->getProxyContext()); + } + } + WNDPROC prevWndFunc = reinterpret_cast(GetProp(hwnd, kParentWndProc)); + return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); +} +#endif + +void SurfaceD3D::subclassWindow() +{ +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + HWND window = mNativeWindow->getNativeWindow(); + if (!window) + { + return; + } + + DWORD processId; + DWORD threadId = GetWindowThreadProcessId(window, &processId); + if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId()) + { + return; + } + + SetLastError(0); + LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast(SurfaceWindowProc)); + if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) + { + mWindowSubclassed = false; + return; + } + + SetProp(window, kSurfaceProperty, reinterpret_cast(this)); + SetProp(window, kParentWndProc, reinterpret_cast(oldWndProc)); + SetProp(window, kDisplayProperty, reinterpret_cast(mDisplay)); + mWindowSubclassed = true; +#endif +} + +void SurfaceD3D::unsubclassWindow() +{ + if (!mWindowSubclassed) + { + return; + } + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + HWND window = mNativeWindow->getNativeWindow(); + if (!window) + { + return; + } + + // un-subclass + LONG_PTR parentWndFunc = reinterpret_cast(GetProp(window, kParentWndProc)); + + // Check the windowproc is still SurfaceWindowProc. + // If this assert fails, then it is likely the application has subclassed the + // hwnd as well and did not unsubclass before destroying its EGL context. The + // application should be modified to either subclass before initializing the + // EGL context, or to unsubclass before destroying the EGL context. + if(parentWndFunc) + { + LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc); + ASSERT(prevWndFunc == reinterpret_cast(SurfaceWindowProc)); + } + + RemoveProp(window, kSurfaceProperty); + RemoveProp(window, kParentWndProc); + RemoveProp(window, kDisplayProperty); +#endif + mWindowSubclassed = false; +} + + egl::Error SurfaceD3D::checkForOutOfDateSwapChain(const gl::Context *context) { RECT client; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h index 4fd45a6dfd..01d2573244 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h @@ -82,6 +82,9 @@ class SurfaceD3D : public SurfaceImpl int backbufferWidth, int backbufferHeight); + void subclassWindow(); + void unsubclassWindow(); + RendererD3D *mRenderer; egl::Display *mDisplay; @@ -93,6 +96,7 @@ class SurfaceD3D : public SurfaceImpl SwapChainD3D *mSwapChain; bool mSwapIntervalDirty; + bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking NativeWindowD3D *mNativeWindow; // Handler for the Window that the surface is created for. EGLint mWidth; -- 2.15.0.windows.1