Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 65 ++++++++++++++++++++++++++++++++++++++ dlls/mfplat/mfplat.spec | 2 ++ dlls/mfplat/tests/mfplat.c | 39 +++++++++++++++++++++++ 3 files changed, 106 insertions(+)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 2e5f17eb2af..9d2842c7170 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -8564,6 +8564,16 @@ HRESULT WINAPI CreatePropertyStore(IPropertyStore **store) return S_OK; }
+struct shared_dxgi_manager +{ + IMFDXGIDeviceManager *manager; + unsigned int token; + unsigned int locks; +}; + +static struct shared_dxgi_manager shared_dm; +static CRITICAL_SECTION shared_dm_cs = { NULL, -1, 0, 0, 0, 0 }; + enum dxgi_device_handle_flags { DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1, @@ -8915,6 +8925,9 @@ static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl = dxgi_device_manager_UnlockDevice, };
+/*********************************************************************** + * MFCreateDXGIDeviceManager (mfplat.@) + */ HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager) { struct dxgi_device_manager *object; @@ -8941,6 +8954,58 @@ HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **man return S_OK; }
+/*********************************************************************** + * MFLockDXGIDeviceManager (mfplat.@) + */ +HRESULT WINAPI MFLockDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager) +{ + HRESULT hr = S_OK; + + TRACE("%p, %p.\n", token, manager); + + EnterCriticalSection(&shared_dm_cs); + + if (!shared_dm.manager) + hr = MFCreateDXGIDeviceManager(&shared_dm.token, &shared_dm.manager); + + if (SUCCEEDED(hr)) + { + *manager = shared_dm.manager; + IMFDXGIDeviceManager_AddRef(*manager); + shared_dm.locks++; + + if (token) *token = shared_dm.token; + } + + LeaveCriticalSection(&shared_dm_cs); + + return hr; +} + +/*********************************************************************** + * MFUnlockDXGIDeviceManager (mfplat.@) + */ +HRESULT WINAPI MFUnlockDXGIDeviceManager(void) +{ + TRACE("\n"); + + EnterCriticalSection(&shared_dm_cs); + + if (shared_dm.manager) + { + IMFDXGIDeviceManager_Release(shared_dm.manager); + if (!--shared_dm.locks) + { + shared_dm.manager = NULL; + shared_dm.token = 0; + } + } + + LeaveCriticalSection(&shared_dm_cs); + + return S_OK; +} + static void llmult128(ULARGE_INTEGER *c1, ULARGE_INTEGER *c0, LONGLONG val, LONGLONG num) { ULARGE_INTEGER a1, b0, v, n; diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index d8558cee0cb..e8dc01c200c 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -131,6 +131,7 @@ @ stdcall MFInvokeCallback(ptr) @ stub MFJoinIoPort @ stdcall MFJoinWorkQueue(long long ptr) rtworkq.RtwqJoinWorkQueue +@ stdcall MFLockDXGIDeviceManager(ptr ptr) @ stdcall MFLockPlatform() rtworkq.RtwqLockPlatform @ stdcall MFLockSharedWorkQueue(wstr long ptr ptr) rtworkq.RtwqLockSharedWorkQueue @ stdcall MFLockWorkQueue(long) rtworkq.RtwqLockWorkQueue @@ -171,6 +172,7 @@ @ stub MFTraceFuncEnter @ stub MFUnblockThread @ stdcall MFUnjoinWorkQueue(long long) rtworkq.RtwqUnjoinWorkQueue +@ stdcall MFUnlockDXGIDeviceManager() @ stdcall MFUnlockPlatform() rtworkq.RtwqUnlockPlatform @ stdcall MFUnlockWorkQueue(long) rtworkq.RtwqUnlockWorkQueue @ stdcall MFUnwrapMediaType(ptr ptr) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index b0c7298c28d..65ab72bd57b 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -262,6 +262,8 @@ static HRESULT (WINAPI *pMFCreateDXGISurfaceBuffer)(REFIID riid, IUnknown *surfa IMFMediaBuffer **buffer); static HRESULT (WINAPI *pMFCreateVideoMediaTypeFromSubtype)(const GUID *subtype, IMFVideoMediaType **media_type); static HRESULT (WINAPI *pMFLockSharedWorkQueue)(const WCHAR *name, LONG base_priority, DWORD *taskid, DWORD *queue); +static HRESULT (WINAPI *pMFLockDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager); +static HRESULT (WINAPI *pMFUnlockDXGIDeviceManager)(void);
static HWND create_window(void) { @@ -935,6 +937,7 @@ static void init_functions(void) X(MFCreateVideoSampleAllocatorEx); X(MFGetPlaneSize); X(MFGetStrideForBitmapInfoHeader); + X(MFLockDXGIDeviceManager); X(MFLockSharedWorkQueue); X(MFMapDX9FormatToDXGIFormat); X(MFMapDXGIFormatToDX9Format); @@ -947,6 +950,7 @@ static void init_functions(void) X(MFTRegisterLocalByCLSID); X(MFTUnregisterLocal); X(MFTUnregisterLocalByCLSID); + X(MFUnlockDXGIDeviceManager);
if ((mod = LoadLibraryA("d3d11.dll"))) { @@ -7168,6 +7172,40 @@ static void test_MFllMulDiv(void) } }
+static void test_shared_dxgi_device_manager(void) +{ + IMFDXGIDeviceManager *manager; + HRESULT hr; + UINT token; + + if (!pMFLockDXGIDeviceManager) + { + win_skip("Shared DXGI device manager is not supported.\n"); + return; + } + + hr = pMFUnlockDXGIDeviceManager(); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + manager = NULL; + hr = pMFLockDXGIDeviceManager(NULL, &manager); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!manager, "Unexpected instance.\n"); + + hr = pMFLockDXGIDeviceManager(&token, &manager); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + EXPECT_REF(manager, 3); + + hr = pMFUnlockDXGIDeviceManager(); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + EXPECT_REF(manager, 2); + + hr = pMFUnlockDXGIDeviceManager(); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); +} + START_TEST(mfplat) { char **argv; @@ -7233,6 +7271,7 @@ START_TEST(mfplat) test_sample_allocator(); test_MFMapDX9FormatToDXGIFormat(); test_MFllMulDiv(); + test_shared_dxgi_device_manager();
CoUninitialize(); }