summaryrefslogtreecommitdiffstats
path: root/src/angle/patches/0006-ANGLE-Fix-flickering-on-resize-when-D3D9-is-used.patch
blob: f515b0a072c7c2291a5572424b0122117c6ef884 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
From 0fc1b9c7e87ab6cdb6bf7c81a1eee0a1d1f74e92 Mon Sep 17 00:00:00 2001
From: Oliver Wolff <oliver.wolff@qt.io>
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<EGLint>(attribs.get(EGL_WIDTH, 0))),
       mHeight(static_cast<EGLint>(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<SurfaceD3D*>(GetProp(hwnd, kSurfaceProperty));
+        if(surf)
+        {
+            egl::Display *display = reinterpret_cast<egl::Display *>(GetProp(hwnd, kDisplayProperty));
+            surf->checkForOutOfDateSwapChain(display->getProxyContext());
+        }
+    }
+    WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(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<LONG_PTR>(SurfaceWindowProc));
+    if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
+    {
+        mWindowSubclassed = false;
+        return;
+    }
+
+    SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
+    SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
+    SetProp(window, kDisplayProperty, reinterpret_cast<HANDLE>(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<LONG_PTR>(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<LONG_PTR>(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