aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c35
-rw-r--r--Alc/ALu.c58
-rw-r--r--OpenAL32/Include/alListener.h30
-rw-r--r--OpenAL32/Include/alMain.h7
-rw-r--r--OpenAL32/alAuxEffectSlot.c7
-rw-r--r--OpenAL32/alListener.c148
-rw-r--r--OpenAL32/alState.c27
7 files changed, 234 insertions, 78 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index b8dae07c..058dd242 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -2064,7 +2064,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
{
ALsizei pos;
- ATOMIC_STORE(&context->UpdateSources, AL_FALSE);
LockUIntMapRead(&context->EffectSlotMap);
for(pos = 0;pos < context->EffectSlotMap.size;pos++)
{
@@ -2272,11 +2271,16 @@ static ALCboolean VerifyDevice(ALCdevice **device)
static ALvoid InitContext(ALCcontext *Context)
{
ALlistener *listener = Context->Listener;
+
//Initialise listener
listener->Gain = 1.0f;
listener->MetersPerUnit = 1.0f;
- aluVectorSet(&listener->Position, 0.0f, 0.0f, 0.0f, 1.0f);
- aluVectorSet(&listener->Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
+ listener->Position[0] = 0.0f;
+ listener->Position[1] = 0.0f;
+ listener->Position[2] = 0.0f;
+ listener->Velocity[0] = 0.0f;
+ listener->Velocity[1] = 0.0f;
+ listener->Velocity[2] = 0.0f;
listener->Forward[0] = 0.0f;
listener->Forward[1] = 0.0f;
listener->Forward[2] = -1.0f;
@@ -2296,9 +2300,12 @@ static ALvoid InitContext(ALCcontext *Context)
listener->Params.DopplerFactor = 1.0f;
listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
+ ATOMIC_INIT(&listener->Update, NULL);
+ ATOMIC_INIT(&listener->FreeList, NULL);
+
//Validate Context
+ RWLockInit(&Context->PropLock);
ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
- ATOMIC_INIT(&Context->UpdateSources, AL_FALSE);
InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
@@ -2321,6 +2328,10 @@ static ALvoid InitContext(ALCcontext *Context)
*/
static void FreeContext(ALCcontext *context)
{
+ ALlistener *listener = context->Listener;
+ struct ALlistenerProps *lprops;
+ size_t count;
+
TRACE("%p\n", context);
if(context->SourceMap.size > 0)
@@ -2344,6 +2355,22 @@ static void FreeContext(ALCcontext *context)
VECTOR_DEINIT(context->ActiveAuxSlots);
+ if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
+ {
+ TRACE("Freed unapplied listener update %p\n", lprops);
+ al_free(lprops);
+ }
+ count = 0;
+ lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_consume);
+ while(lprops)
+ {
+ struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_consume);
+ al_free(lprops);
+ lprops = next;
+ ++count;
+ }
+ TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s");
+
ALCdevice_DecRef(context->Device);
context->Device = NULL;
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 709b7127..82553cc7 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -266,19 +266,25 @@ static ALboolean BsincPrepare(const ALuint increment, BsincState *state)
}
-static ALvoid CalcListenerParams(ALCcontext *Context)
+static ALboolean CalcListenerParams(ALCcontext *Context)
{
ALlistener *Listener = Context->Listener;
ALdouble N[3], V[3], U[3], P[3];
+ struct ALlistenerProps *first;
+ struct ALlistenerProps *props;
+ aluVector vel;
+
+ props = ATOMIC_EXCHANGE(struct ALlistenerProps*, &Listener->Update, NULL, almemory_order_acq_rel);
+ if(!props) return AL_FALSE;
/* AT then UP */
- N[0] = Listener->Forward[0];
- N[1] = Listener->Forward[1];
- N[2] = Listener->Forward[2];
+ N[0] = ATOMIC_LOAD(&props->Forward[0], almemory_order_relaxed);
+ N[1] = ATOMIC_LOAD(&props->Forward[1], almemory_order_relaxed);
+ N[2] = ATOMIC_LOAD(&props->Forward[2], almemory_order_relaxed);
aluNormalized(N);
- V[0] = Listener->Up[0];
- V[1] = Listener->Up[1];
- V[2] = Listener->Up[2];
+ V[0] = ATOMIC_LOAD(&props->Up[0], almemory_order_relaxed);
+ V[1] = ATOMIC_LOAD(&props->Up[1], almemory_order_relaxed);
+ V[2] = ATOMIC_LOAD(&props->Up[2], almemory_order_relaxed);
aluNormalized(V);
/* Build and normalize right-vector */
aluCrossproductd(N, V, U);
@@ -291,19 +297,37 @@ static ALvoid CalcListenerParams(ALCcontext *Context)
0.0, 0.0, 0.0, 1.0
);
- P[0] = Listener->Position.v[0];
- P[1] = Listener->Position.v[1];
- P[2] = Listener->Position.v[2];
+ P[0] = ATOMIC_LOAD(&props->Position[0], almemory_order_relaxed);
+ P[1] = ATOMIC_LOAD(&props->Position[1], almemory_order_relaxed);
+ P[2] = ATOMIC_LOAD(&props->Position[2], almemory_order_relaxed);
aluMatrixdDouble3(P, 1.0, &Listener->Params.Matrix);
aluMatrixdSetRow(&Listener->Params.Matrix, 3, -P[0], -P[1], -P[2], 1.0f);
- Listener->Params.Velocity = aluMatrixdVector(&Listener->Params.Matrix, &Listener->Velocity);
+ aluVectorSet(&vel, ATOMIC_LOAD(&props->Velocity[0], almemory_order_relaxed),
+ ATOMIC_LOAD(&props->Velocity[1], almemory_order_relaxed),
+ ATOMIC_LOAD(&props->Velocity[2], almemory_order_relaxed),
+ 0.0f);
+ Listener->Params.Velocity = aluMatrixdVector(&Listener->Params.Matrix, &vel);
+
+ Listener->Params.Gain = ATOMIC_LOAD(&props->Gain, almemory_order_relaxed);
+ Listener->Params.MetersPerUnit = ATOMIC_LOAD(&props->MetersPerUnit, almemory_order_relaxed);
- Listener->Params.Gain = Listener->Gain;
- Listener->Params.MetersPerUnit = Listener->MetersPerUnit;
+ Listener->Params.DopplerFactor = ATOMIC_LOAD(&props->DopplerFactor, almemory_order_relaxed);
+ Listener->Params.SpeedOfSound = ATOMIC_LOAD(&props->SpeedOfSound, almemory_order_relaxed) *
+ ATOMIC_LOAD(&props->DopplerVelocity, almemory_order_relaxed);
- Listener->Params.DopplerFactor = Context->DopplerFactor;
- Listener->Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
+ /* WARNING: A livelock is theoretically possible if another thread keeps
+ * changing the freelist head without giving this a chance to actually swap
+ * in the old container (practically impossible with this little code,
+ * but...).
+ */
+ first = ATOMIC_LOAD(&Listener->FreeList);
+ do {
+ ATOMIC_STORE(&props->next, first, almemory_order_relaxed);
+ } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALlistenerProps*,
+ &Listener->FreeList, &first, props) == 0);
+
+ return AL_TRUE;
}
ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
@@ -1223,10 +1247,8 @@ void UpdateContextSources(ALCcontext *ctx)
ALvoice *voice, *voice_end;
ALsource *source;
- if(ATOMIC_EXCHANGE(ALenum, &ctx->UpdateSources, AL_FALSE))
+ if(CalcListenerParams(ctx))
{
- CalcListenerParams(ctx);
-
voice = ctx->Voices;
voice_end = voice + ctx->VoiceCount;
for(;voice != voice_end;++voice)
diff --git a/OpenAL32/Include/alListener.h b/OpenAL32/Include/alListener.h
index f28561fa..75a3fb46 100644
--- a/OpenAL32/Include/alListener.h
+++ b/OpenAL32/Include/alListener.h
@@ -8,14 +8,38 @@
extern "C" {
#endif
+struct ALlistenerProps {
+ ATOMIC(ALfloat) Position[3];
+ ATOMIC(ALfloat) Velocity[3];
+ ATOMIC(ALfloat) Forward[3];
+ ATOMIC(ALfloat) Up[3];
+ ATOMIC(ALfloat) Gain;
+ ATOMIC(ALfloat) MetersPerUnit;
+
+ ATOMIC(ALfloat) DopplerFactor;
+ ATOMIC(ALfloat) DopplerVelocity;
+ ATOMIC(ALfloat) SpeedOfSound;
+
+ ATOMIC(struct ALlistenerProps*) next;
+};
+
typedef struct ALlistener {
- aluVector Position;
- aluVector Velocity;
+ volatile ALfloat Position[3];
+ volatile ALfloat Velocity[3];
volatile ALfloat Forward[3];
volatile ALfloat Up[3];
volatile ALfloat Gain;
volatile ALfloat MetersPerUnit;
+ /* Pointer to the most recent property values that are awaiting an update.
+ */
+ ATOMIC(struct ALlistenerProps*) Update;
+
+ /* A linked list of unused property containers, free to use for future
+ * updates.
+ */
+ ATOMIC(struct ALlistenerProps*) FreeList;
+
struct {
aluMatrixd Matrix;
aluVector Velocity;
@@ -28,6 +52,8 @@ typedef struct ALlistener {
} Params;
} ALlistener;
+void UpdateListenerProps(ALCcontext *context);
+
#ifdef __cplusplus
}
#endif
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index e818245b..44ce4fe0 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -679,8 +679,7 @@ struct ALCdevice_struct
#define RECORD_THREAD_NAME "alsoft-record"
-struct ALCcontext_struct
-{
+struct ALCcontext_struct {
RefCount ref;
struct ALlistener *Listener;
@@ -690,8 +689,6 @@ struct ALCcontext_struct
ATOMIC(ALenum) LastError;
- ATOMIC(ALenum) UpdateSources;
-
volatile enum DistanceModel DistanceModel;
volatile ALboolean SourceDistanceModel;
@@ -700,6 +697,8 @@ struct ALCcontext_struct
volatile ALfloat SpeedOfSound;
volatile ALenum DeferUpdates;
+ RWLock PropLock;
+
struct ALvoice *Voices;
ALsizei VoiceCount;
ALsizei MaxVoices;
diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c
index 9780cff3..7f570ef8 100644
--- a/OpenAL32/alAuxEffectSlot.c
+++ b/OpenAL32/alAuxEffectSlot.c
@@ -29,6 +29,7 @@
#include "alAuxEffectSlot.h"
#include "alThunk.h"
#include "alError.h"
+#include "alListener.h"
#include "alSource.h"
#include "almalloc.h"
@@ -187,7 +188,6 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
err = InitializeEffect(device, slot, effect);
if(err != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, done);
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
break;
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
@@ -195,12 +195,15 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
slot->AuxSendAuto = value;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
break;
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
+ /* HACK: Force sources to update by doing a listener update */
+ ReadLock(&context->PropLock);
+ UpdateListenerProps(context);
+ ReadUnlock(&context->PropLock);
done:
ALCcontext_DecRef(context);
diff --git a/OpenAL32/alListener.c b/OpenAL32/alListener.c
index 66865473..b215f678 100644
--- a/OpenAL32/alListener.c
+++ b/OpenAL32/alListener.c
@@ -33,29 +33,28 @@ AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value)
context = GetContextRef();
if(!context) return;
+ WriteLock(&context->PropLock);
switch(param)
{
case AL_GAIN:
if(!(value >= 0.0f && isfinite(value)))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
context->Listener->Gain = value;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
break;
case AL_METERS_PER_UNIT:
if(!(value >= 0.0f && isfinite(value)))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
context->Listener->MetersPerUnit = value;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
break;
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
+ UpdateListenerProps(context);
done:
+ WriteUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -67,33 +66,32 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val
context = GetContextRef();
if(!context) return;
+ WriteLock(&context->PropLock);
switch(param)
{
case AL_POSITION:
if(!(isfinite(value1) && isfinite(value2) && isfinite(value3)))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
- LockContext(context);
- aluVectorSet(&context->Listener->Position, value1, value2, value3, 1.0f);
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
- UnlockContext(context);
+ context->Listener->Position[0] = value1;
+ context->Listener->Position[1] = value2;
+ context->Listener->Position[2] = value3;
break;
case AL_VELOCITY:
if(!(isfinite(value1) && isfinite(value2) && isfinite(value3)))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
- LockContext(context);
- aluVectorSet(&context->Listener->Velocity, value1, value2, value3, 0.0f);
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
- UnlockContext(context);
+ context->Listener->Velocity[0] = value1;
+ context->Listener->Velocity[1] = value2;
+ context->Listener->Velocity[2] = value3;
break;
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
+ UpdateListenerProps(context);
done:
+ WriteUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -121,6 +119,7 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
context = GetContextRef();
if(!context) return;
+ WriteLock(&context->PropLock);
if(!(values))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
switch(param)
@@ -129,8 +128,6 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
if(!(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]) &&
isfinite(values[3]) && isfinite(values[4]) && isfinite(values[5])))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
- LockContext(context);
/* AT then UP */
context->Listener->Forward[0] = values[0];
context->Listener->Forward[1] = values[1];
@@ -138,15 +135,15 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
context->Listener->Up[0] = values[3];
context->Listener->Up[1] = values[4];
context->Listener->Up[2] = values[5];
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
- UnlockContext(context);
break;
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
+ UpdateListenerProps(context);
done:
+ WriteUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -158,13 +155,16 @@ AL_API ALvoid AL_APIENTRY alListeneri(ALenum param, ALint UNUSED(value))
context = GetContextRef();
if(!context) return;
+ WriteLock(&context->PropLock);
switch(param)
{
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
+ UpdateListenerProps(context);
done:
+ WriteUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -184,13 +184,16 @@ AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, A
context = GetContextRef();
if(!context) return;
+ WriteLock(&context->PropLock);
switch(param)
{
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
+ UpdateListenerProps(context);
done:
+ WriteUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -224,6 +227,7 @@ AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values)
context = GetContextRef();
if(!context) return;
+ WriteLock(&context->PropLock);
if(!(values))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
switch(param)
@@ -231,8 +235,10 @@ AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values)
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
+ UpdateListenerProps(context);
done:
+ WriteUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -244,6 +250,7 @@ AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
context = GetContextRef();
if(!context) return;
+ ReadLock(&context->PropLock);
if(!(value))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
switch(param)
@@ -261,6 +268,7 @@ AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
}
done:
+ ReadUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -272,24 +280,21 @@ AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat
context = GetContextRef();
if(!context) return;
+ ReadLock(&context->PropLock);
if(!(value1 && value2 && value3))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
switch(param)
{
case AL_POSITION:
- LockContext(context);
- *value1 = context->Listener->Position.v[0];
- *value2 = context->Listener->Position.v[1];
- *value3 = context->Listener->Position.v[2];
- UnlockContext(context);
+ *value1 = context->Listener->Position[0];
+ *value2 = context->Listener->Position[1];
+ *value3 = context->Listener->Position[2];
break;
case AL_VELOCITY:
- LockContext(context);
- *value1 = context->Listener->Velocity.v[0];
- *value2 = context->Listener->Velocity.v[1];
- *value3 = context->Listener->Velocity.v[2];
- UnlockContext(context);
+ *value1 = context->Listener->Velocity[0];
+ *value2 = context->Listener->Velocity[1];
+ *value3 = context->Listener->Velocity[2];
break;
default:
@@ -297,6 +302,7 @@ AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat
}
done:
+ ReadUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -321,12 +327,12 @@ AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
context = GetContextRef();
if(!context) return;
+ ReadLock(&context->PropLock);
if(!(values))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
switch(param)
{
case AL_ORIENTATION:
- LockContext(context);
// AT then UP
values[0] = context->Listener->Forward[0];
values[1] = context->Listener->Forward[1];
@@ -334,7 +340,6 @@ AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
values[3] = context->Listener->Up[0];
values[4] = context->Listener->Up[1];
values[5] = context->Listener->Up[2];
- UnlockContext(context);
break;
default:
@@ -342,6 +347,7 @@ AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
}
done:
+ ReadUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -353,6 +359,7 @@ AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum param, ALint *value)
context = GetContextRef();
if(!context) return;
+ ReadLock(&context->PropLock);
if(!(value))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
switch(param)
@@ -362,6 +369,7 @@ AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum param, ALint *value)
}
done:
+ ReadUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -373,24 +381,21 @@ AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *valu
context = GetContextRef();
if(!context) return;
+ ReadLock(&context->PropLock);
if(!(value1 && value2 && value3))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
switch (param)
{
case AL_POSITION:
- LockContext(context);
- *value1 = (ALint)context->Listener->Position.v[0];
- *value2 = (ALint)context->Listener->Position.v[1];
- *value3 = (ALint)context->Listener->Position.v[2];
- UnlockContext(context);
+ *value1 = (ALint)context->Listener->Position[0];
+ *value2 = (ALint)context->Listener->Position[1];
+ *value3 = (ALint)context->Listener->Position[2];
break;
case AL_VELOCITY:
- LockContext(context);
- *value1 = (ALint)context->Listener->Velocity.v[0];
- *value2 = (ALint)context->Listener->Velocity.v[1];
- *value3 = (ALint)context->Listener->Velocity.v[2];
- UnlockContext(context);
+ *value1 = (ALint)context->Listener->Velocity[0];
+ *value2 = (ALint)context->Listener->Velocity[1];
+ *value3 = (ALint)context->Listener->Velocity[2];
break;
default:
@@ -398,6 +403,7 @@ AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *valu
}
done:
+ ReadUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -417,12 +423,12 @@ AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
context = GetContextRef();
if(!context) return;
+ ReadLock(&context->PropLock);
if(!(values))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
switch(param)
{
case AL_ORIENTATION:
- LockContext(context);
// AT then UP
values[0] = (ALint)context->Listener->Forward[0];
values[1] = (ALint)context->Listener->Forward[1];
@@ -430,7 +436,6 @@ AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
values[3] = (ALint)context->Listener->Up[0];
values[4] = (ALint)context->Listener->Up[1];
values[5] = (ALint)context->Listener->Up[2];
- UnlockContext(context);
break;
default:
@@ -438,5 +443,64 @@ AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
}
done:
+ ReadUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
+
+
+void UpdateListenerProps(ALCcontext *context)
+{
+ ALlistener *listener = context->Listener;
+ struct ALlistenerProps *props;
+
+ /* Get an unused proprty container, or allocate a new one as needed. */
+ props = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire);
+ if(!props)
+ props = al_calloc(16, sizeof(*props));
+ else
+ {
+ struct ALlistenerProps *next;
+ do {
+ next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
+ } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALlistenerProps*,
+ &listener->FreeList, &props, next, almemory_order_seq_cst,
+ almemory_order_consume) == 0);
+ }
+
+ /* Copy in current property values. */
+ ATOMIC_STORE(&props->Position[0], listener->Position[0], almemory_order_relaxed);
+ ATOMIC_STORE(&props->Position[1], listener->Position[1], almemory_order_relaxed);
+ ATOMIC_STORE(&props->Position[2], listener->Position[2], almemory_order_relaxed);
+
+ ATOMIC_STORE(&props->Velocity[0], listener->Velocity[0], almemory_order_relaxed);
+ ATOMIC_STORE(&props->Velocity[1], listener->Velocity[1], almemory_order_relaxed);
+ ATOMIC_STORE(&props->Velocity[2], listener->Velocity[2], almemory_order_relaxed);
+
+ ATOMIC_STORE(&props->Forward[0], listener->Forward[0], almemory_order_relaxed);
+ ATOMIC_STORE(&props->Forward[1], listener->Forward[1], almemory_order_relaxed);
+ ATOMIC_STORE(&props->Forward[2], listener->Forward[2], almemory_order_relaxed);
+ ATOMIC_STORE(&props->Up[0], listener->Up[0], almemory_order_relaxed);
+ ATOMIC_STORE(&props->Up[1], listener->Up[1], almemory_order_relaxed);
+ ATOMIC_STORE(&props->Up[2], listener->Up[2], almemory_order_relaxed);
+
+ ATOMIC_STORE(&props->Gain, listener->Gain, almemory_order_relaxed);
+ ATOMIC_STORE(&props->MetersPerUnit, listener->MetersPerUnit, almemory_order_relaxed);
+
+ ATOMIC_STORE(&props->DopplerFactor, context->DopplerFactor, almemory_order_relaxed);
+ ATOMIC_STORE(&props->DopplerVelocity, context->DopplerVelocity, almemory_order_relaxed);
+ ATOMIC_STORE(&props->SpeedOfSound, context->SpeedOfSound, almemory_order_relaxed);
+
+ /* Set the new container for updating internal parameters. */
+ props = ATOMIC_EXCHANGE(struct ALlistenerProps*, &listener->Update, props, almemory_order_acq_rel);
+ if(props)
+ {
+ /* If there was an unused update container, put it back in the
+ * freelist.
+ */
+ struct ALlistenerProps *first = ATOMIC_LOAD(&listener->FreeList);
+ do {
+ ATOMIC_STORE(&props->next, first, almemory_order_relaxed);
+ } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALlistenerProps*,
+ &listener->FreeList, &first, props) == 0);
+ }
+}
diff --git a/OpenAL32/alState.c b/OpenAL32/alState.c
index dca41363..899dacd4 100644
--- a/OpenAL32/alState.c
+++ b/OpenAL32/alState.c
@@ -26,6 +26,7 @@
#include "AL/al.h"
#include "AL/alext.h"
#include "alError.h"
+#include "alListener.h"
#include "alSource.h"
#include "alAuxEffectSlot.h"
@@ -55,12 +56,15 @@ AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
{
case AL_SOURCE_DISTANCE_MODEL:
context->SourceDistanceModel = AL_TRUE;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
break;
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
+ /* HACK: Force sources to update by doing a listener update */
+ ReadLock(&context->PropLock);
+ UpdateListenerProps(context);
+ ReadUnlock(&context->PropLock);
done:
ALCcontext_DecRef(context);
@@ -77,12 +81,15 @@ AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
{
case AL_SOURCE_DISTANCE_MODEL:
context->SourceDistanceModel = AL_FALSE;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
break;
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
+ /* HACK: Force sources to update by doing a listener update */
+ ReadLock(&context->PropLock);
+ UpdateListenerProps(context);
+ ReadUnlock(&context->PropLock);
done:
ALCcontext_DecRef(context);
@@ -547,8 +554,10 @@ AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
if(!(value >= 0.0f && isfinite(value)))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ WriteLock(&context->PropLock);
context->DopplerFactor = value;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
+ UpdateListenerProps(context);
+ WriteUnlock(&context->PropLock);
done:
ALCcontext_DecRef(context);
@@ -564,8 +573,10 @@ AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
if(!(value >= 0.0f && isfinite(value)))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ WriteLock(&context->PropLock);
context->DopplerVelocity = value;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
+ UpdateListenerProps(context);
+ WriteUnlock(&context->PropLock);
done:
ALCcontext_DecRef(context);
@@ -581,8 +592,10 @@ AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
if(!(value > 0.0f && isfinite(value)))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ WriteLock(&context->PropLock);
context->SpeedOfSound = value;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
+ UpdateListenerProps(context);
+ WriteUnlock(&context->PropLock);
done:
ALCcontext_DecRef(context);
@@ -601,9 +614,11 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
value == AL_NONE))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ WriteLock(&context->PropLock);
context->DistanceModel = value;
if(!context->SourceDistanceModel)
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
+ UpdateListenerProps(context);
+ WriteUnlock(&context->PropLock);
done:
ALCcontext_DecRef(context);