Commit fd6e137d authored by Zhiyi Zhang's avatar Zhiyi Zhang Committed by Alexandre Julliard

dxgi: Implement adapter video memory budget change notification.

parent 54c27f69
......@@ -333,15 +333,22 @@ 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);
if (!event || !cookie)
return DXGI_ERROR_INVALID_CALL;
return wined3d_adapter_register_budget_change_notification(adapter->wined3d_adapter, event, cookie);
}
static void STDMETHODCALLTYPE dxgi_adapter_UnregisterVideoMemoryBudgetChangeNotification(
IWineDXGIAdapter *iface, DWORD cookie)
{
FIXME("iface %p, cookie %#lx stub!\n", iface, cookie);
TRACE("iface %p, cookie %#lx.\n", iface, cookie);
wined3d_adapter_unregister_budget_change_notification(cookie);
}
static HRESULT STDMETHODCALLTYPE dxgi_adapter_GetDesc3(IWineDXGIAdapter *iface, DXGI_ADAPTER_DESC3 *desc)
......
......@@ -7539,16 +7539,13 @@ static void test_video_memory_budget_notification(void)
goto done;
hr = IDXGIAdapter3_RegisterVideoMemoryBudgetChangeNotificationEvent(adapter3, NULL, &cookie);
todo_wine
ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr);
event = CreateEventW(NULL, FALSE, FALSE, NULL);
hr = IDXGIAdapter3_RegisterVideoMemoryBudgetChangeNotificationEvent(adapter3, event, NULL);
todo_wine
ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr);
hr = IDXGIAdapter3_RegisterVideoMemoryBudgetChangeNotificationEvent(adapter3, event, &cookie);
todo_wine
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = IDXGIAdapter3_QueryVideoMemoryInfo(adapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &memory_info);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
......@@ -7560,7 +7557,6 @@ static void test_video_memory_budget_notification(void)
if (memory_info.Budget)
{
ret = WaitForSingleObject(event, 1000);
todo_wine
ok(ret == WAIT_OBJECT_0, "Expected event fired.\n");
}
......
......@@ -23,6 +23,7 @@
#include "wined3d_private.h"
#include "winternl.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
WINE_DECLARE_DEBUG_CHANNEL(winediag);
......@@ -38,6 +39,19 @@ enum wined3d_driver_model
DRIVER_MODEL_NT6X
};
struct wined3d_adapter_budget_change_notification
{
const struct wined3d_adapter *adapter;
HANDLE event;
DWORD cookie;
UINT64 last_local_budget;
UINT64 last_non_local_budget;
struct list entry;
};
static struct list adapter_budget_change_notifications = LIST_INIT( adapter_budget_change_notifications );
static HANDLE notification_thread, notification_thread_stop_event;
/* The d3d device ID */
static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
......@@ -1046,6 +1060,131 @@ HRESULT CDECL wined3d_adapter_get_video_memory_info(const struct wined3d_adapter
return WINED3D_OK;
}
static DWORD CALLBACK notification_thread_func(void *stop_event)
{
struct wined3d_adapter_budget_change_notification *notification;
struct wined3d_video_memory_info info;
HRESULT hr;
while (TRUE)
{
wined3d_mutex_lock();
LIST_FOR_EACH_ENTRY(notification, &adapter_budget_change_notifications,
struct wined3d_adapter_budget_change_notification, entry)
{
hr = wined3d_adapter_get_video_memory_info(notification->adapter, 0,
WINED3D_MEMORY_SEGMENT_GROUP_LOCAL, &info);
if (SUCCEEDED(hr) && info.budget != notification->last_local_budget)
{
notification->last_local_budget = info.budget;
SetEvent(notification->event);
continue;
}
hr = wined3d_adapter_get_video_memory_info(notification->adapter, 0,
WINED3D_MEMORY_SEGMENT_GROUP_NON_LOCAL, &info);
if (SUCCEEDED(hr) && info.budget != notification->last_non_local_budget)
{
notification->last_non_local_budget = info.budget;
SetEvent(notification->event);
}
}
wined3d_mutex_unlock();
if (WaitForSingleObject(stop_event, 1000) == WAIT_OBJECT_0)
break;
}
return TRUE;
}
HRESULT CDECL wined3d_adapter_register_budget_change_notification(const struct wined3d_adapter *adapter,
HANDLE event, DWORD *cookie)
{
static DWORD cookie_counter;
static BOOL wrapped;
struct wined3d_adapter_budget_change_notification *notification, *new_notification;
BOOL found = FALSE;
new_notification = heap_alloc_zero(sizeof(*new_notification));
if (!new_notification)
return E_OUTOFMEMORY;
wined3d_mutex_lock();
new_notification->adapter = adapter;
new_notification->event = event;
new_notification->cookie = cookie_counter++;
if (cookie_counter < new_notification->cookie)
wrapped = TRUE;
if (wrapped)
{
while (TRUE)
{
LIST_FOR_EACH_ENTRY(notification, &adapter_budget_change_notifications,
struct wined3d_adapter_budget_change_notification, entry)
{
if (notification->cookie == new_notification->cookie)
{
found = TRUE;
break;
}
}
if (!found)
break;
new_notification->cookie = cookie_counter++;
}
}
*cookie = new_notification->cookie;
list_add_head(&adapter_budget_change_notifications, &new_notification->entry);
if (!notification_thread)
{
notification_thread_stop_event = CreateEventW(0, FALSE, FALSE, NULL);
notification_thread = CreateThread(NULL, 0, notification_thread_func,
notification_thread_stop_event, 0, NULL);
}
wined3d_mutex_unlock();
return WINED3D_OK;
}
HRESULT CDECL wined3d_adapter_unregister_budget_change_notification(DWORD cookie)
{
struct wined3d_adapter_budget_change_notification *notification;
HANDLE thread, thread_stop_event;
wined3d_mutex_lock();
LIST_FOR_EACH_ENTRY(notification, &adapter_budget_change_notifications,
struct wined3d_adapter_budget_change_notification, entry)
{
if (notification->cookie == cookie)
{
list_remove(&notification->entry);
heap_free(notification);
break;
}
}
if (!list_empty(&adapter_budget_change_notifications))
{
wined3d_mutex_unlock();
return WINED3D_OK;
}
thread = notification_thread;
thread_stop_event = notification_thread_stop_event;
notification_thread = NULL;
notification_thread_stop_event = NULL;
wined3d_mutex_unlock();
SetEvent(thread_stop_event);
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
CloseHandle(thread_stop_event);
return WINED3D_OK;
}
HRESULT CDECL wined3d_register_software_device(struct wined3d *wined3d, void *init_function)
{
FIXME("wined3d %p, init_function %p stub!\n", wined3d, init_function);
......
......@@ -22,6 +22,8 @@
@ cdecl wined3d_adapter_get_output(ptr long)
@ cdecl wined3d_adapter_get_output_count(ptr)
@ cdecl wined3d_adapter_get_video_memory_info(ptr long long ptr)
@ cdecl wined3d_adapter_register_budget_change_notification(ptr ptr ptr)
@ cdecl wined3d_adapter_unregister_budget_change_notification(long)
@ cdecl wined3d_blend_state_create(ptr ptr ptr ptr ptr)
@ cdecl wined3d_blend_state_decref(ptr)
......
......@@ -2364,6 +2364,9 @@ unsigned int __cdecl wined3d_adapter_get_output_count(const struct wined3d_adapt
HRESULT __cdecl wined3d_adapter_get_video_memory_info(const struct wined3d_adapter *adapter,
unsigned int node_idx, enum wined3d_memory_segment_group group,
struct wined3d_video_memory_info *info);
HRESULT __cdecl wined3d_adapter_register_budget_change_notification(const struct wined3d_adapter *adapter,
HANDLE event, DWORD *cookie);
HRESULT __cdecl wined3d_adapter_unregister_budget_change_notification(DWORD cookie);
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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment