From 4bbb5eb96ad9f2e5b6e064854eeb5f5cb1498f9d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Thu, 9 Apr 2009 20:35:55 +0100 Subject: [PATCH] wgl: Use hooks instead of subclassing the window. Subclassing the window is invasive: we might call an old window proc even after it was removed. Glut and another bug just in the wrong time was provoking this. Hooks don't have this problem. --- .../state_trackers/wgl/shared/stw_device.c | 8 +- .../wgl/shared/stw_framebuffer.c | 95 +++++++++++++------ .../wgl/shared/stw_framebuffer.h | 7 +- .../state_trackers/wgl/shared/stw_tls.h | 3 + 4 files changed, 83 insertions(+), 30 deletions(-) diff --git a/src/gallium/state_trackers/wgl/shared/stw_device.c b/src/gallium/state_trackers/wgl/shared/stw_device.c index c6d59afa033..8e0193d7bef 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_device.c +++ b/src/gallium/state_trackers/wgl/shared/stw_device.c @@ -41,6 +41,7 @@ #include "shared/stw_pixelformat.h" #include "shared/stw_public.h" #include "shared/stw_tls.h" +#include "shared/stw_framebuffer.h" #ifdef WIN32_THREADS extern _glthread_Mutex OneTimeLock; @@ -132,9 +133,11 @@ error1: boolean st_init_thread(void) { - if (!stw_tls_init_thread()) { + if (!stw_tls_init_thread()) + return FALSE; + + if (!stw_framebuffer_init_thread()) return FALSE; - } return TRUE; } @@ -143,6 +146,7 @@ st_init_thread(void) void st_cleanup_thread(void) { + stw_framebuffer_cleanup_thread(); stw_tls_cleanup_thread(); } diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c index d6cf6fb5347..053f741e7b6 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c +++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c @@ -42,6 +42,7 @@ #include "stw_device.h" #include "stw_public.h" #include "stw_winsys.h" +#include "stw_tls.h" void @@ -53,26 +54,43 @@ stw_framebuffer_resize( st_resize_framebuffer( fb->stfb, width, height ); } +/** + * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx + * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx + */ static LRESULT CALLBACK -stw_window_proc( - HWND hWnd, - UINT uMsg, +stw_call_window_proc( + int nCode, WPARAM wParam, LPARAM lParam ) { - struct stw_framebuffer *fb; - - pipe_mutex_lock( stw_dev->mutex ); - for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next) - if (fb->hWnd == hWnd) - break; - pipe_mutex_unlock( stw_dev->mutex ); - assert( fb != NULL ); - - if (uMsg == WM_SIZE && wParam != SIZE_MINIMIZED) - stw_framebuffer_resize( fb, LOWORD( lParam ), HIWORD( lParam ) ); + struct stw_tls_data *tls_data; + PCWPSTRUCT pParams = (PCWPSTRUCT)lParam; + + tls_data = stw_tls_get_data(); + if(!tls_data) + return 0; + + if (nCode < 0) + return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam); + + if (pParams->message == WM_SIZE && pParams->wParam != SIZE_MINIMIZED) { + struct stw_framebuffer *fb; + + pipe_mutex_lock( stw_dev->mutex ); + for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next) + if (fb->hWnd == pParams->hwnd) + break; + pipe_mutex_unlock( stw_dev->mutex ); + + if(fb) { + unsigned width = LOWORD( pParams->lParam ); + unsigned height = HIWORD( pParams->lParam ); + stw_framebuffer_resize( fb, width, height ); + } + } - return CallWindowProc( fb->WndProc, hWnd, uMsg, wParam, lParam ); + return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam); } static INLINE boolean @@ -190,16 +208,7 @@ stw_framebuffer_create( fb->cColorBits = GetDeviceCaps( hdc, BITSPIXEL ); fb->hDC = hdc; - - /* Subclass a window associated with the device context. - */ fb->hWnd = WindowFromDC( hdc ); - if (fb->hWnd != NULL) { - fb->WndProc = (WNDPROC) SetWindowLongPtr( - fb->hWnd, - GWLP_WNDPROC, - (LONG_PTR) stw_window_proc ); - } pipe_mutex_lock( stw_dev->mutex ); fb->next = stw_dev->fb_head; @@ -227,9 +236,6 @@ stw_framebuffer_destroy( pipe_mutex_unlock( stw_dev->mutex ); - if (fb->hWnd) - SetWindowLongPtr( fb->hWnd, GWLP_WNDPROC, (LONG_PTR)fb->WndProc ); - FREE( fb ); } @@ -286,3 +292,38 @@ stw_swap_buffers( return TRUE; } + + +boolean +stw_framebuffer_init_thread(void) +{ + struct stw_tls_data *tls_data; + + tls_data = stw_tls_get_data(); + if(!tls_data) + return FALSE; + + tls_data->hCallWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, + stw_call_window_proc, + NULL, + GetCurrentThreadId()); + if(tls_data->hCallWndProcHook == NULL) + return FALSE; + + return TRUE; +} + +void +stw_framebuffer_cleanup_thread(void) +{ + struct stw_tls_data *tls_data; + + tls_data = stw_tls_get_data(); + if(!tls_data) + return; + + if(tls_data->hCallWndProcHook) { + UnhookWindowsHookEx(tls_data->hCallWndProcHook); + tls_data->hCallWndProcHook = NULL; + } +} diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h index c2822f6d6de..245fdc5fc9e 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h +++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h @@ -39,7 +39,6 @@ struct stw_framebuffer HDC hDC; BYTE cColorBits; HWND hWnd; - WNDPROC WndProc; struct stw_framebuffer *next; }; @@ -64,4 +63,10 @@ struct stw_framebuffer * stw_framebuffer_from_hdc( HDC hdc ); +boolean +stw_framebuffer_init_thread(void); + +void +stw_framebuffer_cleanup_thread(void); + #endif /* STW_FRAMEBUFFER_H */ diff --git a/src/gallium/state_trackers/wgl/shared/stw_tls.h b/src/gallium/state_trackers/wgl/shared/stw_tls.h index 23b61e68ff5..f5a6bdf4b1a 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_tls.h +++ b/src/gallium/state_trackers/wgl/shared/stw_tls.h @@ -28,11 +28,14 @@ #ifndef STW_TLS_H #define STW_TLS_H +#include + struct stw_tls_data { uint currentPixelFormat; HDC currentDC; UINT_PTR currentGLRC; + HHOOK hCallWndProcHook; }; boolean -- 2.30.2