[PATCH v4 4/5] dxgi: Implement IDXGIAdapter3::RegisterVideoMemoryBudgetChangeNotificationEvent().

Conor McCarthy cmccarthy at codeweavers.com
Wed Dec 4 08:11:17 CST 2019


Used by Hitman 2.
Also implements the unregister function.

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 dlls/dxgi/adapter.c            | 14 ++++--
 dlls/wined3d/adapter_gl.c      |  3 ++
 dlls/wined3d/adapter_vk.c      |  3 ++
 dlls/wined3d/directx.c         | 88 ++++++++++++++++++++++++++++++++++
 dlls/wined3d/wined3d.spec      |  2 +
 dlls/wined3d/wined3d_private.h |  3 ++
 include/wine/wined3d.h         |  4 ++
 7 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/dlls/dxgi/adapter.c b/dlls/dxgi/adapter.c
index 3db10e8a..d7afad62 100644
--- a/dlls/dxgi/adapter.c
+++ b/dlls/dxgi/adapter.c
@@ -356,15 +356,23 @@ static HRESULT STDMETHODCALLTYPE dxgi_adapter_SetVideoMemoryReservation(IWineDXG
 static HRESULT STDMETHODCALLTYPE dxgi_adapter_RegisterVideoMemoryBudgetChangeNotificationEvent(
         IWineDXGIAdapter *iface, HANDLE event, DWORD *cookie)
 {
-    FIXME("iface %p, event %p, cookie %p stub!\n", iface, event, cookie);
+    struct dxgi_adapter *adapter = impl_from_IWineDXGIAdapter(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, event %p, cookie %p.\n", iface, event, cookie);
+
+    return wined3d_register_adapter_memory_event(adapter->factory->wined3d, adapter->ordinal, event, cookie);
 }
 
 static void STDMETHODCALLTYPE dxgi_adapter_UnregisterVideoMemoryBudgetChangeNotification(
         IWineDXGIAdapter *iface, DWORD cookie)
 {
-    FIXME("iface %p, cookie %#x stub!\n", iface, cookie);
+    struct dxgi_adapter *adapter = impl_from_IWineDXGIAdapter(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, cookie %#x.\n", iface, cookie);
+
+    if (FAILED(hr = wined3d_unregister_adapter_memory_event(adapter->factory->wined3d, adapter->ordinal, cookie)))
+        ERR("Failed to unregister notification, hr %#x.\n", hr);
 }
 
 static HRESULT STDMETHODCALLTYPE dxgi_adapter_GetDesc3(IWineDXGIAdapter *iface, DXGI_ADAPTER_DESC3 *desc)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c
index 0adcc165..91f97399 100644
--- a/dlls/wined3d/adapter_gl.c
+++ b/dlls/wined3d/adapter_gl.c
@@ -3882,6 +3882,9 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter,
             driver_info->version_high, driver_info->version_low);
 
     memset(&adapter->memory_usage, 0, sizeof(adapter->memory_usage));
+    adapter->memory_events = NULL;
+    adapter->event_capacity = 0;
+    adapter->event_count = 0;
     TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(driver_info->vram_bytes));
 
     if (gl_info->supported[EXT_MEMORY_OBJECT])
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index f00de70c..faa940e9 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -1181,6 +1181,9 @@ static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
 
     adapter_vk_init_driver_info(adapter, &properties2.properties, &memory_properties);
     memset(&adapter->memory_usage, 0, sizeof(adapter->memory_usage));
+    adapter->memory_events = NULL;
+    adapter->event_capacity = 0;
+    adapter->event_count = 0;
     TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->driver_info.vram_bytes));
 
     memcpy(&adapter->driver_uuid, id_properties.driverUUID, sizeof(adapter->driver_uuid));
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 0d2bdc8e..4625009c 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -157,6 +157,7 @@ UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, enum wined3d_adapt
         INT64 amount)
 {
     uint64_t bytes_total;
+    uint32_t i;
 
     adapter->memory_usage[type].bytes_used += amount;
     TRACE("Adjusted used adapter memory type %u by 0x%s to 0x%s.\n", type,
@@ -169,12 +170,17 @@ UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, enum wined3d_adapt
                 wine_dbgstr_longlong(adapter->memory_usage[type].bytes_used),
                 wine_dbgstr_longlong(bytes_total));
 
+    for (i = 0; i < adapter->event_count; ++i)
+        if (adapter->memory_events[i])
+            SetEvent(adapter->memory_events[i]);
+
     return adapter->memory_usage[type].bytes_used;
 }
 
 void wined3d_adapter_cleanup(struct wined3d_adapter *adapter)
 {
     wined3d_output_cleanup(&adapter->output);
+    heap_free(adapter->memory_events);
     heap_free(adapter->formats);
 }
 
@@ -1458,6 +1464,85 @@ fail:
     return E_INVALIDARG;
 }
 
+/* Most apps need only one event handle. Large numbers are unlikely so this function is not optimised. */
+static BOOL wined3d_set_unused_event_handle(struct wined3d_adapter *adapter, HANDLE event, DWORD *cookie)
+{
+    DWORD i;
+    for (i = 0; i < adapter->event_count; ++i)
+    {
+        if (!adapter->memory_events[i])
+        {
+            adapter->memory_events[i] = event;
+            *cookie = i;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+HRESULT CDECL wined3d_register_adapter_memory_event(const struct wined3d *wined3d, unsigned int adapter_idx,
+        HANDLE event, DWORD *cookie)
+{
+    struct wined3d_adapter *adapter;
+    HRESULT hr = E_INVALIDARG;
+
+    TRACE("wined3d %p, adapter_idx %u, event %p, cookie %p.\n",
+            wined3d, adapter_idx, event, cookie);
+
+    if (!cookie)
+        return E_INVALIDARG;
+
+    wined3d_mutex_lock();
+
+    if (adapter_idx >= wined3d->adapter_count)
+        goto done;
+
+    adapter = wined3d->adapters[adapter_idx];
+    if (!wined3d_set_unused_event_handle(adapter, event, cookie))
+    {
+        if(!wined3d_array_reserve((void **)&adapter->memory_events, &adapter->event_capacity,
+                adapter->event_count + 1, sizeof(*adapter->memory_events)))
+        {
+            hr = E_OUTOFMEMORY;
+            goto done;
+        }
+        adapter->memory_events[adapter->event_count] = event;
+        *cookie = adapter->event_count++;
+    }
+
+    hr = WINED3D_OK;
+
+done:
+    wined3d_mutex_unlock();
+    return hr;
+}
+
+HRESULT CDECL wined3d_unregister_adapter_memory_event(const struct wined3d *wined3d, unsigned int adapter_idx,
+        DWORD cookie)
+{
+    struct wined3d_adapter *adapter;
+
+    TRACE("wined3d %p, adapter_idx %u, cookie %u.\n", wined3d, adapter_idx, cookie);
+
+    wined3d_mutex_lock();
+
+    if (adapter_idx >= wined3d->adapter_count)
+        goto fail;
+
+    adapter = wined3d->adapters[adapter_idx];
+    if (cookie >= adapter->event_count)
+        goto fail;
+    adapter->memory_events[cookie] = NULL;
+
+    wined3d_mutex_unlock();
+
+    return WINED3D_OK;
+
+fail:
+    wined3d_mutex_unlock();
+    return E_INVALIDARG;
+}
+
 HRESULT CDECL wined3d_get_adapter_raster_status(const struct wined3d *wined3d, UINT adapter_idx,
         struct wined3d_raster_status *raster_status)
 {
@@ -2860,6 +2945,9 @@ static struct wined3d_adapter *wined3d_adapter_no3d_create(unsigned int ordinal,
 
     wined3d_driver_info_init(&adapter->driver_info, &gpu_description, 0, 0);
     memset(&adapter->memory_usage, 0, sizeof(adapter->memory_usage));
+    adapter->memory_events = NULL;
+    adapter->event_capacity = 0;
+    adapter->event_count = 0;
     TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->driver_info.vram_bytes));
 
     if (!wined3d_adapter_init(adapter, ordinal, &wined3d_adapter_no3d_ops))
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 1ff73adf..17cfed9c 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -21,10 +21,12 @@
 @ cdecl wined3d_get_device_caps(ptr long long ptr)
 @ cdecl wined3d_get_output_desc(ptr long ptr)
 @ cdecl wined3d_incref(ptr)
+@ cdecl wined3d_register_adapter_memory_event(ptr long ptr 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_set_adapter_reserved_memory(ptr long long int64);
+@ cdecl wined3d_unregister_adapter_memory_event(ptr long long);
 @ cdecl wined3d_unregister_windows(ptr)
 
 @ cdecl wined3d_blend_state_create(ptr ptr ptr ptr ptr)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 3b4145fd..d09d60d3 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2886,6 +2886,9 @@ struct wined3d_adapter
     struct wined3d_driver_info driver_info;
     struct wined3d_output output;
     struct wined3d_adapter_memory_usage memory_usage[WINED3D_ADAPTER_MEMORY_COUNT];
+    HANDLE *memory_events;
+    SIZE_T event_capacity;
+    DWORD event_count;
     GUID driver_uuid;
     GUID device_uuid;
     LUID luid;
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 5ca1673d..30c97492 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2230,6 +2230,8 @@ HRESULT __cdecl wined3d_get_device_caps(const struct wined3d *wined3d, unsigned
 HRESULT __cdecl wined3d_get_output_desc(const struct wined3d *wined3d, unsigned int adapter_idx,
         struct wined3d_output_desc *desc);
 ULONG __cdecl wined3d_incref(struct wined3d *wined3d);
+HRESULT __cdecl wined3d_register_adapter_memory_event(const struct wined3d *wined3d, unsigned int adapter_idx,
+        HANDLE event, DWORD *cookie);
 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);
@@ -2237,6 +2239,8 @@ HRESULT __cdecl wined3d_set_adapter_display_mode(struct wined3d *wined3d,
         UINT adapter_idx, const struct wined3d_display_mode *mode);
 HRESULT __cdecl wined3d_set_adapter_reserved_memory(const struct wined3d *wined3d, unsigned int adapter_idx,
         enum wined3d_adapter_memory_type type, UINT64 reservation);
+HRESULT __cdecl wined3d_unregister_adapter_memory_event(const struct wined3d *wined3d, unsigned int adapter_idx,
+        DWORD cookie);
 void __cdecl wined3d_unregister_windows(struct wined3d *wined3d);
 
 HRESULT __cdecl wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
-- 
2.24.0




More information about the wine-devel mailing list