wined3d: Send window messages through the swapchain before sending them to the application.

This commit is contained in:
Henri Verbeet 2009-12-14 20:49:52 +01:00 committed by Alexandre Julliard
parent 0a59c65e74
commit 0e270bbd22
4 changed files with 155 additions and 4 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 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)
{

View File

@ -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