[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