[PATCH 1/5] wined3d: Send window messages through the swapchain before sending them to the application.

Henri Verbeet hverbeet at codeweavers.com
Mon Dec 14 13:49:52 CST 2009


---
 dlls/wined3d/swapchain.c       |   24 ++++++++-
 dlls/wined3d/swapchain_gdi.c   |    2 +
 dlls/wined3d/wined3d_main.c    |  122 ++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/wined3d_private.h |   11 +++-
 4 files changed, 155 insertions(+), 4 deletions(-)

diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index c960ace..705a002 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -90,8 +90,10 @@ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface)
         mode.Format = This->orig_fmt;
         IWineD3DDevice_SetDisplayMode((IWineD3DDevice *)This->device, 0, &mode);
     }
-    HeapFree(GetProcessHeap(), 0, This->context);
 
+    wined3d_unregister_window(This->win_handle);
+
+    HeapFree(GetProcessHeap(), 0, This->context);
     HeapFree(GetProcessHeap(), 0, This);
 }
 
@@ -676,6 +678,12 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface
 
     window = present_parameters->hDeviceWindow ? present_parameters->hDeviceWindow : device->createParms.hFocusWindow;
 
+    if (!wined3d_register_window(window, swapchain))
+    {
+        ERR("Failed to register window %p.\n", window);
+        return E_FAIL;
+    }
+
     swapchain->device = device;
     swapchain->parent = parent;
     swapchain->ref = 1;
@@ -907,6 +915,8 @@ err:
 
     if (swapchain->frontBuffer) IWineD3DSurface_Release(swapchain->frontBuffer);
 
+    wined3d_unregister_window(window);
+
     return hr;
 }
 
@@ -951,3 +961,15 @@ void get_drawable_size_swapchain(struct wined3d_context *context, UINT *width, U
     *width = surface->currentDesc.Width;
     *height = surface->currentDesc.Height;
 }
+
+LRESULT swapchain_process_message(IWineD3DSwapChainImpl *swapchain, HWND window,
+        UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc)
+{
+    if (message == WM_DESTROY)
+    {
+        TRACE("unregister window %p.\n", window);
+        wined3d_unregister_window(window);
+    }
+
+    return CallWindowProcW(proc, window, message, wparam, lparam);
+}
diff --git a/dlls/wined3d/swapchain_gdi.c b/dlls/wined3d/swapchain_gdi.c
index c437b41..ed42f55 100644
--- a/dlls/wined3d/swapchain_gdi.c
+++ b/dlls/wined3d/swapchain_gdi.c
@@ -70,6 +70,8 @@ static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface)
         IWineD3DDevice_SetDisplayMode((IWineD3DDevice *)This->device, 0, &mode);
     }
 
+    wined3d_unregister_window(This->win_handle);
+
     HeapFree(GetProcessHeap(), 0, This->context);
     HeapFree(GetProcessHeap(), 0, This);
 }
diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c
index 5f19c26..05aea11 100644
--- a/dlls/wined3d/wined3d_main.c
+++ b/dlls/wined3d/wined3d_main.c
@@ -29,6 +29,22 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 
+struct wined3d_wndproc
+{
+    HWND window;
+    WNDPROC proc;
+    IWineD3DSwapChainImpl *swapchain;
+};
+
+struct wined3d_wndproc_table
+{
+    struct wined3d_wndproc *entries;
+    unsigned int count;
+    unsigned int size;
+};
+
+static struct wined3d_wndproc_table wndproc_table;
+
 int num_lock = 0;
 void (*CDECL wine_tsx11_lock_ptr)(void) = NULL;
 void (*CDECL wine_tsx11_unlock_ptr)(void) = NULL;
@@ -325,6 +341,7 @@ static BOOL wined3d_init(HINSTANCE hInstDLL)
 static BOOL wined3d_destroy(HINSTANCE hInstDLL)
 {
     DWORD wined3d_context_tls_idx = context_get_tls_idx();
+    unsigned int i;
 
     if (!TlsFree(wined3d_context_tls_idx))
     {
@@ -332,6 +349,13 @@ static BOOL wined3d_destroy(HINSTANCE hInstDLL)
         ERR("Failed to free context TLS index, err %#x.\n", err);
     }
 
+    for (i = 0; i < wndproc_table.count; ++i)
+    {
+        struct wined3d_wndproc *entry = &wndproc_table.entries[i];
+        SetWindowLongPtrW(entry->window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
+    }
+    HeapFree(GetProcessHeap(), 0, wndproc_table.entries);
+
     HeapFree(GetProcessHeap(), 0, wined3d_settings.logo);
     UnregisterClassA(WINED3D_OPENGL_WINDOW_CLASS_NAME, hInstDLL);
 
@@ -348,6 +372,104 @@ void WINAPI wined3d_mutex_unlock(void)
     LeaveCriticalSection(&wined3d_cs);
 }
 
+static struct wined3d_wndproc *wined3d_find_wndproc(HWND window)
+{
+    unsigned int i;
+
+    for (i = 0; i < wndproc_table.count; ++i)
+    {
+        if (wndproc_table.entries[i].window == window)
+        {
+            return &wndproc_table.entries[i];
+        }
+    }
+
+    return NULL;
+}
+
+static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
+{
+    IWineD3DSwapChainImpl *swapchain;
+    struct wined3d_wndproc *entry;
+    WNDPROC proc;
+
+    wined3d_mutex_lock();
+    entry = wined3d_find_wndproc(window);
+
+    if (!entry)
+    {
+        wined3d_mutex_unlock();
+        ERR("Window %p is not registered with wined3d.\n", window);
+        return CallWindowProcW(DefWindowProcW, window, message, wparam, lparam);
+    }
+
+    swapchain = entry->swapchain;
+    proc = entry->proc;
+    wined3d_mutex_unlock();
+
+    return swapchain_process_message(swapchain, window, message, wparam, lparam, proc);
+}
+
+BOOL wined3d_register_window(HWND window, IWineD3DSwapChainImpl *swapchain)
+{
+    struct wined3d_wndproc *entry;
+
+    wined3d_mutex_lock();
+
+    if (wndproc_table.size == wndproc_table.count)
+    {
+        unsigned int new_size = max(1, wndproc_table.size * 2);
+        struct wined3d_wndproc *new_entries;
+
+        if (!wndproc_table.entries) new_entries = HeapAlloc(GetProcessHeap(), 0, new_size * sizeof(*new_entries));
+        else new_entries = HeapReAlloc(GetProcessHeap(), 0, wndproc_table.entries, new_size * sizeof(*new_entries));
+
+        if (!new_entries)
+        {
+            wined3d_mutex_unlock();
+            ERR("Failed to grow table.\n");
+            return FALSE;
+        }
+
+        wndproc_table.entries = new_entries;
+        wndproc_table.size = new_size;
+    }
+
+    entry = &wndproc_table.entries[wndproc_table.count++];
+    entry->window = window;
+    entry->proc = (WNDPROC)SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
+    entry->swapchain = swapchain;
+
+    wined3d_mutex_unlock();
+
+    return TRUE;
+}
+
+void wined3d_unregister_window(HWND window)
+{
+    unsigned int i;
+
+    wined3d_mutex_lock();
+    for (i = 0; i < wndproc_table.count; ++i)
+    {
+        if (wndproc_table.entries[i].window == window)
+        {
+            struct wined3d_wndproc *entry = &wndproc_table.entries[i];
+            struct wined3d_wndproc *last = &wndproc_table.entries[--wndproc_table.count];
+
+            if (GetWindowLongPtrW(window, GWLP_WNDPROC) == (LONG_PTR)wined3d_wndproc)
+                SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
+            if (entry != last) *entry = *last;
+            wined3d_mutex_unlock();
+
+            return;
+        }
+    }
+    wined3d_mutex_unlock();
+
+    ERR("Window %p is not registered with wined3d.\n", window);
+}
+
 /* At process attach */
 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
 {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e0b4ab1..cd4cf6f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -816,6 +816,7 @@ typedef struct IWineD3DStateBlockImpl IWineD3DStateBlockImpl;
 typedef struct IWineD3DSurfaceImpl    IWineD3DSurfaceImpl;
 typedef struct IWineD3DPaletteImpl    IWineD3DPaletteImpl;
 typedef struct IWineD3DDeviceImpl     IWineD3DDeviceImpl;
+typedef struct IWineD3DSwapChainImpl  IWineD3DSwapChainImpl;
 
 /* Global variables */
 extern const float identity[16] DECLSPEC_HIDDEN;
@@ -1439,6 +1440,8 @@ typedef struct IWineD3DImpl
 
 extern const IWineD3DVtbl IWineD3D_Vtbl DECLSPEC_HIDDEN;
 
+BOOL wined3d_register_window(HWND window, struct IWineD3DSwapChainImpl *swapchain) DECLSPEC_HIDDEN;
+void wined3d_unregister_window(HWND window) DECLSPEC_HIDDEN;
 BOOL InitAdapters(IWineD3DImpl *This) DECLSPEC_HIDDEN;
 
 /* A helper function that dumps a resource list */
@@ -2397,7 +2400,7 @@ extern const IWineD3DRendertargetViewVtbl wined3d_rendertarget_view_vtbl DECLSPE
  * IWineD3DSwapChainImpl implementation structure (extends IUnknown)
  */
 
-typedef struct IWineD3DSwapChainImpl
+struct IWineD3DSwapChainImpl
 {
     /*IUnknown part*/
     const IWineD3DSwapChainVtbl *lpVtbl;
@@ -2422,7 +2425,7 @@ typedef struct IWineD3DSwapChainImpl
     unsigned int            num_contexts;
 
     HWND                    win_handle;
-} IWineD3DSwapChainImpl;
+};
 
 const IWineD3DSwapChainVtbl IWineGDISwapChain_Vtbl DECLSPEC_HIDDEN;
 void x11_copy_to_screen(IWineD3DSwapChainImpl *This, const RECT *rc) DECLSPEC_HIDDEN;
@@ -2452,8 +2455,10 @@ HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface,
 struct wined3d_context *swapchain_create_context_for_thread(IWineD3DSwapChain *iface) DECLSPEC_HIDDEN;
 HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface_type,
         IWineD3DDeviceImpl *device, WINED3DPRESENT_PARAMETERS *present_parameters, IUnknown *parent) DECLSPEC_HIDDEN;
-void swapchain_setup_fullscreen_window(IWineD3DSwapChainImpl *swapchain, UINT w, UINT h) DECLSPEC_HIDDEN;
+LRESULT swapchain_process_message(IWineD3DSwapChainImpl *device, HWND window,
+        UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc) DECLSPEC_HIDDEN;
 void swapchain_restore_fullscreen_window(IWineD3DSwapChainImpl *swapchain) DECLSPEC_HIDDEN;
+void swapchain_setup_fullscreen_window(IWineD3DSwapChainImpl *swapchain, UINT w, UINT h) DECLSPEC_HIDDEN;
 
 #define DEFAULT_REFRESH_RATE 0
 
-- 
1.6.4.4




More information about the wine-patches mailing list