From 6be752a9b1a38379b8631c5dcb6c47e099af4f02 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 7 Jul 2017 18:33:54 -0700 Subject: Add methods for thread-local contexts to the router --- router/al.c | 38 +++++++++++++++++++++++++++++--------- router/alc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--- router/router.c | 25 +++++++++++++++++++++++++ router/router.h | 5 +++++ 4 files changed, 110 insertions(+), 12 deletions(-) (limited to 'router') diff --git a/router/al.c b/router/al.c index 7af7168a..3349ad13 100644 --- a/router/al.c +++ b/router/al.c @@ -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; } diff --git a/router/alc.c b/router/alc.c index 9f94c869..7737d97b 100644 --- a/router/alc.c +++ b/router/alc.c @@ -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; +} diff --git a/router/router.c b/router/router.c index 54f82245..d1c5cfb3 100644 --- a/router/router.c +++ b/router/router.c @@ -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) diff --git a/router/router.h b/router/router.h index 0749ffad..ee885d85 100644 --- a/router/router.h +++ b/router/router.h @@ -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; -- cgit v1.2.3