mfplat: Initialize system queues on startup.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
f42b3a1f10
commit
7a120b0b2c
|
@ -36,6 +36,8 @@
|
|||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
#include "mfplat_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
|
||||
static LONG platform_lock;
|
||||
|
@ -465,11 +467,16 @@ HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
|
|||
#define MF_VERSION_XP MAKELONG( MF_API_VERSION, 1 )
|
||||
#define MF_VERSION_WIN7 MAKELONG( MF_API_VERSION, 2 )
|
||||
|
||||
FIXME("(%u, %u): stub\n", version, flags);
|
||||
TRACE("%#x, %#x.\n", version, flags);
|
||||
|
||||
if(version != MF_VERSION_XP && version != MF_VERSION_WIN7)
|
||||
if (version != MF_VERSION_XP && version != MF_VERSION_WIN7)
|
||||
return MF_E_BAD_STARTUP_VERSION;
|
||||
|
||||
if (InterlockedIncrement(&platform_lock) == 1)
|
||||
{
|
||||
init_system_queues();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -478,7 +485,15 @@ HRESULT WINAPI MFStartup(ULONG version, DWORD flags)
|
|||
*/
|
||||
HRESULT WINAPI MFShutdown(void)
|
||||
{
|
||||
FIXME("(): stub\n");
|
||||
TRACE("\n");
|
||||
|
||||
if (platform_lock <= 0)
|
||||
return S_OK;
|
||||
|
||||
if (InterlockedExchangeAdd(&platform_lock, -1) == 1)
|
||||
{
|
||||
shutdown_system_queues();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -498,7 +513,10 @@ HRESULT WINAPI MFLockPlatform(void)
|
|||
*/
|
||||
HRESULT WINAPI MFUnlockPlatform(void)
|
||||
{
|
||||
InterlockedDecrement(&platform_lock);
|
||||
if (InterlockedDecrement(&platform_lock) == 0)
|
||||
{
|
||||
shutdown_system_queues();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright 2019 Nikolay Sivov for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
extern void init_system_queues(void) DECLSPEC_HIDDEN;
|
||||
extern void shutdown_system_queues(void) DECLSPEC_HIDDEN;
|
|
@ -26,33 +26,40 @@
|
|||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
|
||||
#include "mfplat_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
|
||||
#define FIRST_USER_QUEUE_HANDLE 5
|
||||
#define MAX_USER_QUEUE_HANDLES 124
|
||||
|
||||
struct queue
|
||||
{
|
||||
TP_POOL *pool;
|
||||
};
|
||||
|
||||
struct queue_handle
|
||||
{
|
||||
void *obj;
|
||||
LONG refcount;
|
||||
WORD generation;
|
||||
};
|
||||
|
||||
static struct queue user_queues[MAX_USER_QUEUE_HANDLES];
|
||||
static struct queue *next_free_user_queue;
|
||||
static struct queue *next_unused_user_queue = user_queues;
|
||||
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 CRITICAL_SECTION user_queues_section;
|
||||
static CRITICAL_SECTION_DEBUG user_queues_critsect_debug =
|
||||
static CRITICAL_SECTION queues_section;
|
||||
static CRITICAL_SECTION_DEBUG queues_critsect_debug =
|
||||
{
|
||||
0, 0, &user_queues_section,
|
||||
{ &user_queues_critsect_debug.ProcessLocksList, &user_queues_critsect_debug.ProcessLocksList },
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": user_queues_section") }
|
||||
0, 0, &queues_section,
|
||||
{ &queues_critsect_debug.ProcessLocksList, &queues_critsect_debug.ProcessLocksList },
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": queues_section") }
|
||||
};
|
||||
static CRITICAL_SECTION user_queues_section = { &user_queues_critsect_debug, -1, 0, 0, 0, 0 };
|
||||
static CRITICAL_SECTION queues_section = { &queues_critsect_debug, -1, 0, 0, 0, 0 };
|
||||
|
||||
static struct queue *get_queue_obj(DWORD handle)
|
||||
static struct queue_handle *get_queue_obj(DWORD handle)
|
||||
{
|
||||
unsigned int idx = HIWORD(handle) - FIRST_USER_QUEUE_HANDLE;
|
||||
|
||||
|
@ -65,12 +72,79 @@ static struct queue *get_queue_obj(DWORD handle)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static HRESULT alloc_user_queue(DWORD *queue)
|
||||
enum system_queue_index
|
||||
{
|
||||
struct queue *entry;
|
||||
SYS_QUEUE_STANDARD = 0,
|
||||
SYS_QUEUE_RT,
|
||||
SYS_QUEUE_IO,
|
||||
SYS_QUEUE_TIMER,
|
||||
SYS_QUEUE_MULTITHREADED,
|
||||
SYS_QUEUE_DO_NOT_USE,
|
||||
SYS_QUEUE_LONG_FUNCTION,
|
||||
SYS_QUEUE_COUNT,
|
||||
};
|
||||
|
||||
static struct queue system_queues[SYS_QUEUE_COUNT];
|
||||
|
||||
static void init_work_queue(MFASYNC_WORKQUEUE_TYPE queue_type, struct queue *queue)
|
||||
{
|
||||
queue->pool = CreateThreadpool(NULL);
|
||||
}
|
||||
|
||||
void init_system_queues(void)
|
||||
{
|
||||
/* Always initialize standard queue, keep the rest lazy. */
|
||||
|
||||
EnterCriticalSection(&queues_section);
|
||||
|
||||
if (system_queues[SYS_QUEUE_STANDARD].pool)
|
||||
{
|
||||
LeaveCriticalSection(&queues_section);
|
||||
return;
|
||||
}
|
||||
|
||||
init_work_queue(MF_STANDARD_WORKQUEUE, &system_queues[SYS_QUEUE_STANDARD]);
|
||||
|
||||
LeaveCriticalSection(&queues_section);
|
||||
}
|
||||
|
||||
static void shutdown_queue(struct queue *queue)
|
||||
{
|
||||
if (!queue->pool)
|
||||
return;
|
||||
|
||||
CloseThreadpool(queue->pool);
|
||||
queue->pool = NULL;
|
||||
}
|
||||
|
||||
void shutdown_system_queues(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
EnterCriticalSection(&queues_section);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(system_queues); ++i)
|
||||
{
|
||||
shutdown_queue(&system_queues[i]);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&queues_section);
|
||||
}
|
||||
|
||||
static HRESULT alloc_user_queue(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue_id)
|
||||
{
|
||||
struct queue_handle *entry;
|
||||
struct queue *queue;
|
||||
unsigned int idx;
|
||||
|
||||
EnterCriticalSection(&user_queues_section);
|
||||
*queue_id = MFASYNC_CALLBACK_QUEUE_UNDEFINED;
|
||||
|
||||
queue = heap_alloc_zero(sizeof(*queue));
|
||||
if (!queue)
|
||||
return E_OUTOFMEMORY;
|
||||
init_work_queue(queue_type, queue);
|
||||
|
||||
EnterCriticalSection(&queues_section);
|
||||
|
||||
entry = next_free_user_queue;
|
||||
if (entry)
|
||||
|
@ -79,17 +153,18 @@ static HRESULT alloc_user_queue(DWORD *queue)
|
|||
entry = next_unused_user_queue++;
|
||||
else
|
||||
{
|
||||
LeaveCriticalSection(&user_queues_section);
|
||||
LeaveCriticalSection(&queues_section);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
entry->refcount = 1;
|
||||
entry->obj = NULL;
|
||||
entry->obj = queue;
|
||||
if (++queue_generation == 0xffff) queue_generation = 1;
|
||||
entry->generation = queue_generation;
|
||||
idx = entry - user_queues + FIRST_USER_QUEUE_HANDLE;
|
||||
*queue = (idx << 16) | entry->generation;
|
||||
LeaveCriticalSection(&user_queues_section);
|
||||
*queue_id = (idx << 16) | entry->generation;
|
||||
|
||||
LeaveCriticalSection(&queues_section);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -97,31 +172,31 @@ static HRESULT alloc_user_queue(DWORD *queue)
|
|||
static HRESULT lock_user_queue(DWORD queue)
|
||||
{
|
||||
HRESULT hr = MF_E_INVALID_WORKQUEUE;
|
||||
struct queue *entry;
|
||||
struct queue_handle *entry;
|
||||
|
||||
if (!(queue & MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK))
|
||||
return S_OK;
|
||||
|
||||
EnterCriticalSection(&user_queues_section);
|
||||
EnterCriticalSection(&queues_section);
|
||||
entry = get_queue_obj(queue);
|
||||
if (entry && entry->refcount)
|
||||
{
|
||||
entry->refcount++;
|
||||
hr = S_OK;
|
||||
}
|
||||
LeaveCriticalSection(&user_queues_section);
|
||||
LeaveCriticalSection(&queues_section);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT unlock_user_queue(DWORD queue)
|
||||
{
|
||||
HRESULT hr = MF_E_INVALID_WORKQUEUE;
|
||||
struct queue *entry;
|
||||
struct queue_handle *entry;
|
||||
|
||||
if (!(queue & MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK))
|
||||
return S_OK;
|
||||
|
||||
EnterCriticalSection(&user_queues_section);
|
||||
EnterCriticalSection(&queues_section);
|
||||
entry = get_queue_obj(queue);
|
||||
if (entry && entry->refcount)
|
||||
{
|
||||
|
@ -132,7 +207,7 @@ static HRESULT unlock_user_queue(DWORD queue)
|
|||
}
|
||||
hr = S_OK;
|
||||
}
|
||||
LeaveCriticalSection(&user_queues_section);
|
||||
LeaveCriticalSection(&queues_section);
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -309,7 +384,7 @@ HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue)
|
|||
{
|
||||
TRACE("%p.\n", queue);
|
||||
|
||||
return alloc_user_queue(queue);
|
||||
return alloc_user_queue(MF_STANDARD_WORKQUEUE, queue);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -88,7 +88,15 @@ DEFINE_GUID(MFMediaType_Video, 0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0
|
|||
|
||||
typedef unsigned __int64 MFWORKITEM_KEY;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MF_STANDARD_WORKQUEUE,
|
||||
MF_WINDOW_WORKQUEUE,
|
||||
MF_MULTITHREADED_WORKQUEUE,
|
||||
} MFASYNC_WORKQUEUE_TYPE;
|
||||
|
||||
HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue);
|
||||
HRESULT WINAPI MFAllocateWorkQueueEx(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue);
|
||||
HRESULT WINAPI MFCancelWorkItem(MFWORKITEM_KEY key);
|
||||
HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines);
|
||||
HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size);
|
||||
|
|
|
@ -431,6 +431,7 @@ cpp_quote("#define MFASYNC_CALLBACK_QUEUE_STANDARD 0x00000001")
|
|||
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_RT 0x00000002")
|
||||
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_IO 0x00000003")
|
||||
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_TIMER 0x00000004")
|
||||
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_MULTITHREADED 0x00000005")
|
||||
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION 0x00000007")
|
||||
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK 0xffff0000")
|
||||
cpp_quote("#define MFASYNC_CALLBACK_QUEUE_ALL 0xffffffff")
|
||||
|
|
Loading…
Reference in New Issue