wgl: Use hooks instead of subclassing the window.
authorJosé Fonseca <jfonseca@vmware.com>
Thu, 9 Apr 2009 19:35:55 +0000 (20:35 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Thu, 9 Apr 2009 19:45:43 +0000 (20:45 +0100)
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
src/gallium/state_trackers/wgl/shared/stw_framebuffer.c
src/gallium/state_trackers/wgl/shared/stw_framebuffer.h
src/gallium/state_trackers/wgl/shared/stw_tls.h

index c6d59afa0334902bb69afd588c9dae7e148794c2..8e0193d7befc3c6ba20f48a8d0a242a9bcd859ef 100644 (file)
@@ -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();
 }
 
index d6cf6fb53476387583f5ba4919fd7862326c39a6..053f741e7b613cca664e9361d1a8c53392da1083 100644 (file)
@@ -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;
+   }
+}
index c2822f6d6def46b20f382817fb30ac2b55a883d1..245fdc5fc9ea442776103c24a1458dfc8652748e 100644 (file)
@@ -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 */
index 23b61e68ff5d55c6c9efafe7d490495d7a01b3f1..f5a6bdf4b1a6068367f2aeb98536d70c72f71262 100644 (file)
 #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