Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/mfplat.spec | 1 + dlls/mfplat/tests/mfplat.c | 46 ++++++++++++++++++++++++++++++++++++++ dlls/rtworkq/queue.c | 34 ++++++++++++++++++++++++++-- include/mfapi.h | 1 + 4 files changed, 80 insertions(+), 2 deletions(-)
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 7d014e334c8..cbda9404aa9 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -132,6 +132,7 @@ @ stub MFJoinIoPort @ stdcall MFJoinWorkQueue(long long ptr) rtworkq.RtwqJoinWorkQueue @ stdcall MFLockPlatform() rtworkq.RtwqLockPlatform +@ stdcall MFLockSharedWorkQueue(wstr long ptr ptr) rtworkq.RtwqLockSharedWorkQueue @ stdcall MFLockWorkQueue(long) rtworkq.RtwqLockWorkQueue @ stdcall MFMapDX9FormatToDXGIFormat(long) @ stdcall MFMapDXGIFormatToDX9Format(long) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 18361d4d721..1b24dce2fe0 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -240,6 +240,7 @@ static HRESULT (WINAPI *pMFCreateVideoSampleAllocatorEx)(REFIID riid, void **all static HRESULT (WINAPI *pMFCreateDXGISurfaceBuffer)(REFIID riid, IUnknown *surface, UINT subresource, BOOL bottomup, 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 HWND create_window(void) { @@ -907,6 +908,7 @@ static void init_functions(void) X(MFCreateVideoSampleAllocatorEx); X(MFGetPlaneSize); X(MFGetStrideForBitmapInfoHeader); + X(MFLockSharedWorkQueue); X(MFMapDX9FormatToDXGIFormat); X(MFMapDXGIFormatToDX9Format); X(MFPutWaitingWorkItem); @@ -7016,6 +7018,49 @@ done: DestroyWindow(window); }
+static void test_MFLockSharedWorkQueue(void) +{ + DWORD taskid, queue, queue2; + HRESULT hr; + + if (!pMFLockSharedWorkQueue) + { + win_skip("MFLockSharedWorkQueue() is not available.\n"); + return; + } + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); + + hr = pMFLockSharedWorkQueue(NULL, 0, &taskid, &queue); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = pMFLockSharedWorkQueue(NULL, 0, NULL, &queue); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + taskid = 0; + hr = pMFLockSharedWorkQueue(L"", 0, &taskid, &queue); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + queue = 0; + hr = pMFLockSharedWorkQueue(L"", 0, NULL, &queue); + ok(queue & MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK, "Unexpected queue id.\n"); + + queue2 = 0; + hr = pMFLockSharedWorkQueue(L"", 0, NULL, &queue2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(queue == queue2, "Unexpected queue %#x.\n", queue2); + + hr = MFUnlockWorkQueue(queue2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = MFUnlockWorkQueue(queue); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = MFShutdown(); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); +} + START_TEST(mfplat) { char **argv; @@ -7044,6 +7089,7 @@ START_TEST(mfplat) test_source_resolver(); test_MFCreateAsyncResult(); test_allocate_queue(); + test_MFLockSharedWorkQueue(); test_MFCopyImage(); test_MFCreateCollection(); test_MFHeapAlloc(); diff --git a/dlls/rtworkq/queue.c b/dlls/rtworkq/queue.c index f4e9f10d3f0..6817b06f284 100644 --- a/dlls/rtworkq/queue.c +++ b/dlls/rtworkq/queue.c @@ -58,6 +58,7 @@ static struct queue_handle user_queues[MAX_USER_QUEUE_HANDLES]; static struct queue_handle *next_free_user_queue; static struct queue_handle *next_unused_user_queue = user_queues; static WORD queue_generation; +static DWORD shared_mt_queue;
static CRITICAL_SECTION queues_section; static CRITICAL_SECTION_DEBUG queues_critsect_debug = @@ -217,6 +218,7 @@ static HRESULT unlock_user_queue(DWORD queue) { if (--entry->refcount == 0) { + if (shared_mt_queue == queue) shared_mt_queue = 0; shutdown_queue((struct queue *)entry->obj); heap_free(entry->obj); entry->obj = next_free_user_queue; @@ -1438,9 +1440,37 @@ HRESULT WINAPI RtwqSetLongRunning(DWORD queue_id, BOOL enable)
HRESULT WINAPI RtwqLockSharedWorkQueue(const WCHAR *usageclass, LONG priority, DWORD *taskid, DWORD *queue) { - FIXME("%s, %d, %p, %p.\n", debugstr_w(usageclass), priority, taskid, queue); + struct queue_desc desc; + HRESULT hr; + + TRACE("%s, %d, %p, %p.\n", debugstr_w(usageclass), priority, taskid, queue); + + if (!usageclass) + return E_POINTER; + + if (!*usageclass && taskid) + return E_INVALIDARG; + + if (*usageclass) + FIXME("Class name is ignored.\n"); + + EnterCriticalSection(&queues_section);
- return RtwqAllocateWorkQueue(RTWQ_STANDARD_WORKQUEUE, queue); + if (shared_mt_queue) + hr = lock_user_queue(shared_mt_queue); + else + { + desc.queue_type = RTWQ_MULTITHREADED_WORKQUEUE; + desc.ops = &pool_queue_ops; + desc.target_queue = 0; + hr = alloc_user_queue(&desc, &shared_mt_queue); + } + + *queue = shared_mt_queue; + + LeaveCriticalSection(&queues_section); + + return hr; }
HRESULT WINAPI RtwqSetDeadline(DWORD queue_id, LONGLONG deadline, HANDLE *request) diff --git a/include/mfapi.h b/include/mfapi.h index d6969984da7..c1cf766c005 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -553,6 +553,7 @@ HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *attributes, const UINT8 * HRESULT WINAPI MFInitMediaTypeFromWaveFormatEx(IMFMediaType *mediatype, const WAVEFORMATEX *format, UINT32 size); HRESULT WINAPI MFInvokeCallback(IMFAsyncResult *result); HRESULT WINAPI MFLockPlatform(void); +HRESULT WINAPI MFLockSharedWorkQueue(const WCHAR *name, LONG base_priority, DWORD *taskid, DWORD *queue); DXGI_FORMAT WINAPI MFMapDX9FormatToDXGIFormat(DWORD format); DWORD WINAPI MFMapDXGIFormatToDX9Format(DXGI_FORMAT dxgi_format); HRESULT WINAPI MFPutWaitingWorkItem(HANDLE event, LONG priority, IMFAsyncResult *result, MFWORKITEM_KEY *key);