diff options
-rw-r--r-- | Alc/ALc.c | 35 | ||||
-rw-r--r-- | Alc/ALu.c | 58 | ||||
-rw-r--r-- | OpenAL32/Include/alListener.h | 30 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 7 | ||||
-rw-r--r-- | OpenAL32/alAuxEffectSlot.c | 7 | ||||
-rw-r--r-- | OpenAL32/alListener.c | 148 | ||||
-rw-r--r-- | OpenAL32/alState.c | 27 |
7 files changed, 234 insertions, 78 deletions
@@ -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; @@ -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); |