aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-07-07 18:33:54 -0700
committerChris Robinson <[email protected]>2017-07-07 18:33:54 -0700
commit6be752a9b1a38379b8631c5dcb6c47e099af4f02 (patch)
treeb22d581ed2fd98fbd12526d2af005c6517f110c4
parentfaefa1d55479a5d5a05ddb18f6b9051634adec3d (diff)
Add methods for thread-local contexts to the router
-rw-r--r--router/al.c38
-rw-r--r--router/alc.c54
-rw-r--r--router/router.c25
-rw-r--r--router/router.h5
4 files changed, 110 insertions, 12 deletions
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;