Signed-off-by: Jactry Zeng jzeng@codeweavers.com --- dlls/mfplat/main.c | 158 +++++++++++++++++++++++++++++++++++++ dlls/mfplat/mfplat.spec | 1 + dlls/mfplat/tests/mfplat.c | 75 ++++++++++++++++++ include/mfapi.h | 1 + include/mfobjects.idl | 17 ++++ 5 files changed, 252 insertions(+)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index f8f4b502a5..c2293cfd8b 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -7617,3 +7617,161 @@ HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
return S_OK; } + +struct mfdxgi_dev_mgr +{ + IMFDXGIDeviceManager IMFDXGIDeviceManager_iface; + LONG ref; + UINT token; +}; + +static struct mfdxgi_dev_mgr *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface) +{ + return CONTAINING_RECORD(iface, struct mfdxgi_dev_mgr, IMFDXGIDeviceManager_iface); +} + +static HRESULT WINAPI mfdxgi_dev_mgr_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj) +{ + TRACE("(%p, %s, %p).\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) || + IsEqualGUID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFDXGIDeviceManager_AddRef(iface); + return S_OK; + } + + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI mfdxgi_dev_mgr_AddRef(IMFDXGIDeviceManager *iface) +{ + struct mfdxgi_dev_mgr *manager = impl_from_IMFDXGIDeviceManager(iface); + ULONG refcount = InterlockedIncrement(&manager->ref); + + TRACE("(%p) ref=%u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI mfdxgi_dev_mgr_Release(IMFDXGIDeviceManager *iface) +{ + struct mfdxgi_dev_mgr *manager = impl_from_IMFDXGIDeviceManager(iface); + ULONG refcount = InterlockedDecrement(&manager->ref); + + TRACE("(%p) ref=%u.\n", iface, refcount); + + if (!refcount) + { + heap_free(manager); + } + + return refcount; +} + +static HRESULT WINAPI mfdxgi_dev_mgr_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE device) +{ + struct mfdxgi_dev_mgr *This = impl_from_IMFDXGIDeviceManager(iface); + + FIXME("(%p)->(%p): stub.\n", This, device); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfdxgi_dev_mgr_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE device, + REFIID riid, void **service) +{ + struct mfdxgi_dev_mgr *This = impl_from_IMFDXGIDeviceManager(iface); + + FIXME("(%p)->(%p, %s, %p): stub.\n", This, device, debugstr_guid(riid), service); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfdxgi_dev_mgr_LockDevice(IMFDXGIDeviceManager *iface, HANDLE device, + REFIID riid, void **ppv, BOOL block) +{ + struct mfdxgi_dev_mgr *This = impl_from_IMFDXGIDeviceManager(iface); + + FIXME("(%p)->(%p, %s, %p, %d): stub.\n", This, device, wine_dbgstr_guid(riid), ppv, block); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfdxgi_dev_mgr_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *device) +{ + struct mfdxgi_dev_mgr *This = impl_from_IMFDXGIDeviceManager(iface); + + FIXME("(%p)->(%p): stub.\n", This, device); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfdxgi_dev_mgr_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token) +{ + struct mfdxgi_dev_mgr *This = impl_from_IMFDXGIDeviceManager(iface); + + FIXME("(%p)->(%p, %u): stub.\n", This, device, token); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfdxgi_dev_mgr_TestDevice(IMFDXGIDeviceManager *iface, HANDLE device) +{ + struct mfdxgi_dev_mgr *This = impl_from_IMFDXGIDeviceManager(iface); + + FIXME("(%p)->(%p): stub.\n", This, device); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfdxgi_dev_mgr_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE device, BOOL state) +{ + struct mfdxgi_dev_mgr *This = impl_from_IMFDXGIDeviceManager(iface); + + FIXME("(%p)->(%p, %d): stub.\n", This, device, state); + + return E_NOTIMPL; +} + +static const IMFDXGIDeviceManagerVtbl mfdxgi_dev_mgr_vtbl = +{ + mfdxgi_dev_mgr_QueryInterface, + mfdxgi_dev_mgr_AddRef, + mfdxgi_dev_mgr_Release, + mfdxgi_dev_mgr_CloseDeviceHandle, + mfdxgi_dev_mgr_GetVideoService, + mfdxgi_dev_mgr_LockDevice, + mfdxgi_dev_mgr_OpenDeviceHandle, + mfdxgi_dev_mgr_ResetDevice, + mfdxgi_dev_mgr_TestDevice, + mfdxgi_dev_mgr_UnlockDevice, +}; + +HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager) +{ + struct mfdxgi_dev_mgr *dev_mgr; + + TRACE("(%p, %p).\n", token, manager); + + if (!token || !manager) + return E_POINTER; + + dev_mgr = heap_alloc(sizeof(*dev_mgr)); + if (!dev_mgr) + return E_OUTOFMEMORY; + + dev_mgr->IMFDXGIDeviceManager_iface.lpVtbl = &mfdxgi_dev_mgr_vtbl; + dev_mgr->ref = 1; + dev_mgr->token = MFGetSystemTime(); + + TRACE("Created device manager: %p, token: %u.\n", dev_mgr, dev_mgr->token); + + *token = dev_mgr->token; + *manager = &dev_mgr->IMFDXGIDeviceManager_iface; + + return S_OK; +} diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 2f16bbd197..cc440c5ee0 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -42,6 +42,7 @@ @ stdcall MFCreateAttributes(ptr long) @ stub MFCreateAudioMediaType @ stdcall MFCreateCollection(ptr) +@ stdcall MFCreateDXGIDeviceManager(ptr ptr) @ stdcall MFCreateEventQueue(ptr) @ stdcall MFCreateFile(long long long wstr ptr) @ stub MFCreateLegacyMediaBufferOnMFMediaBuffer diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index b4ba6b6c57..312f8b3bb2 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -58,6 +58,7 @@ static void _expect_ref(IUnknown *obj, ULONG ref, int line)
static HRESULT (WINAPI *pMFCopyImage)(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines); +static HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager); static HRESULT (WINAPI *pMFCreateSourceResolver)(IMFSourceResolver **resolver); static HRESULT (WINAPI *pMFCreateMFByteStreamOnStream)(IStream *stream, IMFByteStream **bytestream); static void* (WINAPI *pMFHeapAlloc)(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type); @@ -510,6 +511,7 @@ static void init_functions(void) X(MFAddPeriodicCallback); X(MFAllocateSerialWorkQueue); X(MFCopyImage); + X(MFCreateDXGIDeviceManager); X(MFCreateSourceResolver); X(MFCreateMFByteStreamOnStream); X(MFHeapAlloc); @@ -3704,6 +3706,78 @@ if (0) ok(!refcount, "Unexpected refcount %u.\n", refcount); }
+struct dev_mgr_ret +{ + IMFDXGIDeviceManager *dev_mgr; + UINT token; +}; + +static DWORD WINAPI create_dxgi_dev_mgr(LPVOID lParam) +{ + struct dev_mgr_ret *ret = lParam; + HRESULT hr; + + hr = pMFCreateDXGIDeviceManager(&ret->token, &ret->dev_mgr); + ok(hr == S_OK, "MFCreateDXGIDeviceManager failed: %#x.\n", hr); + ok(!!ret->token, "got wrong token: %u.\n", ret->token); + EXPECT_REF(ret->dev_mgr, 1); + + return 0; +} + +static void test_create_dxgi_device_manager(void) +{ + IMFDXGIDeviceManager *manager, *manager2; + struct dev_mgr_ret ret1, ret2; + HANDLE thread1, thread2; + UINT token, token2; + HRESULT hr; + + if (!pMFCreateDXGIDeviceManager) + { + win_skip("MFCreateDXGIDeviceManager not found.\n"); + return; + } + + hr = pMFCreateDXGIDeviceManager(NULL, &manager); + ok(hr == E_POINTER, "MFCreateDXGIDeviceManager should failed: %#x.\n", hr); + + token = 0; + hr = pMFCreateDXGIDeviceManager(&token, NULL); + ok(hr == E_POINTER, "MFCreateDXGIDeviceManager should failed: %#x.\n", hr); + ok(!token, "got wrong token: %u.\n", token); + + hr = pMFCreateDXGIDeviceManager(&token, &manager); + ok(hr == S_OK, "MFCreateDXGIDeviceManager failed: %#x.\n", hr); + EXPECT_REF(manager, 1); + ok(!!token, "got wrong token: %u.\n", token); + + Sleep(50); + token2 = 0; + hr = pMFCreateDXGIDeviceManager(&token2, &manager2); + ok(hr == S_OK, "MFCreateDXGIDeviceManager failed: %#x.\n", hr); + EXPECT_REF(manager2, 1); + ok(token2 && token2 != token, "got wrong token: %u, %u.\n", token2, token); + ok(manager != manager2, "got wrong pointer: %p.\n", manager2); + EXPECT_REF(manager, 1); + + IMFDXGIDeviceManager_Release(manager); + IMFDXGIDeviceManager_Release(manager2); + + memset(&ret1, 0, sizeof(ret1)); + thread1 = CreateThread(NULL, 0, create_dxgi_dev_mgr, &ret1, 0, NULL); + ok(WaitForSingleObject(thread1, 1000) == WAIT_OBJECT_0, "wait failed.\n"); + Sleep(50); + memset(&ret2, 0, sizeof(ret2)); + thread2 = CreateThread(NULL, 0, create_dxgi_dev_mgr, &ret2, 0, NULL); + ok(WaitForSingleObject(thread2, 1000) == WAIT_OBJECT_0, "wait failed.\n"); + ok(ret1.dev_mgr != ret2.dev_mgr, "got wrong pointer: %p, %p.\n", ret1.dev_mgr, ret2.dev_mgr); + ok(ret1.token != ret2.token, "got wrong token: %u, %u.\n", ret1.token, ret2.token); + + IMFDXGIDeviceManager_Release(ret1.dev_mgr); + IMFDXGIDeviceManager_Release(ret2.dev_mgr); +} + START_TEST(mfplat) { CoInitialize(NULL); @@ -3741,6 +3815,7 @@ START_TEST(mfplat) test_async_create_file(); test_local_handlers(); test_create_property_store(); + test_create_dxgi_device_manager();
CoUninitialize(); } diff --git a/include/mfapi.h b/include/mfapi.h index 957fb0df9f..f84c051792 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -384,6 +384,7 @@ HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IM HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size); HRESULT WINAPI MFCreateAsyncResult(IUnknown *object, IMFAsyncCallback *callback, IUnknown *state, IMFAsyncResult **result); HRESULT WINAPI MFCreateCollection(IMFCollection **collection); +HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager); HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue); HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags, LPCWSTR url, IMFByteStream **bytestream); diff --git a/include/mfobjects.idl b/include/mfobjects.idl index 0cc8f422da..203acc770f 100644 --- a/include/mfobjects.idl +++ b/include/mfobjects.idl @@ -727,3 +727,20 @@ interface IMFMediaEventQueue : IUnknown [in] HRESULT status, [in, unique] IUnknown *unk); HRESULT Shutdown(); } + +[ + object, + uuid(eb533d5d-2db6-40f8-97a9-494692014f07), + local, + pointer_default(unique) +] +interface IMFDXGIDeviceManager : IUnknown +{ + HRESULT CloseDeviceHandle([in] HANDLE device); + HRESULT GetVideoService([in] HANDLE device, [in] REFIID riid, [out] void **service); + HRESULT LockDevice([in] HANDLE device, [in] REFIID riid, [out] void **ppv, [in] BOOL block); + HRESULT OpenDeviceHandle([out] HANDLE *device); + HRESULT ResetDevice([in] IUnknown *device, [in] UINT token); + HRESULT TestDevice([in] HANDLE device); + HRESULT UnlockDevice([in] HANDLE device, [in] BOOL state); +}
On 8/28/19 4:37 PM, Jactry Zeng wrote:
+struct mfdxgi_dev_mgr +{
- IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
- LONG ref;
- UINT token;
+};
To be consistent with the rest of mf* modules, please use 'dxgi_device_manager' and 'refcount' for names.
+static HRESULT WINAPI mfdxgi_dev_mgr_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE device) +{
- struct mfdxgi_dev_mgr *This = impl_from_IMFDXGIDeviceManager(iface);
- FIXME("(%p)->(%p): stub.\n", This, device);
- return E_NOTIMPL;
+}
'This' -> 'manager', iface pointer in traces instead of This.
- dev_mgr->token = MFGetSystemTime();
This truncates result which is not pretty. Maybe it's enough to have global counter for this?
- struct mfdxgi_dev_mgr *dev_mgr;
'dev_mgr' -> 'object'.
- Sleep(50);
- token2 = 0;
- hr = pMFCreateDXGIDeviceManager(&token2, &manager2);
- ok(hr == S_OK, "MFCreateDXGIDeviceManager failed: %#x.\n", hr);
- EXPECT_REF(manager2, 1);
- ok(token2 && token2 != token, "got wrong token: %u, %u.\n", token2, token);
- ok(manager != manager2, "got wrong pointer: %p.\n", manager2);
- EXPECT_REF(manager, 1);
- IMFDXGIDeviceManager_Release(manager);
- IMFDXGIDeviceManager_Release(manager2);
- memset(&ret1, 0, sizeof(ret1));
- thread1 = CreateThread(NULL, 0, create_dxgi_dev_mgr, &ret1, 0, NULL);
- ok(WaitForSingleObject(thread1, 1000) == WAIT_OBJECT_0, "wait failed.\n");
- Sleep(50);
- memset(&ret2, 0, sizeof(ret2));
- thread2 = CreateThread(NULL, 0, create_dxgi_dev_mgr, &ret2, 0, NULL);
- ok(WaitForSingleObject(thread2, 1000) == WAIT_OBJECT_0, "wait failed.\n");
- ok(ret1.dev_mgr != ret2.dev_mgr, "got wrong pointer: %p, %p.\n", ret1.dev_mgr, ret2.dev_mgr);
- ok(ret1.token != ret2.token, "got wrong token: %u, %u.\n", ret1.token, ret2.token);
- IMFDXGIDeviceManager_Release(ret1.dev_mgr);
- IMFDXGIDeviceManager_Release(ret2.dev_mgr);
Do we need this? It only shows that token is different for newly created manager instance which is also true for same thread case.
- test_create_dxgi_device_manager();
'test_dxgi_device_manager' would be better, because we're going to test more than just creating it.
Hi Nikolay,
On 28/8/2019 9:55 pm, Nikolay Sivov wrote:
+ dev_mgr->token = MFGetSystemTime();
This truncates result which is not pretty. Maybe it's enough to have global counter for this?
How about 'object->token = MFGetSystemTime() >> 16;'? Then it will be a lower probabilityto generate duplicate token.
Thanks for the review.