diff options
Diffstat (limited to 'src/3rdparty/angle')
-rw-r--r-- | src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 87 | ||||
-rw-r--r-- | src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h | 4 |
2 files changed, 91 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp index 3d27548504..f567f47525 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 b925bfc8cc..67d408ddd9 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; |