Mesa (master): wgl: Use hooks instead of subclassing the window.

Jose Fonseca jrfonseca at kemper.freedesktop.org
Thu Apr 9 19:45:55 UTC 2009


Module: Mesa
Branch: master
Commit: 4bbb5eb96ad9f2e5b6e064854eeb5f5cb1498f9d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4bbb5eb96ad9f2e5b6e064854eeb5f5cb1498f9d

Author: José Fonseca <jfonseca at vmware.com>
Date:   Thu Apr  9 20:35:55 2009 +0100

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.

---

 src/gallium/state_trackers/wgl/shared/stw_device.c |    8 ++-
 .../state_trackers/wgl/shared/stw_framebuffer.c    |   95 ++++++++++++++------
 .../state_trackers/wgl/shared/stw_framebuffer.h    |    7 ++-
 src/gallium/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 c6d59af..8e0193d 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 d6cf6fb..053f741 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 c2822f6..245fdc5 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 23b61e6..f5a6bdf 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 <windows.h>
+
 struct stw_tls_data
 {
    uint currentPixelFormat;
    HDC currentDC;
    UINT_PTR currentGLRC;
+   HHOOK hCallWndProcHook;
 };
 
 boolean




More information about the mesa-commit mailing list