Add methods for thread-local contexts to the router
This commit is contained in:
+29
-9
@@ -9,16 +9,36 @@
|
||||
|
||||
ATOMIC(DriverIface*) CurrentCtxDriver = ATOMIC_INIT_STATIC(NULL);
|
||||
|
||||
#define DECL_THUNK1(R,n,T1) AL_API R AL_APIENTRY n(T1 a) \
|
||||
{ return ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire)->n(a); }
|
||||
#define DECL_THUNK1(R,n,T1) AL_API R AL_APIENTRY n(T1 a) \
|
||||
{ \
|
||||
DriverIface *iface = altss_get(ThreadCtxDriver); \
|
||||
if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);\
|
||||
return iface->n(a); \
|
||||
}
|
||||
#define DECL_THUNK2(R,n,T1,T2) AL_API R AL_APIENTRY n(T1 a, T2 b) \
|
||||
{ return ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire)->n(a, b); }
|
||||
{ \
|
||||
DriverIface *iface = altss_get(ThreadCtxDriver); \
|
||||
if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);\
|
||||
return iface->n(a, b); \
|
||||
}
|
||||
#define DECL_THUNK3(R,n,T1,T2,T3) AL_API R AL_APIENTRY n(T1 a, T2 b, T3 c) \
|
||||
{ return ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire)->n(a, b, c); }
|
||||
{ \
|
||||
DriverIface *iface = altss_get(ThreadCtxDriver); \
|
||||
if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);\
|
||||
return iface->n(a, b, c); \
|
||||
}
|
||||
#define DECL_THUNK4(R,n,T1,T2,T3,T4) AL_API R AL_APIENTRY n(T1 a, T2 b, T3 c, T4 d) \
|
||||
{ return ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire)->n(a, b, c, d); }
|
||||
{ \
|
||||
DriverIface *iface = altss_get(ThreadCtxDriver); \
|
||||
if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);\
|
||||
return iface->n(a, b, c, d); \
|
||||
}
|
||||
#define DECL_THUNK5(R,n,T1,T2,T3,T4,T5) AL_API R AL_APIENTRY n(T1 a, T2 b, T3 c, T4 d, T5 e) \
|
||||
{ return ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire)->n(a, b, c, d, e); }
|
||||
{ \
|
||||
DriverIface *iface = altss_get(ThreadCtxDriver); \
|
||||
if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);\
|
||||
return iface->n(a, b, c, d, e); \
|
||||
}
|
||||
|
||||
|
||||
/* Ugly hack for some apps calling alGetError without a current context, and
|
||||
@@ -26,9 +46,9 @@ ATOMIC(DriverIface*) CurrentCtxDriver = ATOMIC_INIT_STATIC(NULL);
|
||||
*/
|
||||
AL_API ALenum AL_APIENTRY alGetError(void)
|
||||
{
|
||||
DriverIface *iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);
|
||||
if(iface) return iface->alGetError();
|
||||
return AL_NO_ERROR;
|
||||
DriverIface *iface = altss_get(ThreadCtxDriver);
|
||||
if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);
|
||||
return iface ? iface->alGetError() : AL_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+51
-3
@@ -473,16 +473,22 @@ ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
|
||||
*/
|
||||
if(idx < 0)
|
||||
{
|
||||
DriverIface *oldiface = ATOMIC_EXCHANGE_PTR_SEQ(&CurrentCtxDriver, NULL);
|
||||
DriverIface *oldiface = altss_get(ThreadCtxDriver);
|
||||
if(oldiface) oldiface->alcSetThreadContext(NULL);
|
||||
oldiface = ATOMIC_EXCHANGE_PTR_SEQ(&CurrentCtxDriver, NULL);
|
||||
if(oldiface) oldiface->alcMakeContextCurrent(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
DriverIface *oldiface = ATOMIC_EXCHANGE_PTR_SEQ(&CurrentCtxDriver, &DriverList[idx]);
|
||||
DriverIface *oldiface = altss_get(ThreadCtxDriver);
|
||||
if(oldiface && oldiface != &DriverList[idx])
|
||||
oldiface->alcSetThreadContext(NULL);
|
||||
oldiface = ATOMIC_EXCHANGE_PTR_SEQ(&CurrentCtxDriver, &DriverList[idx]);
|
||||
if(oldiface && oldiface != &DriverList[idx])
|
||||
oldiface->alcMakeContextCurrent(NULL);
|
||||
}
|
||||
almtx_unlock(&ContextSwitchLock);
|
||||
altss_set(ThreadCtxDriver, NULL);
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
@@ -525,7 +531,8 @@ ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
|
||||
|
||||
ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
|
||||
{
|
||||
DriverIface *iface = ATOMIC_LOAD_SEQ(&CurrentCtxDriver);
|
||||
DriverIface *iface = altss_get(ThreadCtxDriver);
|
||||
if(!iface) iface = ATOMIC_LOAD_SEQ(&CurrentCtxDriver);
|
||||
return iface ? iface->alcGetCurrentContext() : NULL;
|
||||
}
|
||||
|
||||
@@ -900,3 +907,44 @@ ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer,
|
||||
}
|
||||
ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
|
||||
}
|
||||
|
||||
|
||||
ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
|
||||
{
|
||||
ALCenum err = ALC_INVALID_CONTEXT;
|
||||
ALint idx;
|
||||
|
||||
if(!context)
|
||||
{
|
||||
DriverIface *oldiface = altss_get(ThreadCtxDriver);
|
||||
if(oldiface && !oldiface->alcSetThreadContext(NULL))
|
||||
return ALC_FALSE;
|
||||
altss_set(ThreadCtxDriver, NULL);
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
idx = LookupPtrIntMapKey(&ContextIfaceMap, context);
|
||||
if(idx >= 0)
|
||||
{
|
||||
if(DriverList[idx].alcSetThreadContext(context))
|
||||
{
|
||||
DriverIface *oldiface = altss_get(ThreadCtxDriver);
|
||||
if(oldiface != &DriverList[idx])
|
||||
{
|
||||
altss_set(ThreadCtxDriver, &DriverList[idx]);
|
||||
if(oldiface) oldiface->alcSetThreadContext(NULL);
|
||||
}
|
||||
return ALC_TRUE;
|
||||
}
|
||||
err = DriverList[idx].alcGetError(NULL);
|
||||
}
|
||||
ATOMIC_STORE_SEQ(&LastError, err);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
|
||||
{
|
||||
DriverIface *iface = altss_get(ThreadCtxDriver);
|
||||
if(iface) return iface->alcGetThreadContext();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ DriverIface *DriverList = NULL;
|
||||
int DriverListSize = 0;
|
||||
static int DriverListSizeMax = 0;
|
||||
|
||||
altss_t ThreadCtxDriver;
|
||||
|
||||
enum LogLevel LogLevel = LogLevel_Error;
|
||||
FILE *LogFile;
|
||||
|
||||
@@ -54,6 +56,7 @@ BOOL APIENTRY DllMain(HINSTANCE UNUSED(module), DWORD reason, void* UNUSED(reser
|
||||
}
|
||||
LoadDriverList();
|
||||
|
||||
altss_create(&ThreadCtxDriver, NULL);
|
||||
InitALC();
|
||||
break;
|
||||
|
||||
@@ -63,6 +66,7 @@ BOOL APIENTRY DllMain(HINSTANCE UNUSED(module), DWORD reason, void* UNUSED(reser
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
ReleaseALC();
|
||||
altss_delete(ThreadCtxDriver);
|
||||
|
||||
for(i = 0;i < DriverListSize;i++)
|
||||
{
|
||||
@@ -124,6 +128,7 @@ static void AddModule(HMODULE module, const WCHAR *name)
|
||||
}
|
||||
|
||||
memset(&newdrv, 0, sizeof(newdrv));
|
||||
/* Load required functions. */
|
||||
#define LOAD_PROC(x) do { \
|
||||
newdrv.x = CAST_FUNC(newdrv.x) GetProcAddress(module, #x); \
|
||||
if(!newdrv.x) \
|
||||
@@ -237,10 +242,30 @@ static void AddModule(HMODULE module, const WCHAR *name)
|
||||
newdrv.ALCVer = MAKE_ALC_VER(alc_ver[0], alc_ver[1]);
|
||||
else
|
||||
newdrv.ALCVer = MAKE_ALC_VER(1, 0);
|
||||
|
||||
#undef LOAD_PROC
|
||||
#define LOAD_PROC(x) do { \
|
||||
newdrv.x = CAST_FUNC(newdrv.x) newdrv.alcGetProcAddress(NULL, #x); \
|
||||
if(!newdrv.x) \
|
||||
{ \
|
||||
ERR("Failed to find entry point for %s in %ls\n", #x, name); \
|
||||
err = 1; \
|
||||
} \
|
||||
} while(0)
|
||||
if(newdrv.alcIsExtensionPresent(NULL, "ALC_EXT_thread_local_context"))
|
||||
{
|
||||
LOAD_PROC(alcSetThreadContext);
|
||||
LOAD_PROC(alcGetThreadContext);
|
||||
}
|
||||
}
|
||||
|
||||
if(!err)
|
||||
{
|
||||
TRACE("Loaded module %p, %ls, ALC %d.%d\n", module, name,
|
||||
newdrv.ALCVer>>8, newdrv.ALCVer&255);
|
||||
DriverList[DriverListSize++] = newdrv;
|
||||
}
|
||||
#undef LOAD_PROC
|
||||
}
|
||||
|
||||
static void SearchDrivers(WCHAR *path)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "AL/alc.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alext.h"
|
||||
#include "atomic.h"
|
||||
#include "rwlock.h"
|
||||
#include "threads.h"
|
||||
@@ -54,6 +55,9 @@ typedef struct DriverIface {
|
||||
LPALCCAPTURESTOP alcCaptureStop;
|
||||
LPALCCAPTURESAMPLES alcCaptureSamples;
|
||||
|
||||
PFNALCSETTHREADCONTEXTPROC alcSetThreadContext;
|
||||
PFNALCGETTHREADCONTEXTPROC alcGetThreadContext;
|
||||
|
||||
LPALENABLE alEnable;
|
||||
LPALDISABLE alDisable;
|
||||
LPALISENABLED alIsEnabled;
|
||||
@@ -132,6 +136,7 @@ typedef struct DriverIface {
|
||||
extern DriverIface *DriverList;
|
||||
extern int DriverListSize;
|
||||
|
||||
extern altss_t ThreadCtxDriver;
|
||||
extern ATOMIC(DriverIface*) CurrentCtxDriver;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user