Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- v2: Add tests to show that window association doesn't modify WNDPROC. v3: Move most of the code into wined3d. Supersede 163626~163629
dlls/dxgi/factory.c | 15 ++++++-- dlls/wined3d/swapchain.c | 1 + dlls/wined3d/wined3d.spec | 2 ++ dlls/wined3d/wined3d_main.c | 62 ++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d_private.h | 10 ++++++ include/wine/wined3d.h | 2 ++ 6 files changed, 90 insertions(+), 2 deletions(-)
diff --git a/dlls/dxgi/factory.c b/dlls/dxgi/factory.c index 52c145bc6a..a574090026 100644 --- a/dlls/dxgi/factory.c +++ b/dlls/dxgi/factory.c @@ -174,9 +174,20 @@ static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumAdapters(IWineDXGIFactory *ifa static HRESULT STDMETHODCALLTYPE dxgi_factory_MakeWindowAssociation(IWineDXGIFactory *iface, HWND window, UINT flags) { - FIXME("iface %p, window %p, flags %#x stub!\n", iface, window, flags); + struct dxgi_factory *factory = impl_from_IWineDXGIFactory(iface);
- return S_OK; + TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags); + + if (flags > DXGI_MWA_VALID) + return DXGI_ERROR_INVALID_CALL; + + if (!window) + { + wined3d_remove_window_association(factory->wined3d); + return S_OK; + } + + return wined3d_add_window_association(factory->wined3d, window, flags); }
static HRESULT STDMETHODCALLTYPE dxgi_factory_GetWindowAssociation(IWineDXGIFactory *iface, HWND *window) diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index fbedd7470d..808602cb15 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -22,6 +22,7 @@
#include "config.h" #include "wine/port.h" +#include "wine/list.h" #include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d); diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 040b9fc4ac..733eedb485 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -1,6 +1,7 @@ @ stdcall wined3d_mutex_lock() @ stdcall wined3d_mutex_unlock()
+@ cdecl wined3d_add_window_association(ptr ptr long) @ cdecl wined3d_calculate_format_pitch(ptr long long long) @ cdecl wined3d_check_depth_stencil_match(ptr long long long long long) @ cdecl wined3d_check_device_format(ptr long long long long long long long) @@ -20,6 +21,7 @@ @ cdecl wined3d_get_output_desc(ptr long ptr) @ cdecl wined3d_incref(ptr) @ cdecl wined3d_register_software_device(ptr ptr) +@ cdecl wined3d_remove_window_association(ptr) @ cdecl wined3d_set_adapter_display_mode(ptr long ptr)
@ cdecl wined3d_blend_state_create(ptr ptr ptr ptr ptr) diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c index 180e2d262e..9ef023dfb7 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -48,6 +48,8 @@ struct wined3d_wndproc_table
static struct wined3d_wndproc_table wndproc_table;
+struct list window_associations = LIST_INIT(window_associations); + static CRITICAL_SECTION wined3d_cs; static CRITICAL_SECTION_DEBUG wined3d_cs_debug = { @@ -555,6 +557,66 @@ void wined3d_unregister_window(HWND window) wined3d_wndproc_mutex_unlock(); }
+HRESULT CDECL wined3d_add_window_association(struct wined3d *wined3d, HWND hwnd, UINT flags) +{ + struct wined3d_window_association *association; + BOOL found = FALSE; + HRESULT hr = S_OK; + + wined3d_mutex_lock(); + LIST_FOR_EACH_ENTRY(association, &window_associations, struct wined3d_window_association, entry) + { + if (hwnd == association->hwnd) + { + found = TRUE; + break; + } + } + + if (found) + { + if(association->wined3d != wined3d) + WARN("window %p is already associated\n", hwnd); + else + association->flags = flags; + goto done; + } + else + { + association = heap_alloc_zero(sizeof(*association)); + if (!association) + { + hr = E_OUTOFMEMORY; + goto done; + } + + association->wined3d = wined3d; + association->hwnd = hwnd; + association->flags = flags; + list_add_head(&window_associations, &association->entry); + } + +done: + wined3d_mutex_unlock(); + return hr; +} + +void CDECL wined3d_remove_window_association(struct wined3d *wined3d) +{ + struct wined3d_window_association *association, *association2; + + wined3d_mutex_lock(); + LIST_FOR_EACH_ENTRY_SAFE(association, association2, &window_associations, struct wined3d_window_association, entry) + { + if (wined3d == association->wined3d) + { + list_remove(&association->entry); + heap_free(association); + } + } + wined3d_mutex_unlock(); +} + /* At process attach */ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 0fc56462b0..f277d898f3 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -215,6 +215,16 @@ struct wined3d_d3d_info DWORD multisample_draw_location; };
+struct wined3d_window_association +{ + struct wined3d *wined3d; + HWND hwnd; + UINT flags; + struct list entry; +}; + +extern struct list window_associations DECLSPEC_HIDDEN; + static const struct color_fixup_desc COLOR_FIXUP_IDENTITY = {0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_W};
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 958ade166c..8514860a79 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2172,6 +2172,7 @@ typedef HRESULT (CDECL *wined3d_device_reset_cb)(struct wined3d_resource *resour void __stdcall wined3d_mutex_lock(void); void __stdcall wined3d_mutex_unlock(void);
+HRESULT __cdecl wined3d_add_window_association(struct wined3d *wined3d, HWND hwnd, UINT flags); UINT __cdecl wined3d_calculate_format_pitch(const struct wined3d *wined3d, UINT adapter_idx, enum wined3d_format_id format_id, UINT width); HRESULT __cdecl wined3d_check_depth_stencil_match(const struct wined3d *wined3d, UINT adapter_idx, @@ -2211,6 +2212,7 @@ HRESULT __cdecl wined3d_get_output_desc(const struct wined3d *wined3d, unsigned struct wined3d_output_desc *desc); ULONG __cdecl wined3d_incref(struct wined3d *wined3d); HRESULT __cdecl wined3d_register_software_device(struct wined3d *wined3d, void *init_function); +void __cdecl wined3d_remove_window_association(struct wined3d *wined3d); HRESULT __cdecl wined3d_set_adapter_display_mode(struct wined3d *wined3d, UINT adapter_idx, const struct wined3d_display_mode *mode);