[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