Nikolay Sivov : dxva2: Implement handle management for device manager.
Alexandre Julliard
julliard at winehq.org
Mon Jun 22 15:55:58 CDT 2020
Module: wine
Branch: master
Commit: 24aaf0d535b6c5c0d56b1e50deb2e47d3cce9ab8
URL: https://source.winehq.org/git/wine.git/?a=commit;h=24aaf0d535b6c5c0d56b1e50deb2e47d3cce9ab8
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Mon Jun 22 13:45:30 2020 +0300
dxva2: Implement handle management for device manager.
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/dxva2/main.c | 158 ++++++++++++++++++++++++++++++++++++++++++++---
dlls/dxva2/tests/dxva2.c | 16 +----
2 files changed, 151 insertions(+), 23 deletions(-)
diff --git a/dlls/dxva2/main.c b/dlls/dxva2/main.c
index e1eb212843..7e983a43dd 100644
--- a/dlls/dxva2/main.c
+++ b/dlls/dxva2/main.c
@@ -33,14 +33,59 @@
WINE_DEFAULT_DEBUG_CHANNEL(dxva2);
+enum device_handle_flags
+{
+ HANDLE_FLAG_OPEN = 0x1,
+ HANDLE_FLAG_INVALID = 0x2,
+};
+
+struct device_handle
+{
+ unsigned int flags;
+};
+
struct device_manager
{
IDirect3DDeviceManager9 IDirect3DDeviceManager9_iface;
LONG refcount;
+ IDirect3DDevice9 *device;
UINT token;
+
+ struct device_handle *handles;
+ size_t count;
+ size_t capacity;
+
+ CRITICAL_SECTION cs;
};
+static BOOL dxva_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
+{
+ size_t new_capacity, max_capacity;
+ void *new_elements;
+
+ if (count <= *capacity)
+ return TRUE;
+
+ max_capacity = ~(SIZE_T)0 / size;
+ if (count > max_capacity)
+ return FALSE;
+
+ new_capacity = max(4, *capacity);
+ while (new_capacity < count && new_capacity <= max_capacity / 2)
+ new_capacity *= 2;
+ if (new_capacity < count)
+ new_capacity = max_capacity;
+
+ if (!(new_elements = heap_realloc(*elements, new_capacity * size)))
+ return FALSE;
+
+ *elements = new_elements;
+ *capacity = new_capacity;
+
+ return TRUE;
+}
+
static struct device_manager *impl_from_IDirect3DDeviceManager9(IDirect3DDeviceManager9 *iface)
{
return CONTAINING_RECORD(iface, struct device_manager, IDirect3DDeviceManager9_iface);
@@ -82,6 +127,10 @@ static ULONG WINAPI device_manager_Release(IDirect3DDeviceManager9 *iface)
if (!refcount)
{
+ if (manager->device)
+ IDirect3DDevice9_Release(manager->device);
+ DeleteCriticalSection(&manager->cs);
+ heap_free(manager->handles);
heap_free(manager);
}
@@ -91,30 +140,122 @@ static ULONG WINAPI device_manager_Release(IDirect3DDeviceManager9 *iface)
static HRESULT WINAPI device_manager_ResetDevice(IDirect3DDeviceManager9 *iface, IDirect3DDevice9 *device,
UINT token)
{
- FIXME("%p, %p, %#x.\n", iface, device, token);
+ struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
+ size_t i;
- return E_NOTIMPL;
+ TRACE("%p, %p, %#x.\n", iface, device, token);
+
+ if (token != manager->token)
+ return E_INVALIDARG;
+
+ EnterCriticalSection(&manager->cs);
+ if (manager->device)
+ {
+ for (i = 0; i < manager->count; ++i)
+ manager->handles[i].flags |= HANDLE_FLAG_INVALID;
+ IDirect3DDevice9_Release(manager->device);
+ }
+ manager->device = device;
+ IDirect3DDevice9_AddRef(manager->device);
+ LeaveCriticalSection(&manager->cs);
+
+ return S_OK;
}
static HRESULT WINAPI device_manager_OpenDeviceHandle(IDirect3DDeviceManager9 *iface, HANDLE *hdevice)
{
- FIXME("%p, %p.\n", iface, hdevice);
+ struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
+ HRESULT hr = S_OK;
+ size_t i;
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, hdevice);
+
+ *hdevice = NULL;
+
+ EnterCriticalSection(&manager->cs);
+ if (!manager->device)
+ hr = DXVA2_E_NOT_INITIALIZED;
+ else
+ {
+ for (i = 0; i < manager->count; ++i)
+ {
+ if (!(manager->handles[i].flags & HANDLE_FLAG_OPEN))
+ {
+ manager->handles[i].flags |= HANDLE_FLAG_OPEN;
+ *hdevice = ULongToHandle(i + 1);
+ break;
+ }
+ }
+
+ if (dxva_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
+ sizeof(*manager->handles)))
+ {
+ *hdevice = ULongToHandle(manager->count + 1);
+ manager->handles[manager->count].flags |= HANDLE_FLAG_OPEN;
+ manager->count++;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+ LeaveCriticalSection(&manager->cs);
+
+ return hr;
+}
+
+static HRESULT device_manager_get_handle_index(struct device_manager *manager, HANDLE hdevice, size_t *idx)
+{
+ if (hdevice > ULongToHandle(manager->count))
+ return E_HANDLE;
+ *idx = (ULONG_PTR)hdevice - 1;
+ return S_OK;
}
static HRESULT WINAPI device_manager_CloseDeviceHandle(IDirect3DDeviceManager9 *iface, HANDLE hdevice)
{
- FIXME("%p, %p.\n", iface, hdevice);
+ struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
+ HRESULT hr;
+ size_t idx;
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, hdevice);
+
+ EnterCriticalSection(&manager->cs);
+ if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
+ {
+ if (manager->handles[idx].flags & HANDLE_FLAG_OPEN)
+ {
+ manager->handles[idx].flags = 0;
+ if (idx == manager->count - 1)
+ manager->count--;
+ }
+ else
+ hr = E_HANDLE;
+ }
+ LeaveCriticalSection(&manager->cs);
+
+ return hr;
}
static HRESULT WINAPI device_manager_TestDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice)
{
- FIXME("%p, %p.\n", iface, hdevice);
+ struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
+ HRESULT hr;
+ size_t idx;
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, hdevice);
+
+ EnterCriticalSection(&manager->cs);
+ if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
+ {
+ unsigned int flags = manager->handles[idx].flags;
+
+ if (flags & HANDLE_FLAG_INVALID)
+ hr = DXVA2_E_NEW_VIDEO_DEVICE;
+ else if (!(flags & HANDLE_FLAG_OPEN))
+ hr = E_HANDLE;
+ }
+ LeaveCriticalSection(&manager->cs);
+
+ return hr;
}
static HRESULT WINAPI device_manager_LockDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice,
@@ -176,6 +317,7 @@ HRESULT WINAPI DXVA2CreateDirect3DDeviceManager9(UINT *token, IDirect3DDeviceMan
object->IDirect3DDeviceManager9_iface.lpVtbl = &device_manager_vtbl;
object->refcount = 1;
object->token = GetTickCount();
+ InitializeCriticalSection(&object->cs);
*token = object->token;
*manager = &object->IDirect3DDeviceManager9_iface;
diff --git a/dlls/dxva2/tests/dxva2.c b/dlls/dxva2/tests/dxva2.c
index cbcad40ca5..605a69dd5a 100644
--- a/dlls/dxva2/tests/dxva2.c
+++ b/dlls/dxva2/tests/dxva2.c
@@ -84,23 +84,19 @@ static void test_device_manager(void)
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle);
-todo_wine
ok(hr == DXVA2_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
/* Invalid token. */
hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token + 1);
-todo_wine
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token);
-todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
refcount = get_refcount((IUnknown *)device);
handle1 = NULL;
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle1);
-todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
refcount2 = get_refcount((IUnknown *)device);
@@ -108,40 +104,32 @@ todo_wine
handle = NULL;
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle);
-todo_wine {
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(handle != handle1, "Unexpected handle.\n");
-}
+
hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle);
-todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
/* Already closed. */
hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle);
-todo_wine
ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr);
handle = NULL;
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle);
-todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle1);
-todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_TestDevice(manager, handle1);
-todo_wine
ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr);
handle = NULL;
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle);
-todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
handle1 = NULL;
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle1);
-todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, &IID_IDirectXVideoProcessorService,
@@ -153,7 +141,6 @@ todo_wine
device2 = create_device(d3d, window);
hr = IDirect3DDeviceManager9_ResetDevice(manager, device2, token);
-todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, &IID_IDirectXVideoProcessorService,
@@ -162,7 +149,6 @@ todo_wine
ok(hr == DXVA2_E_NEW_VIDEO_DEVICE, "Unexpected hr %#x.\n", hr);
hr = IDirect3DDeviceManager9_TestDevice(manager, handle);
-todo_wine
ok(hr == DXVA2_E_NEW_VIDEO_DEVICE, "Unexpected hr %#x.\n", hr);
IDirect3DDevice9_Release(device);
More information about the wine-cvs
mailing list