[PATCH v3 1/5] dxgi: Implement dxgi_factory_MakeWindowAssociation().

Zhiyi Zhang zzhang at codeweavers.com
Tue May 21 07:54:31 CDT 2019


Signed-off-by: Zhiyi Zhang <zzhang at 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);
 
-- 
2.20.1





More information about the wine-devel mailing list