[PATCH 5/5] dxgi: Implement Alt+Enter handling.

Henri Verbeet hverbeet at codeweavers.com
Wed Jun 19 05:11:04 CDT 2019


From: Zhiyi Zhang <zzhang at codeweavers.com>

Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
This supersedes patches 165255 and 165258.

 dlls/dxgi/factory.c            |  16 ++-
 dlls/dxgi/tests/dxgi.c         |   9 +-
 dlls/dxgi/utils.c              |   2 +-
 dlls/wined3d/device.c          |   2 +-
 dlls/wined3d/swapchain.c       |   4 +
 dlls/wined3d/wined3d.spec      |   2 +
 dlls/wined3d/wined3d_main.c    | 293 +++++++++++++++++++++++++++++++++++------
 dlls/wined3d/wined3d_private.h |   3 +-
 include/wine/wined3d.h         |   8 ++
 9 files changed, 291 insertions(+), 48 deletions(-)

diff --git a/dlls/dxgi/factory.c b/dlls/dxgi/factory.c
index 6912fc180ea..a0038b4fe77 100644
--- a/dlls/dxgi/factory.c
+++ b/dlls/dxgi/factory.c
@@ -174,7 +174,21 @@ 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);
+
+    TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
+
+    if (flags > DXGI_MWA_VALID)
+        return DXGI_ERROR_INVALID_CALL;
+
+    if (!window)
+    {
+        wined3d_unregister_windows(factory->wined3d);
+        return S_OK;
+    }
+
+    if (!wined3d_register_window(factory->wined3d, window, NULL, flags))
+        return E_FAIL;
 
     return S_OK;
 }
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c
index d0581223a6a..bff894773a5 100644
--- a/dlls/dxgi/tests/dxgi.c
+++ b/dlls/dxgi/tests/dxgi.c
@@ -5086,7 +5086,7 @@ static void test_window_association(void)
     }
 
     hr = IDXGIFactory_MakeWindowAssociation(factory, swapchain_desc.OutputWindow, DXGI_MWA_VALID + 1);
-    todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
+    ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
 
     /* Alt+Enter tests. */
     hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
@@ -5134,10 +5134,9 @@ static void test_window_association(void)
             flush_events();
             hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
             ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
-            todo_wine_if(tests[i].expect_fullscreen)
-                ok(fullscreen == tests[i].expect_fullscreen
-                        || broken(tests[i].broken_d3d10 && fullscreen),
-                        "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
+            ok(fullscreen == tests[i].expect_fullscreen
+                    || broken(tests[i].broken_d3d10 && fullscreen),
+                    "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
 
             wndproc = GetWindowLongPtrW(swapchain_desc.OutputWindow, GWLP_WNDPROC);
             ok(wndproc == original_wndproc, "Text %u: Got unexpected wndproc %#lx, expected %#lx.\n",
diff --git a/dlls/dxgi/utils.c b/dlls/dxgi/utils.c
index 23f5188b011..be94bde8478 100644
--- a/dlls/dxgi/utils.c
+++ b/dlls/dxgi/utils.c
@@ -511,7 +511,7 @@ unsigned int wined3d_bind_flags_from_dxgi_usage(DXGI_USAGE dxgi_usage)
 }
 
 #define DXGI_WINED3D_SWAPCHAIN_FLAGS \
-        (WINED3D_SWAPCHAIN_USE_CLOSEST_MATCHING_MODE | WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT)
+        (WINED3D_SWAPCHAIN_USE_CLOSEST_MATCHING_MODE | WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT | WINED3D_SWAPCHAIN_HOOK)
 
 unsigned int dxgi_swapchain_flags_from_wined3d(unsigned int wined3d_flags)
 {
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 09e3da31854..81b5a3ab620 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1015,7 +1015,7 @@ HRESULT CDECL wined3d_device_acquire_focus_window(struct wined3d_device *device,
 {
     TRACE("device %p, window %p.\n", device, window);
 
-    if (!wined3d_register_window(window, device))
+    if (!wined3d_register_window(NULL, window, device, 0))
     {
         ERR("Failed to register window %p.\n", window);
         return E_FAIL;
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index e4882bd4007..780734112fe 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -121,6 +121,7 @@ ULONG CDECL wined3d_swapchain_decref(struct wined3d_swapchain *swapchain)
         device = swapchain->device;
         if (device->swapchain_count && device->swapchains[0] == swapchain)
             wined3d_device_uninit_3d(device);
+        wined3d_unhook_swapchain(swapchain);
         wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
 
         swapchain_cleanup(swapchain);
@@ -1037,6 +1038,9 @@ HRESULT CDECL wined3d_swapchain_create(struct wined3d_device *device, struct win
         return hr;
     }
 
+    if (desc->flags & WINED3D_SWAPCHAIN_HOOK)
+        wined3d_hook_swapchain(object);
+
     if (desc->flags & WINED3D_SWAPCHAIN_IMPLICIT)
     {
         wined3d_mutex_lock();
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 040b9fc4ac1..59f99c91e07 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -20,7 +20,9 @@
 @ cdecl wined3d_get_output_desc(ptr long ptr)
 @ cdecl wined3d_incref(ptr)
 @ cdecl wined3d_register_software_device(ptr ptr)
+@ cdecl wined3d_register_window(ptr ptr ptr long)
 @ cdecl wined3d_set_adapter_display_mode(ptr long ptr)
+@ cdecl wined3d_unregister_windows(ptr)
 
 @ cdecl wined3d_blend_state_create(ptr ptr ptr ptr ptr)
 @ cdecl wined3d_blend_state_decref(ptr)
diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c
index 180e2d262e2..716a2b088c8 100644
--- a/dlls/wined3d/wined3d_main.c
+++ b/dlls/wined3d/wined3d_main.c
@@ -33,20 +33,47 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
 struct wined3d_wndproc
 {
+    struct wined3d *wined3d;
     HWND window;
     BOOL unicode;
     WNDPROC proc;
     struct wined3d_device *device;
+    uint32_t flags;
 };
 
 struct wined3d_wndproc_table
 {
     struct wined3d_wndproc *entries;
-    unsigned int count;
+    SIZE_T count;
     SIZE_T size;
 };
 
+struct wined3d_window_hook
+{
+    HHOOK hook;
+    DWORD thread_id;
+    unsigned int count;
+};
+
+struct wined3d_hooked_swapchain
+{
+    struct wined3d_swapchain *swapchain;
+    DWORD thread_id;
+};
+
+struct wined3d_hook_table
+{
+    struct wined3d_window_hook *hooks;
+    SIZE_T hooks_size;
+    SIZE_T hook_count;
+
+    struct wined3d_hooked_swapchain *swapchains;
+    SIZE_T swapchains_size;
+    SIZE_T swapchain_count;
+};
+
 static struct wined3d_wndproc_table wndproc_table;
+static struct wined3d_hook_table hook_table;
 
 static CRITICAL_SECTION wined3d_cs;
 static CRITICAL_SECTION_DEBUG wined3d_cs_debug =
@@ -396,6 +423,14 @@ static BOOL wined3d_dll_destroy(HINSTANCE hInstDLL)
     }
     heap_free(wndproc_table.entries);
 
+    heap_free(hook_table.swapchains);
+    for (i = 0; i < hook_table.hook_count; ++i)
+    {
+        WARN("Leftover hook table entry %p.\n", &hook_table.hooks[i]);
+        UnhookWindowsHookEx(hook_table.hooks[i].hook);
+    }
+    heap_free(hook_table.hooks);
+
     heap_free(wined3d_settings.logo);
     UnregisterClassA(WINED3D_OPENGL_WINDOW_CLASS_NAME, hInstDLL);
 
@@ -424,16 +459,16 @@ static void wined3d_wndproc_mutex_unlock(void)
     LeaveCriticalSection(&wined3d_wndproc_cs);
 }
 
-static struct wined3d_wndproc *wined3d_find_wndproc(HWND window)
+static struct wined3d_wndproc *wined3d_find_wndproc(HWND window, struct wined3d *wined3d)
 {
     unsigned int i;
 
     for (i = 0; i < wndproc_table.count; ++i)
     {
-        if (wndproc_table.entries[i].window == window)
-        {
-            return &wndproc_table.entries[i];
-        }
+        struct wined3d_wndproc *entry = &wndproc_table.entries[i];
+
+        if (entry->window == window && entry->wined3d == wined3d)
+            return entry;
     }
 
     return NULL;
@@ -447,9 +482,8 @@ static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam
     WNDPROC proc;
 
     wined3d_wndproc_mutex_lock();
-    entry = wined3d_find_wndproc(window);
 
-    if (!entry)
+    if (!(entry = wined3d_find_wndproc(window, NULL)))
     {
         wined3d_wndproc_mutex_unlock();
         ERR("Window %p is not registered with wined3d.\n", window);
@@ -468,16 +502,62 @@ static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam
     return CallWindowProcA(proc, window, message, wparam, lparam);
 }
 
-BOOL wined3d_register_window(HWND window, struct wined3d_device *device)
+static LRESULT CALLBACK wined3d_hook_proc(int code, WPARAM wparam, LPARAM lparam)
+{
+    struct wined3d_swapchain_desc swapchain_desc;
+    struct wined3d_swapchain *swapchain;
+    struct wined3d_wndproc *entry;
+    MSG *msg = (MSG *)lparam;
+    unsigned int i;
+
+    /* Handle Alt+Enter. */
+    if (code == HC_ACTION && msg->message == WM_SYSKEYDOWN
+            && msg->wParam == VK_RETURN && (msg->lParam & (KF_ALTDOWN << 16)))
+    {
+        wined3d_wndproc_mutex_lock();
+
+        for (i = 0; i < hook_table.swapchain_count; ++i)
+        {
+            swapchain = hook_table.swapchains[i].swapchain;
+
+            if (swapchain->device_window != msg->hwnd)
+                continue;
+
+            if ((entry = wined3d_find_wndproc(msg->hwnd, swapchain->device->wined3d))
+                    && (entry->flags & (WINED3D_REGISTER_WINDOW_NO_WINDOW_CHANGES
+                    | WINED3D_REGISTER_WINDOW_NO_ALT_ENTER)))
+                continue;
+
+            wined3d_swapchain_get_desc(swapchain, &swapchain_desc);
+            swapchain_desc.windowed = !swapchain_desc.windowed;
+            wined3d_swapchain_set_fullscreen(swapchain, &swapchain_desc, NULL);
+
+            wined3d_wndproc_mutex_unlock();
+
+            return 1;
+        }
+
+        wined3d_wndproc_mutex_unlock();
+    }
+
+    return CallNextHookEx(0, code, wparam, lparam);
+}
+
+BOOL CDECL wined3d_register_window(struct wined3d *wined3d, HWND window,
+        struct wined3d_device *device, unsigned int flags)
 {
     struct wined3d_wndproc *entry;
 
+    TRACE("wined3d %p, window %p, device %p, flags %#x.\n", wined3d, window, device, flags);
+
     wined3d_wndproc_mutex_lock();
 
-    if (wined3d_find_wndproc(window))
+    if ((entry = wined3d_find_wndproc(window, wined3d)))
     {
+        if (!wined3d)
+            WARN("Window %p is already registered with wined3d.\n", window);
+        entry->flags = flags;
         wined3d_wndproc_mutex_unlock();
-        WARN("Window %p is already registered with wined3d.\n", window);
         return TRUE;
     }
 
@@ -492,65 +572,200 @@ BOOL wined3d_register_window(HWND window, struct wined3d_device *device)
     entry = &wndproc_table.entries[wndproc_table.count++];
     entry->window = window;
     entry->unicode = IsWindowUnicode(window);
-    /* Set a window proc that matches the window. Some applications (e.g. NoX)
-     * replace the window proc after we've set ours, and expect to be able to
-     * call the previous one (ours) directly, without using CallWindowProc(). */
-    if (entry->unicode)
-        entry->proc = (WNDPROC)SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
+    if (!wined3d)
+    {
+        /* Set a window proc that matches the window. Some applications (e.g.
+         * NoX) replace the window proc after we've set ours, and expect to be
+         * able to call the previous one (ours) directly, without using
+         * CallWindowProc(). */
+        if (entry->unicode)
+            entry->proc = (WNDPROC)SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
+        else
+            entry->proc = (WNDPROC)SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
+    }
     else
-        entry->proc = (WNDPROC)SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
+    {
+        entry->proc = NULL;
+    }
     entry->device = device;
+    entry->wined3d = wined3d;
+    entry->flags = flags;
 
     wined3d_wndproc_mutex_unlock();
 
     return TRUE;
 }
 
+static BOOL restore_wndproc(struct wined3d_wndproc *entry)
+{
+    LONG_PTR proc;
+
+    if (entry->unicode)
+    {
+        proc = GetWindowLongPtrW(entry->window, GWLP_WNDPROC);
+        if (proc != (LONG_PTR)wined3d_wndproc)
+            return FALSE;
+        SetWindowLongPtrW(entry->window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
+    }
+    else
+    {
+        proc = GetWindowLongPtrA(entry->window, GWLP_WNDPROC);
+        if (proc != (LONG_PTR)wined3d_wndproc)
+            return FALSE;
+        SetWindowLongPtrA(entry->window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
+    }
+
+    return TRUE;
+}
+
 void wined3d_unregister_window(HWND window)
 {
     struct wined3d_wndproc *entry, *last;
-    LONG_PTR proc;
 
     wined3d_wndproc_mutex_lock();
 
-    if (!(entry = wined3d_find_wndproc(window)))
+    if (!(entry = wined3d_find_wndproc(window, NULL)))
     {
         wined3d_wndproc_mutex_unlock();
         ERR("Window %p is not registered with wined3d.\n", window);
         return;
     }
 
-    if (entry->unicode)
+    if (entry->proc && !restore_wndproc(entry))
     {
-        proc = GetWindowLongPtrW(window, GWLP_WNDPROC);
-        if (proc != (LONG_PTR)wined3d_wndproc)
+        entry->device = NULL;
+        WARN("Not unregistering window %p, current window proc doesn't match wined3d window proc.\n", window);
+        wined3d_wndproc_mutex_unlock();
+        return;
+    }
+
+    last = &wndproc_table.entries[--wndproc_table.count];
+    if (entry != last) *entry = *last;
+
+    wined3d_wndproc_mutex_unlock();
+}
+
+void CDECL wined3d_unregister_windows(struct wined3d *wined3d)
+{
+    struct wined3d_wndproc *entry, *last;
+    unsigned int i = 0;
+
+    TRACE("wined3d %p.\n", wined3d);
+
+    wined3d_wndproc_mutex_lock();
+
+    while (i < wndproc_table.count)
+    {
+        entry = &wndproc_table.entries[i];
+
+        if (entry->wined3d != wined3d)
+        {
+            ++i;
+            continue;
+        }
+
+        if (entry->proc && !restore_wndproc(entry))
         {
             entry->device = NULL;
-            wined3d_wndproc_mutex_unlock();
-            WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
-                    window, proc, wined3d_wndproc);
-            return;
+            WARN("Not unregistering window %p, current window proc doesn't match wined3d window proc.\n",
+                    entry->window);
+            ++i;
+            continue;
         }
 
-        SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
+        last = &wndproc_table.entries[--wndproc_table.count];
+        if (entry != last)
+            *entry = *last;
+        else
+            ++i;
     }
-    else
+
+    wined3d_wndproc_mutex_unlock();
+}
+
+static struct wined3d_window_hook *wined3d_find_hook(DWORD thread_id)
+{
+    unsigned int i;
+
+    for (i = 0; i < hook_table.hook_count; ++i)
     {
-        proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
-        if (proc != (LONG_PTR)wined3d_wndproc)
+        if (hook_table.hooks[i].thread_id == thread_id)
+            return &hook_table.hooks[i];
+    }
+
+    return NULL;
+}
+
+void wined3d_hook_swapchain(struct wined3d_swapchain *swapchain)
+{
+    struct wined3d_hooked_swapchain *swapchain_entry;
+    struct wined3d_window_hook *hook;
+
+    wined3d_wndproc_mutex_lock();
+
+    if (!wined3d_array_reserve((void **)&hook_table.swapchains, &hook_table.swapchains_size,
+            hook_table.swapchain_count + 1, sizeof(*swapchain_entry)))
+    {
+        wined3d_wndproc_mutex_unlock();
+        return;
+    }
+
+    swapchain_entry = &hook_table.swapchains[hook_table.swapchain_count++];
+    swapchain_entry->swapchain = swapchain;
+    swapchain_entry->thread_id = GetWindowThreadProcessId(swapchain->device_window, NULL);
+
+    if ((hook = wined3d_find_hook(swapchain_entry->thread_id)))
+    {
+        ++hook->count;
+        wined3d_wndproc_mutex_unlock();
+        return;
+    }
+
+    if (!wined3d_array_reserve((void **)&hook_table.hooks, &hook_table.hooks_size,
+            hook_table.hook_count + 1, sizeof(*hook)))
+    {
+        --hook_table.swapchain_count;
+        wined3d_wndproc_mutex_unlock();
+        return;
+    }
+
+    hook = &hook_table.hooks[hook_table.hook_count++];
+    hook->thread_id = swapchain_entry->thread_id;
+    hook->hook = SetWindowsHookExW(WH_GETMESSAGE, wined3d_hook_proc, 0, hook->thread_id);
+    hook->count = 1;
+
+    wined3d_wndproc_mutex_unlock();
+}
+
+void wined3d_unhook_swapchain(struct wined3d_swapchain *swapchain)
+{
+    struct wined3d_hooked_swapchain *swapchain_entry, *last_swapchain_entry;
+    struct wined3d_window_hook *hook, *last_hook;
+    unsigned int i;
+
+    wined3d_wndproc_mutex_lock();
+
+    for (i = 0; i < hook_table.swapchain_count; ++i)
+    {
+        swapchain_entry = &hook_table.swapchains[i];
+
+        if (swapchain_entry->swapchain != swapchain)
+            continue;
+
+        if ((hook = wined3d_find_hook(swapchain_entry->thread_id)) && !--hook->count)
         {
-            entry->device = NULL;
-            wined3d_wndproc_mutex_unlock();
-            WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
-                    window, proc, wined3d_wndproc);
-            return;
+            UnhookWindowsHookEx(hook->hook);
+            last_hook = &hook_table.hooks[--hook_table.hook_count];
+            if (hook != last_hook)
+                *hook = *last_hook;
         }
 
-        SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
-    }
+        last_swapchain_entry = &hook_table.swapchains[--hook_table.swapchain_count];
+        if (swapchain_entry != last_swapchain_entry)
+            *swapchain_entry = *last_swapchain_entry;
 
-    last = &wndproc_table.entries[--wndproc_table.count];
-    if (entry != last) *entry = *last;
+        break;
+    }
 
     wined3d_wndproc_mutex_unlock();
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index aebaa9ed2f2..75f27cebb27 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2974,8 +2974,9 @@ struct wined3d
     struct wined3d_adapter *adapters[1];
 };
 
+void wined3d_hook_swapchain(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 HRESULT wined3d_init(struct wined3d *wined3d, DWORD flags) DECLSPEC_HIDDEN;
-BOOL wined3d_register_window(HWND window, struct wined3d_device *device) DECLSPEC_HIDDEN;
+void wined3d_unhook_swapchain(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void wined3d_unregister_window(HWND window) DECLSPEC_HIDDEN;
 
 BOOL wined3d_get_app_name(char *app_name, unsigned int app_name_size) DECLSPEC_HIDDEN;
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index ada56365505..a0ff3f13354 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -903,6 +903,7 @@ enum wined3d_shader_type
 #define WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT                   0x00004000u
 #define WINED3D_SWAPCHAIN_GDI_COMPATIBLE                        0x00008000u
 #define WINED3D_SWAPCHAIN_IMPLICIT                              0x00010000u
+#define WINED3D_SWAPCHAIN_HOOK                                  0x00020000u
 
 #define WINED3DDP_MAXTEXCOORD                                   8
 
@@ -1584,6 +1585,10 @@ enum wined3d_shader_type
 
 #define WINED3D_MAX_VIEWPORTS                                   16
 
+#define WINED3D_REGISTER_WINDOW_NO_WINDOW_CHANGES               0x00000001u
+#define WINED3D_REGISTER_WINDOW_NO_ALT_ENTER                    0x00000002u
+#define WINED3D_REGISTER_WINDOW_NO_PRINT_SCREEN                 0x00000004u
+
 struct wined3d_display_mode
 {
     UINT width;
@@ -2210,8 +2215,11 @@ 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);
+BOOL __cdecl wined3d_register_window(struct wined3d *wined3d, HWND window,
+        struct wined3d_device *device, unsigned int flags);
 HRESULT __cdecl wined3d_set_adapter_display_mode(struct wined3d *wined3d,
         UINT adapter_idx, const struct wined3d_display_mode *mode);
+void __cdecl wined3d_unregister_windows(struct wined3d *wined3d);
 
 HRESULT __cdecl wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
         const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops,
-- 
2.11.0




More information about the wine-devel mailing list