Signed-off-by: Nikolay Sivov <nsivov(a)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);
--
2.30.2