Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 248 +++++++++++++++++++++++++++++++++---- dlls/mfplat/tests/mfplat.c | 156 ++++++++++++++++++++++- include/mfapi.h | 4 + 3 files changed, 380 insertions(+), 28 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 452426d055f..68aa2cdaa2d 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -8556,12 +8556,29 @@ HRESULT WINAPI CreatePropertyStore(IPropertyStore **store) return S_OK; }
+enum dxgi_device_handle_flags +{ + DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1, + DXGI_DEVICE_HANDLE_FLAG_INVALID = 0x2, + DXGI_DEVICE_HANDLE_FLAG_LOCKED = 0x4, +}; + struct dxgi_device_manager { IMFDXGIDeviceManager IMFDXGIDeviceManager_iface; LONG refcount; UINT token; IDXGIDevice *device; + + unsigned int *handles; + size_t count; + size_t capacity; + + unsigned int locks; + unsigned int locking_tid; + + CRITICAL_SECTION cs; + CONDITION_VARIABLE lock; };
static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface) @@ -8569,6 +8586,14 @@ static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceM return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface); }
+static HRESULT dxgi_device_manager_get_handle_index(struct dxgi_device_manager *manager, HANDLE hdevice, size_t *idx) +{ + if (!hdevice || hdevice > ULongToHandle(manager->count)) + return E_HANDLE; + *idx = (ULONG_PTR)hdevice - 1; + return S_OK; +} + static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj) { TRACE("(%p, %s, %p).\n", iface, debugstr_guid(riid), obj); @@ -8607,17 +8632,61 @@ static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface) { if (manager->device) IDXGIDevice_Release(manager->device); + DeleteCriticalSection(&manager->cs); + heap_free(manager->handles); heap_free(manager); }
return refcount; }
-static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE device) +static void dxgi_device_manager_lock_handle(struct dxgi_device_manager *manager, size_t idx) { - FIXME("(%p, %p): stub.\n", iface, device); + if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED) + return;
- return E_NOTIMPL; + manager->handles[idx] |= DXGI_DEVICE_HANDLE_FLAG_LOCKED; + manager->locks++; +} + +static void dxgi_device_manager_unlock_handle(struct dxgi_device_manager *manager, size_t idx) +{ + if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED)) + return; + + manager->handles[idx] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED; + if (!--manager->locks) + manager->locking_tid = 0; +} + +static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE hdevice) +{ + struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface); + HRESULT hr; + size_t idx; + + TRACE("%p, %p.\n", iface, hdevice); + + EnterCriticalSection(&manager->cs); + + if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx))) + { + if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN) + { + dxgi_device_manager_unlock_handle(manager, idx); + manager->handles[idx] = 0; + if (idx == manager->count - 1) + manager->count--; + } + else + hr = E_HANDLE; + } + + LeaveCriticalSection(&manager->cs); + + WakeAllConditionVariable(&manager->lock); + + return hr; }
static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE device, @@ -8628,57 +8697,180 @@ static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager * return E_NOTIMPL; }
-static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE device, - REFIID riid, void **ppv, BOOL block) +static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice, + REFIID riid, void **obj, BOOL block) { - FIXME("(%p, %p, %s, %p, %d): stub.\n", iface, device, wine_dbgstr_guid(riid), ppv, block); + struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface); + HRESULT hr; + size_t idx;
- return E_NOTIMPL; + TRACE("%p, %p, %s, %p, %d.\n", iface, hdevice, wine_dbgstr_guid(riid), obj, block); + + EnterCriticalSection(&manager->cs); + + if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx))) + { + if (!manager->device) + { + hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED; + } + else if (manager->locking_tid == GetCurrentThreadId()) + { + if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj))) + dxgi_device_manager_lock_handle(manager, idx); + } + else if (manager->locking_tid && !block) + { + hr = MF_E_DXGI_VIDEO_DEVICE_LOCKED; + } + else + { + while (manager->locking_tid) + { + SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE); + } + + if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx))) + { + if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID) + hr = MF_E_DXGI_NEW_VIDEO_DEVICE; + else if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj))) + { + manager->locking_tid = GetCurrentThreadId(); + dxgi_device_manager_lock_handle(manager, idx); + } + } + } + } + + LeaveCriticalSection(&manager->cs); + + return hr; }
-static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *device) +static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *hdevice) { - FIXME("(%p, %p): stub.\n", iface, device); + struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(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 = MF_E_DXGI_DEVICE_NOT_INITIALIZED; + else + { + for (i = 0; i < manager->count; ++i) + { + if (!(manager->handles[i] & DXGI_DEVICE_HANDLE_FLAG_OPEN)) + { + manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_OPEN; + *hdevice = ULongToHandle(i + 1); + break; + } + } + + if (mf_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1, + sizeof(*manager->handles))) + { + *hdevice = ULongToHandle(manager->count + 1); + manager->handles[manager->count++] = DXGI_DEVICE_HANDLE_FLAG_OPEN; + } + else + hr = E_OUTOFMEMORY; + } + + LeaveCriticalSection(&manager->cs); + + return hr; }
static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token) { struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface); IDXGIDevice *dxgi_device; - HRESULT hr; + size_t i;
- TRACE("(%p, %p, %u).\n", iface, device, token); + TRACE("%p, %p, %u.\n", iface, device, token);
if (!device || token != manager->token) return E_INVALIDARG;
- hr = IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device); - if (SUCCEEDED(hr)) + if (FAILED(IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device))) + return E_INVALIDARG; + + EnterCriticalSection(&manager->cs); + + if (manager->device) { - if (manager->device) - IDXGIDevice_Release(manager->device); - manager->device = dxgi_device; + for (i = 0; i < manager->count; ++i) + { + manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_INVALID; + manager->handles[i] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED; + } + manager->locking_tid = 0; + manager->locks = 0; + IDXGIDevice_Release(manager->device); } - else - hr = E_INVALIDARG; + manager->device = dxgi_device;
- return hr; + LeaveCriticalSection(&manager->cs); + + WakeAllConditionVariable(&manager->lock); + + return S_OK; }
-static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE device) +static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice) { - FIXME("(%p, %p): stub.\n", iface, device); + struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface); + HRESULT hr; + size_t idx;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, hdevice); + + EnterCriticalSection(&manager->cs); + + if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx))) + { + if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID) + hr = MF_E_DXGI_NEW_VIDEO_DEVICE; + else if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)) + hr = E_HANDLE; + } + + LeaveCriticalSection(&manager->cs); + + return hr; }
-static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE device, BOOL state) +static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice, + BOOL savestate) { - FIXME("(%p, %p, %d): stub.\n", iface, device, state); + struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface); + HRESULT hr = E_FAIL; + size_t idx;
- return E_NOTIMPL; + TRACE("%p, %p, %d.\n", iface, hdevice, savestate); + + EnterCriticalSection(&manager->cs); + + if (SUCCEEDED(dxgi_device_manager_get_handle_index(manager, hdevice, &idx))) + { + hr = manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED ? S_OK : E_INVALIDARG; + if (SUCCEEDED(hr)) + dxgi_device_manager_unlock_handle(manager, idx); + } + + LeaveCriticalSection(&manager->cs); + + WakeAllConditionVariable(&manager->lock); + + return hr; }
static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl = @@ -8699,7 +8891,7 @@ HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **man { struct dxgi_device_manager *object;
- TRACE("(%p, %p).\n", token, manager); + TRACE("%p, %p.\n", token, manager);
if (!token || !manager) return E_POINTER; @@ -8712,6 +8904,8 @@ HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **man object->refcount = 1; object->token = GetTickCount(); object->device = NULL; + InitializeCriticalSection(&object->cs); + InitializeConditionVariable(&object->lock);
TRACE("Created device manager: %p, token: %u.\n", object, object->token);
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index a5388840bc5..17371a0e1c0 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -4497,10 +4497,38 @@ if (0) ok(!refcount, "Unexpected refcount %u.\n", refcount); }
+struct test_thread_param +{ + IMFDXGIDeviceManager *manager; + HANDLE handle; + BOOL lock; +}; + +static DWORD WINAPI test_device_manager_thread(void *arg) +{ + struct test_thread_param *param = arg; + ID3D11Device *device; + HRESULT hr; + + if (param->lock) + { + hr = IMFDXGIDeviceManager_LockDevice(param->manager, param->handle, &IID_ID3D11Device, + (void **)&device, FALSE); + if (SUCCEEDED(hr)) + ID3D11Device_Release(device); + } + else + hr = IMFDXGIDeviceManager_UnlockDevice(param->manager, param->handle, FALSE); + + return hr; +} + static void test_dxgi_device_manager(void) { IMFDXGIDeviceManager *manager, *manager2; - ID3D11Device *d3d11_dev, *d3d11_dev2; + ID3D11Device *device, *d3d11_dev, *d3d11_dev2; + struct test_thread_param param; + HANDLE handle1, handle, thread; UINT token, token2; HRESULT hr;
@@ -4532,6 +4560,12 @@ static void test_dxgi_device_manager(void) ok(manager != manager2, "got wrong pointer: %p.\n", manager2); EXPECT_REF(manager, 1);
+ hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle); + ok(hr == MF_E_DXGI_DEVICE_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, 0); + ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr); + hr = pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_VIDEO_SUPPORT, NULL, 0, D3D11_SDK_VERSION, &d3d11_dev, NULL, NULL); ok(hr == S_OK, "D3D11CreateDevice failed: %#x.\n", hr); @@ -4569,6 +4603,126 @@ static void test_dxgi_device_manager(void) EXPECT_REF(d3d11_dev2, 2); EXPECT_REF(d3d11_dev, 1);
+ handle = NULL; + hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!handle, "Unexpected handle value %p.\n", handle); + + handle1 = NULL; + hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(handle != handle1, "Unexpected handle.\n"); + + hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + /* Already closed. */ + hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle); + ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr); + + handle = NULL; + hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_TestDevice(manager, handle1); + ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_LockDevice(manager, handle, &IID_ID3D11Device, (void **)&device, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(device == d3d11_dev2, "Unexpected device pointer.\n"); + ID3D11Device_Release(device); + + hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle, FALSE); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_UnlockDevice(manager, UlongToHandle(100), FALSE); + ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr); + + /* Locked with one handle, unlock with another. */ + hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_LockDevice(manager, handle, &IID_ID3D11Device, (void **)&device, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle1, FALSE); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + ID3D11Device_Release(device); + + /* Closing unlocks the device. */ + hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_LockDevice(manager, handle1, &IID_ID3D11Device, (void **)&device, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ID3D11Device_Release(device); + + hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + /* Open two handles. */ + hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_LockDevice(manager, handle, &IID_ID3D11Device, (void **)&device, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ID3D11Device_Release(device); + + hr = IMFDXGIDeviceManager_LockDevice(manager, handle1, &IID_ID3D11Device, (void **)&device, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ID3D11Device_Release(device); + + hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle, FALSE); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + param.manager = manager; + param.handle = handle; + param.lock = TRUE; + thread = CreateThread(NULL, 0, test_device_manager_thread, ¶m, 0, NULL); + ok(!WaitForSingleObject(thread, 1000), "Wait for a test thread failed.\n"); + GetExitCodeThread(thread, (DWORD *)&hr); + ok(hr == MF_E_DXGI_VIDEO_DEVICE_LOCKED, "Unexpected hr %#x.\n", hr); + CloseHandle(thread); + + hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle1, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle1, FALSE); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + /* Lock on main thread, unlock on another. */ + hr = IMFDXGIDeviceManager_LockDevice(manager, handle, &IID_ID3D11Device, (void **)&device, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ID3D11Device_Release(device); + + param.manager = manager; + param.handle = handle; + param.lock = FALSE; + thread = CreateThread(NULL, 0, test_device_manager_thread, ¶m, 0, NULL); + ok(!WaitForSingleObject(thread, 1000), "Wait for a test thread failed.\n"); + GetExitCodeThread(thread, (DWORD *)&hr); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + CloseHandle(thread); + + hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IMFDXGIDeviceManager_Release(manager); EXPECT_REF(d3d11_dev2, 1); ID3D11Device_Release(d3d11_dev); diff --git a/include/mfapi.h b/include/mfapi.h index 499c77ab337..25fced1c7d6 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -482,6 +482,10 @@ typedef enum #define MFSESSIONCAP_RATE_REVERSE 0x00000020 #define MFSESSIONCAP_DOES_NOT_USE_NETWORK 0x00000040
+#define MF_E_DXGI_DEVICE_NOT_INITIALIZED ((HRESULT)0x80041000) +#define MF_E_DXGI_NEW_VIDEO_DEVICE ((HRESULT)0x80041001) +#define MF_E_DXGI_VIDEO_DEVICE_LOCKED ((HRESULT)0x80041002) + HRESULT WINAPI MFAddPeriodicCallback(MFPERIODICCALLBACK callback, IUnknown *context, DWORD *key); HRESULT WINAPI MFAllocateSerialWorkQueue(DWORD target_queue, DWORD *queue); HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 28 ++++++++++++++++++++++++---- dlls/mfplat/tests/mfplat.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 68aa2cdaa2d..1c51fafff1e 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -8689,12 +8689,32 @@ static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager return hr; }
-static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE device, - REFIID riid, void **service) +static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE hdevice, + REFIID riid, void **service) { - FIXME("(%p, %p, %s, %p): stub.\n", iface, device, debugstr_guid(riid), service); + struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface); + HRESULT hr; + size_t idx;
- return E_NOTIMPL; + TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), service); + + EnterCriticalSection(&manager->cs); + + if (!manager->device) + hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED; + else if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx))) + { + if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID) + hr = MF_E_DXGI_NEW_VIDEO_DEVICE; + else if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN) + hr = IDXGIDevice_QueryInterface(manager->device, riid, service); + else + hr = E_HANDLE; + } + + LeaveCriticalSection(&manager->cs); + + return hr; }
static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice, diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 17371a0e1c0..971469ec574 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -4530,6 +4530,7 @@ static void test_dxgi_device_manager(void) struct test_thread_param param; HANDLE handle1, handle, thread; UINT token, token2; + IUnknown *unk; HRESULT hr;
if (!pMFCreateDXGIDeviceManager) @@ -4560,6 +4561,9 @@ static void test_dxgi_device_manager(void) ok(manager != manager2, "got wrong pointer: %p.\n", manager2); EXPECT_REF(manager, 1);
+ hr = IMFDXGIDeviceManager_GetVideoService(manager, NULL, &IID_ID3D11Device, (void **)&unk); + ok(hr == MF_E_DXGI_DEVICE_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr); + hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle); ok(hr == MF_E_DXGI_DEVICE_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
@@ -4593,6 +4597,12 @@ static void test_dxgi_device_manager(void) EXPECT_REF(manager, 1); EXPECT_REF(d3d11_dev, 2);
+ /* GetVideoService() on device change. */ + handle = NULL; + hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!handle, "Unexpected handle value %p.\n", handle); + hr = pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &d3d11_dev2, NULL, NULL); ok(hr == S_OK, "D3D11CreateDevice failed: %#x.\n", hr); @@ -4603,11 +4613,32 @@ static void test_dxgi_device_manager(void) EXPECT_REF(d3d11_dev2, 2); EXPECT_REF(d3d11_dev, 1);
+ hr = IMFDXGIDeviceManager_GetVideoService(manager, handle, &IID_ID3D11Device, (void **)&unk); + ok(hr == MF_E_DXGI_NEW_VIDEO_DEVICE, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + handle = NULL; hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(!!handle, "Unexpected handle value %p.\n", handle);
+ hr = IMFDXGIDeviceManager_GetVideoService(manager, NULL, &IID_ID3D11Device, (void **)&unk); + ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr); + + hr = IMFDXGIDeviceManager_GetVideoService(manager, handle, &IID_ID3D11Device, (void **)&unk); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IUnknown_Release(unk); + + hr = IMFDXGIDeviceManager_GetVideoService(manager, handle, &IID_IUnknown, (void **)&unk); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IUnknown_Release(unk); + + hr = IMFDXGIDeviceManager_GetVideoService(manager, handle, &IID_IDXGIDevice, (void **)&unk); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IUnknown_Release(unk); + handle1 = NULL; hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle1); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);