dxva2: Implement handle management for device manager.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
fd72999bd6
commit
24aaf0d535
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue