summaryrefslogtreecommitdiffstats
path: root/src/angle/patches/0014-ANGLE-Fix-flickering-on-resize-when-D3D9-is-used.patch
blob: e389219976db3ac8d743f7e72b69b63e9315f7db (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
From 0a6fe2a93f451997d01e5e326846e0911d22622b Mon Sep 17 00:00:00 2001
From: Oliver Wolff <oliver.wolff@qt.io>
Date: Wed, 31 May 2017 15:50:28 +0200
Subject: [PATCH] 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 | 87 ++++++++++++++++++++++
 .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.h   |  4 +
 2 files changed, 91 insertions(+)

diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
index 3d27548..f567f47 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
@@ -61,16 +61,19 @@ SurfaceD3D::SurfaceD3D(RendererD3D *renderer,
       mDepthStencilFormat(config->depthStencilFormat),
       mSwapChain(nullptr),
       mSwapIntervalDirty(true),
+      mWindowSubclassed(false),
       mNativeWindow(window, config, directComposition == EGL_TRUE),
       mWidth(width),
       mHeight(height),
       mSwapInterval(1),
       mShareHandle(reinterpret_cast<HANDLE *>(shareHandle))
 {
+    subclassWindow();
 }
 
 SurfaceD3D::~SurfaceD3D()
 {
+    unsubclassWindow();
     releaseSwapChain();
 }
 
@@ -243,6 +246,90 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
     return egl::Error(EGL_SUCCESS);
 }
 
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
+#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
+
+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)
+      {
+          surf->checkForOutOfDateSwapChain();
+      }
+  }
+  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));
+    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);
+        UNUSED_ASSERTION_VARIABLE(prevWndFunc);
+        ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
+    }
+
+    RemoveProp(window, kSurfaceProperty);
+    RemoveProp(window, kParentWndProc);
+#endif
+    mWindowSubclassed = false;
+}
+
 bool SurfaceD3D::checkForOutOfDateSwapChain()
 {
     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 b925bfc..67d408d 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
     egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight);
     egl::Error resizeSwapChain(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
 
     NativeWindow mNativeWindow;   // Handler for the Window that the surface is created for.
     EGLint mWidth;
-- 
2.10.2.windows.1