dxva2: Implement locking functionality in device manager.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b61455cb81
commit
431324ba63
|
@ -42,6 +42,7 @@ enum device_handle_flags
|
|||
struct device_handle
|
||||
{
|
||||
unsigned int flags;
|
||||
IDirect3DStateBlock9 *state_block;
|
||||
};
|
||||
|
||||
struct device_manager
|
||||
|
@ -57,7 +58,10 @@ struct device_manager
|
|||
size_t count;
|
||||
size_t capacity;
|
||||
|
||||
HANDLE locking_handle;
|
||||
|
||||
CRITICAL_SECTION cs;
|
||||
CONDITION_VARIABLE lock;
|
||||
};
|
||||
|
||||
static BOOL dxva_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
|
||||
|
@ -254,6 +258,7 @@ static ULONG WINAPI device_manager_Release(IDirect3DDeviceManager9 *iface)
|
|||
{
|
||||
struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
|
||||
ULONG refcount = InterlockedDecrement(&manager->refcount);
|
||||
size_t i;
|
||||
|
||||
TRACE("%p, refcount %u.\n", iface, refcount);
|
||||
|
||||
|
@ -262,6 +267,11 @@ static ULONG WINAPI device_manager_Release(IDirect3DDeviceManager9 *iface)
|
|||
if (manager->device)
|
||||
IDirect3DDevice9_Release(manager->device);
|
||||
DeleteCriticalSection(&manager->cs);
|
||||
for (i = 0; i < manager->count; ++i)
|
||||
{
|
||||
if (manager->handles[i].state_block)
|
||||
IDirect3DStateBlock9_Release(manager->handles[i].state_block);
|
||||
}
|
||||
heap_free(manager->handles);
|
||||
heap_free(manager);
|
||||
}
|
||||
|
@ -284,13 +294,21 @@ static HRESULT WINAPI device_manager_ResetDevice(IDirect3DDeviceManager9 *iface,
|
|||
if (manager->device)
|
||||
{
|
||||
for (i = 0; i < manager->count; ++i)
|
||||
{
|
||||
if (manager->handles[i].state_block)
|
||||
IDirect3DStateBlock9_Release(manager->handles[i].state_block);
|
||||
manager->handles[i].state_block = NULL;
|
||||
manager->handles[i].flags |= HANDLE_FLAG_INVALID;
|
||||
}
|
||||
manager->locking_handle = NULL;
|
||||
IDirect3DDevice9_Release(manager->device);
|
||||
}
|
||||
manager->device = device;
|
||||
IDirect3DDevice9_AddRef(manager->device);
|
||||
LeaveCriticalSection(&manager->cs);
|
||||
|
||||
WakeAllConditionVariable(&manager->lock);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -324,6 +342,7 @@ static HRESULT WINAPI device_manager_OpenDeviceHandle(IDirect3DDeviceManager9 *i
|
|||
{
|
||||
*hdevice = ULongToHandle(manager->count + 1);
|
||||
manager->handles[manager->count].flags |= HANDLE_FLAG_OPEN;
|
||||
manager->handles[manager->count].state_block = NULL;
|
||||
manager->count++;
|
||||
}
|
||||
else
|
||||
|
@ -355,15 +374,22 @@ static HRESULT WINAPI device_manager_CloseDeviceHandle(IDirect3DDeviceManager9 *
|
|||
{
|
||||
if (manager->handles[idx].flags & HANDLE_FLAG_OPEN)
|
||||
{
|
||||
if (manager->locking_handle == hdevice)
|
||||
manager->locking_handle = NULL;
|
||||
manager->handles[idx].flags = 0;
|
||||
if (idx == manager->count - 1)
|
||||
manager->count--;
|
||||
if (manager->handles[idx].state_block)
|
||||
IDirect3DStateBlock9_Release(manager->handles[idx].state_block);
|
||||
manager->handles[idx].state_block = NULL;
|
||||
}
|
||||
else
|
||||
hr = E_HANDLE;
|
||||
}
|
||||
LeaveCriticalSection(&manager->cs);
|
||||
|
||||
WakeAllConditionVariable(&manager->lock);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -393,16 +419,75 @@ static HRESULT WINAPI device_manager_TestDevice(IDirect3DDeviceManager9 *iface,
|
|||
static HRESULT WINAPI device_manager_LockDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice,
|
||||
IDirect3DDevice9 **device, BOOL block)
|
||||
{
|
||||
FIXME("%p, %p, %p, %d.\n", iface, hdevice, device, block);
|
||||
struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
|
||||
HRESULT hr;
|
||||
size_t idx;
|
||||
|
||||
return E_NOTIMPL;
|
||||
TRACE("%p, %p, %p, %d.\n", iface, hdevice, device, block);
|
||||
|
||||
EnterCriticalSection(&manager->cs);
|
||||
if (!manager->device)
|
||||
hr = DXVA2_E_NOT_INITIALIZED;
|
||||
else if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
|
||||
{
|
||||
if (manager->locking_handle && !block)
|
||||
hr = DXVA2_E_VIDEO_DEVICE_LOCKED;
|
||||
else
|
||||
{
|
||||
while (manager->locking_handle && block)
|
||||
{
|
||||
SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
|
||||
{
|
||||
if (manager->handles[idx].flags & HANDLE_FLAG_INVALID)
|
||||
hr = DXVA2_E_NEW_VIDEO_DEVICE;
|
||||
else
|
||||
{
|
||||
if (manager->handles[idx].state_block)
|
||||
{
|
||||
if (FAILED(IDirect3DStateBlock9_Apply(manager->handles[idx].state_block)))
|
||||
WARN("Failed to apply state.\n");
|
||||
IDirect3DStateBlock9_Release(manager->handles[idx].state_block);
|
||||
manager->handles[idx].state_block = NULL;
|
||||
}
|
||||
*device = manager->device;
|
||||
IDirect3DDevice9_AddRef(*device);
|
||||
manager->locking_handle = hdevice;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&manager->cs);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI device_manager_UnlockDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice, BOOL savestate)
|
||||
{
|
||||
FIXME("%p, %p, %d.\n", iface, hdevice, savestate);
|
||||
struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
|
||||
HRESULT hr;
|
||||
size_t idx;
|
||||
|
||||
return E_NOTIMPL;
|
||||
TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
|
||||
|
||||
EnterCriticalSection(&manager->cs);
|
||||
|
||||
if (hdevice != manager->locking_handle)
|
||||
hr = E_INVALIDARG;
|
||||
else if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
|
||||
{
|
||||
manager->locking_handle = NULL;
|
||||
if (savestate)
|
||||
IDirect3DDevice9_CreateStateBlock(manager->device, D3DSBT_ALL, &manager->handles[idx].state_block);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&manager->cs);
|
||||
|
||||
WakeAllConditionVariable(&manager->lock);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI device_manager_GetVideoService(IDirect3DDeviceManager9 *iface, HANDLE hdevice, REFIID riid,
|
||||
|
@ -470,6 +555,7 @@ HRESULT WINAPI DXVA2CreateDirect3DDeviceManager9(UINT *token, IDirect3DDeviceMan
|
|||
object->refcount = 1;
|
||||
object->token = GetTickCount();
|
||||
InitializeCriticalSection(&object->cs);
|
||||
InitializeConditionVariable(&object->lock);
|
||||
|
||||
*token = object->token;
|
||||
*manager = &object->IDirect3DDeviceManager9_iface;
|
||||
|
|
|
@ -72,6 +72,7 @@ static void test_device_manager(void)
|
|||
HWND window;
|
||||
UINT token;
|
||||
HRESULT hr;
|
||||
RECT rect;
|
||||
|
||||
window = create_window();
|
||||
d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
|
@ -88,13 +89,15 @@ static void test_device_manager(void)
|
|||
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle);
|
||||
ok(hr == DXVA2_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_LockDevice(manager, 0, &device2, FALSE);
|
||||
ok(hr == DXVA2_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Invalid token. */
|
||||
hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token + 1);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
refcount = get_refcount((IUnknown *)device);
|
||||
|
||||
handle1 = NULL;
|
||||
|
@ -140,6 +143,7 @@ static void test_device_manager(void)
|
|||
IDirectXVideoProcessorService_Release(processor_service);
|
||||
|
||||
device2 = create_device(d3d, window);
|
||||
|
||||
hr = IDirect3DDeviceManager9_ResetDevice(manager, device2, token);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
|
@ -150,6 +154,110 @@ static void test_device_manager(void)
|
|||
hr = IDirect3DDeviceManager9_TestDevice(manager, handle);
|
||||
ok(hr == DXVA2_E_NEW_VIDEO_DEVICE, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Lock/Unlock. */
|
||||
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_LockDevice(manager, handle, &device3, FALSE);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(device2 == device3, "Unexpected device pointer.\n");
|
||||
IDirect3DDevice9_Release(device3);
|
||||
|
||||
hr = IDirect3DDeviceManager9_UnlockDevice(manager, handle, FALSE);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_UnlockDevice(manager, handle, FALSE);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_UnlockDevice(manager, (HANDLE)((ULONG_PTR)handle + 100), FALSE);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Locked with one handle, unlock with another. */
|
||||
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle1);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_LockDevice(manager, handle, &device3, FALSE);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(device2 == device3, "Unexpected device pointer.\n");
|
||||
IDirect3DDevice9_Release(device3);
|
||||
|
||||
hr = IDirect3DDeviceManager9_UnlockDevice(manager, handle1, FALSE);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Closing unlocks the device. */
|
||||
hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_LockDevice(manager, handle1, &device3, FALSE);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(device2 == device3, "Unexpected device pointer.\n");
|
||||
IDirect3DDevice9_Release(device3);
|
||||
|
||||
hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle1);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Open two handles. */
|
||||
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle1);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_LockDevice(manager, handle, &device3, FALSE);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(device2 == device3, "Unexpected device pointer.\n");
|
||||
IDirect3DDevice9_Release(device3);
|
||||
|
||||
hr = IDirect3DDeviceManager9_LockDevice(manager, handle1, &device3, FALSE);
|
||||
ok(hr == DXVA2_E_VIDEO_DEVICE_LOCKED, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle1);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* State saving function. */
|
||||
hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_LockDevice(manager, handle, &device3, FALSE);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(device2 == device3, "Unexpected device pointer.\n");
|
||||
|
||||
SetRect(&rect, 50, 60, 70, 80);
|
||||
hr = IDirect3DDevice9_SetScissorRect(device3, &rect);
|
||||
ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_UnlockDevice(manager, handle, TRUE);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
SetRect(&rect, 30, 60, 70, 80);
|
||||
hr = IDirect3DDevice9_SetScissorRect(device3, &rect);
|
||||
ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
|
||||
|
||||
IDirect3DDevice9_Release(device3);
|
||||
|
||||
hr = IDirect3DDeviceManager9_LockDevice(manager, handle, &device3, FALSE);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(device2 == device3, "Unexpected device pointer.\n");
|
||||
|
||||
hr = IDirect3DDevice9_GetScissorRect(device3, &rect);
|
||||
ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
|
||||
ok(rect.left == 50 && rect.top == 60 && rect.right == 70 && rect.bottom == 80,
|
||||
"Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
|
||||
|
||||
IDirect3DDevice9_Release(device3);
|
||||
|
||||
hr = IDirect3DDeviceManager9_UnlockDevice(manager, handle, TRUE);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Acceleration service. */
|
||||
hr = DXVA2CreateVideoService(device, &IID_IDirectXVideoAccelerationService, (void **)&accel_service);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
|
Loading…
Reference in New Issue