diff options
Diffstat (limited to 'OpenAL32')
-rw-r--r-- | OpenAL32/Include/alMain.h | 2 | ||||
-rw-r--r-- | OpenAL32/Include/alSource.h | 104 | ||||
-rw-r--r-- | OpenAL32/Include/alu.h | 5 | ||||
-rw-r--r-- | OpenAL32/alAuxEffectSlot.c | 2 | ||||
-rw-r--r-- | OpenAL32/alListener.c | 36 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 452 | ||||
-rw-r--r-- | OpenAL32/alState.c | 48 |
7 files changed, 474 insertions, 175 deletions
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 44ce4fe0..a624e078 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -695,7 +695,7 @@ struct ALCcontext_struct { volatile ALfloat DopplerFactor; volatile ALfloat DopplerVelocity; volatile ALfloat SpeedOfSound; - volatile ALenum DeferUpdates; + ATOMIC(ALenum) DeferUpdates; RWLock PropLock; diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index 187d7e07..6d915153 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -13,6 +13,7 @@ extern "C" { struct ALbuffer; struct ALsource; +struct ALsourceProps; typedef struct ALbufferlistitem { @@ -25,11 +26,13 @@ typedef struct ALvoice { struct ALsource *volatile Source; /** Method to update mixing parameters. */ - ALvoid (*Update)(struct ALvoice *self, const struct ALsource *source, const struct ALbuffer *ALBuffer, const ALCcontext *context); + ALvoid (*Update)(struct ALvoice *self, const struct ALsourceProps *props, const struct ALbuffer *ALBuffer, const ALCcontext *context); /** Current target parameters used for mixing. */ ALint Step; + ALboolean Looping; + /* If not 'moving', gain/coefficients are set directly without fading. */ ALboolean Moving; @@ -46,6 +49,59 @@ typedef struct ALvoice { } ALvoice; +struct ALsourceProps { + ATOMIC(ALfloat) Pitch; + ATOMIC(ALfloat) Gain; + ATOMIC(ALfloat) OuterGain; + ATOMIC(ALfloat) MinGain; + ATOMIC(ALfloat) MaxGain; + ATOMIC(ALfloat) InnerAngle; + ATOMIC(ALfloat) OuterAngle; + ATOMIC(ALfloat) RefDistance; + ATOMIC(ALfloat) MaxDistance; + ATOMIC(ALfloat) RollOffFactor; + ATOMIC(ALfloat) Position[3]; + ATOMIC(ALfloat) Velocity[3]; + ATOMIC(ALfloat) Direction[3]; + ATOMIC(ALfloat) Orientation[2][3]; + ATOMIC(ALboolean) HeadRelative; + ATOMIC(ALboolean) Looping; + ATOMIC(enum DistanceModel) DistanceModel; + ATOMIC(ALboolean) DirectChannels; + + ATOMIC(ALboolean) DryGainHFAuto; + ATOMIC(ALboolean) WetGainAuto; + ATOMIC(ALboolean) WetGainHFAuto; + ATOMIC(ALfloat) OuterGainHF; + + ATOMIC(ALfloat) AirAbsorptionFactor; + ATOMIC(ALfloat) RoomRolloffFactor; + ATOMIC(ALfloat) DopplerFactor; + + ATOMIC(ALfloat) StereoPan[2]; + + ATOMIC(ALfloat) Radius; + + /** Direct filter and auxiliary send info. */ + struct { + ATOMIC(ALfloat) Gain; + ATOMIC(ALfloat) GainHF; + ATOMIC(ALfloat) HFReference; + ATOMIC(ALfloat) GainLF; + ATOMIC(ALfloat) LFReference; + } Direct; + struct { + ATOMIC(struct ALeffectslot*) Slot; + ATOMIC(ALfloat) Gain; + ATOMIC(ALfloat) GainHF; + ATOMIC(ALfloat) HFReference; + ATOMIC(ALfloat) GainLF; + ATOMIC(ALfloat) LFReference; + } Send[MAX_SENDS]; + + ATOMIC(struct ALsourceProps*) next; +}; + typedef struct ALsource { /** Source properties. */ volatile ALfloat Pitch; @@ -58,9 +114,9 @@ typedef struct ALsource { volatile ALfloat RefDistance; volatile ALfloat MaxDistance; volatile ALfloat RollOffFactor; - aluVector Position; - aluVector Velocity; - aluVector Direction; + volatile ALfloat Position[3]; + volatile ALfloat Velocity[3]; + volatile ALfloat Direction[3]; volatile ALfloat Orientation[2][3]; volatile ALboolean HeadRelative; volatile ALboolean Looping; @@ -83,6 +139,23 @@ typedef struct ALsource { volatile ALfloat Radius; + /** Direct filter and auxiliary send info. */ + struct { + ALfloat Gain; + ALfloat GainHF; + ALfloat HFReference; + ALfloat GainLF; + ALfloat LFReference; + } Direct; + struct { + struct ALeffectslot *Slot; + ALfloat Gain; + ALfloat GainHF; + ALfloat HFReference; + ALfloat GainLF; + ALfloat LFReference; + } Send[MAX_SENDS]; + /** * Last user-specified offset, and the offset type (bytes, samples, or * seconds). @@ -114,25 +187,8 @@ typedef struct ALsource { ALuint NumChannels; ALuint SampleSize; - /** Direct filter and auxiliary send info. */ - struct { - ALfloat Gain; - ALfloat GainHF; - ALfloat HFReference; - ALfloat GainLF; - ALfloat LFReference; - } Direct; - struct { - struct ALeffectslot *Slot; - ALfloat Gain; - ALfloat GainHF; - ALfloat HFReference; - ALfloat GainLF; - ALfloat LFReference; - } Send[MAX_SENDS]; - - /** Source needs to update its mixing parameters. */ - ATOMIC(ALenum) NeedsUpdate; + ATOMIC(struct ALsourceProps*) Update; + ATOMIC(struct ALsourceProps*) FreeList; /** Self ID */ ALuint id; @@ -152,6 +208,8 @@ inline struct ALsource *LookupSource(ALCcontext *context, ALuint id) inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id) { return (struct ALsource*)RemoveUIntMapKeyNoLock(&context->SourceMap, id); } +void UpdateSourceProps(ALsource *source, ALuint num_sends); +void UpdateAllSourceProps(ALCcontext *context); ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state); ALboolean ApplyOffset(ALsource *Source); diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h index c20c6404..8e93dc6e 100644 --- a/OpenAL32/Include/alu.h +++ b/OpenAL32/Include/alu.h @@ -34,6 +34,7 @@ extern "C" { #endif struct ALsource; +struct ALsourceProps; struct ALvoice; struct ALeffectslot; struct ALbuffer; @@ -375,8 +376,8 @@ void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALuint numchans, c ALvoid UpdateContextSources(ALCcontext *context); -ALvoid CalcSourceParams(struct ALvoice *voice, const struct ALsource *source, const struct ALbuffer *buffer, const ALCcontext *ALContext); -ALvoid CalcNonAttnSourceParams(struct ALvoice *voice, const struct ALsource *source, const struct ALbuffer *buffer, const ALCcontext *ALContext); +ALvoid CalcAttnSourceParams(struct ALvoice *voice, const struct ALsourceProps *props, const struct ALbuffer *buffer, const ALCcontext *ALContext); +ALvoid CalcNonAttnSourceParams(struct ALvoice *voice, const struct ALsourceProps *props, const struct ALbuffer *buffer, const ALCcontext *ALContext); ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, ALCdevice *Device, ALuint SamplesToDo); diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c index 98ee9328..6d1423db 100644 --- a/OpenAL32/alAuxEffectSlot.c +++ b/OpenAL32/alAuxEffectSlot.c @@ -202,6 +202,8 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); slot->AuxSendAuto = value; UpdateEffectSlotProps(slot, AL_FALSE); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateAllSourceProps(context); break; default: diff --git a/OpenAL32/alListener.c b/OpenAL32/alListener.c index 1c40c399..c59d644b 100644 --- a/OpenAL32/alListener.c +++ b/OpenAL32/alListener.c @@ -51,7 +51,11 @@ AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value) default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } - UpdateListenerProps(context); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } done: WriteUnlock(&context->PropLock); @@ -88,7 +92,11 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } - UpdateListenerProps(context); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } done: WriteUnlock(&context->PropLock); @@ -140,7 +148,11 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values) default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } - UpdateListenerProps(context); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } done: WriteUnlock(&context->PropLock); @@ -161,7 +173,11 @@ AL_API ALvoid AL_APIENTRY alListeneri(ALenum param, ALint UNUSED(value)) default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } - UpdateListenerProps(context); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } done: WriteUnlock(&context->PropLock); @@ -190,7 +206,11 @@ AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, A default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } - UpdateListenerProps(context); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } done: WriteUnlock(&context->PropLock); @@ -235,7 +255,11 @@ AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values) default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } - UpdateListenerProps(context); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } done: WriteUnlock(&context->PropLock); diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index a62bf59e..e2d6ca4f 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -48,6 +48,7 @@ extern inline struct ALsource *LookupSource(ALCcontext *context, ALuint id); extern inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id); static ALvoid InitSourceParams(ALsource *Source); +static ALvoid DeinitSource(ALsource *source); static ALint64 GetSourceSampleOffset(ALsource *Source); static ALdouble GetSourceSecOffset(ALsource *Source); static ALdouble GetSourceOffset(ALsource *Source, ALenum name); @@ -123,6 +124,12 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp p static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint *values); static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint64 *values); +static inline bool SourceShouldUpdate(const ALsource *source, const ALCcontext *context) +{ + return (source->state == AL_PLAYING || source->state == AL_PAUSED) && + !ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire); +} + static ALint FloatValsByProp(ALenum prop) { if(prop != (ALenum)((SourceProp)prop)) @@ -376,8 +383,14 @@ static ALint Int64ValsByProp(ALenum prop) SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); \ } while(0) +#define DO_UPDATEPROPS() do { \ + if(SourceShouldUpdate(Source, Context)) \ + UpdateSourceProps(Source, device->NumAuxSends); \ +} while(0) + static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALfloat *values) { + ALCdevice *device = Context->Device; ALint ival; switch(prop) @@ -393,98 +406,98 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp p CHECKVAL(*values >= 0.0f); Source->Pitch = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_CONE_INNER_ANGLE: CHECKVAL(*values >= 0.0f && *values <= 360.0f); Source->InnerAngle = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_CONE_OUTER_ANGLE: CHECKVAL(*values >= 0.0f && *values <= 360.0f); Source->OuterAngle = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_GAIN: CHECKVAL(*values >= 0.0f); Source->Gain = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_MAX_DISTANCE: CHECKVAL(*values >= 0.0f); Source->MaxDistance = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_ROLLOFF_FACTOR: CHECKVAL(*values >= 0.0f); Source->RollOffFactor = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_REFERENCE_DISTANCE: CHECKVAL(*values >= 0.0f); Source->RefDistance = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_MIN_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->MinGain = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_MAX_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->MaxGain = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_CONE_OUTER_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->OuterGain = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_CONE_OUTER_GAINHF: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->OuterGainHF = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_AIR_ABSORPTION_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 10.0f); Source->AirAbsorptionFactor = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_ROOM_ROLLOFF_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 10.0f); Source->RoomRolloffFactor = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_DOPPLER_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->DopplerFactor = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_SEC_OFFSET: @@ -492,13 +505,13 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp p case AL_BYTE_OFFSET: CHECKVAL(*values >= 0.0f); - LockContext(Context); Source->OffsetType = prop; Source->Offset = *values; if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && - !Context->DeferUpdates) + !ATOMIC_LOAD(&Context->DeferUpdates, almemory_order_acquire)) { + LockContext(Context); WriteLock(&Source->queue_lock); if(ApplyOffset(Source) == AL_FALSE) { @@ -507,68 +520,64 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp p SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); } WriteUnlock(&Source->queue_lock); + UnlockContext(Context); } - UnlockContext(Context); return AL_TRUE; case AL_SOURCE_RADIUS: CHECKVAL(*values >= 0.0f && isfinite(*values)); Source->Radius = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_STEREO_ANGLES: CHECKVAL(isfinite(values[0]) && isfinite(values[1])); - LockContext(Context); Source->StereoPan[0] = values[0]; Source->StereoPan[1] = values[1]; - UnlockContext(Context); - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_POSITION: CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2])); - LockContext(Context); - aluVectorSet(&Source->Position, values[0], values[1], values[2], 1.0f); - UnlockContext(Context); - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + Source->Position[0] = values[0]; + Source->Position[1] = values[1]; + Source->Position[2] = values[2]; + DO_UPDATEPROPS(); return AL_TRUE; case AL_VELOCITY: CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2])); - LockContext(Context); - aluVectorSet(&Source->Velocity, values[0], values[1], values[2], 0.0f); - UnlockContext(Context); - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + Source->Velocity[0] = values[0]; + Source->Velocity[1] = values[1]; + Source->Velocity[2] = values[2]; + DO_UPDATEPROPS(); return AL_TRUE; case AL_DIRECTION: CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2])); - LockContext(Context); - aluVectorSet(&Source->Direction, values[0], values[1], values[2], 0.0f); - UnlockContext(Context); - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + Source->Direction[0] = values[0]; + Source->Direction[1] = values[1]; + Source->Direction[2] = values[2]; + DO_UPDATEPROPS(); return AL_TRUE; case AL_ORIENTATION: CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]) && isfinite(values[3]) && isfinite(values[4]) && isfinite(values[5])); - LockContext(Context); Source->Orientation[0][0] = values[0]; Source->Orientation[0][1] = values[1]; Source->Orientation[0][2] = values[2]; Source->Orientation[1][0] = values[3]; Source->Orientation[1][1] = values[4]; Source->Orientation[1][2] = values[5]; - UnlockContext(Context); - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; @@ -626,13 +635,14 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->HeadRelative = (ALboolean)*values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_LOOPING: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->Looping = (ALboolean)*values; + DO_UPDATEPROPS(); return AL_TRUE; case AL_BUFFER: @@ -695,13 +705,13 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p case AL_BYTE_OFFSET: CHECKVAL(*values >= 0); - LockContext(Context); Source->OffsetType = prop; Source->Offset = *values; if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && - !Context->DeferUpdates) + !ATOMIC_LOAD(&Context->DeferUpdates, almemory_order_acquire)) { + LockContext(Context); WriteLock(&Source->queue_lock); if(ApplyOffset(Source) == AL_FALSE) { @@ -710,8 +720,8 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); } WriteUnlock(&Source->queue_lock); + UnlockContext(Context); } - UnlockContext(Context); return AL_TRUE; case AL_DIRECT_FILTER: @@ -722,7 +732,6 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); } - LockContext(Context); if(!filter) { Source->Direct.Gain = 1.0f; @@ -739,37 +748,36 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p Source->Direct.GainLF = filter->GainLF; Source->Direct.LFReference = filter->LFReference; } - UnlockContext(Context); UnlockFiltersRead(device); - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_DIRECT_FILTER_GAINHF_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->DryGainHFAuto = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->WetGainAuto = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->WetGainHFAuto = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_DIRECT_CHANNELS_SOFT: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->DirectChannels = *values; - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_DISTANCE_MODEL: @@ -783,27 +791,20 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p Source->DistanceModel = *values; if(Context->SourceDistanceModel) - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + DO_UPDATEPROPS(); return AL_TRUE; case AL_AUXILIARY_SEND_FILTER: LockFiltersRead(device); - LockContext(Context); if(!((ALuint)values[1] < device->NumAuxSends && (values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != NULL) && (values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL))) { - UnlockContext(Context); UnlockFiltersRead(device); SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); } - /* Add refcount on the new slot, and release the previous slot */ - if(slot) IncrementRef(&slot->ref); - slot = ExchangePtr((XchgPtr*)&Source->Send[values[1]].Slot, slot); - if(slot) DecrementRef(&slot->ref); - if(!filter) { /* Disable filter */ @@ -821,9 +822,28 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p Source->Send[values[1]].GainLF = filter->GainLF; Source->Send[values[1]].LFReference = filter->LFReference; } - UnlockContext(Context); UnlockFiltersRead(device); - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + + if(slot != Source->Send[values[1]].Slot && + (Source->state == AL_PLAYING || Source->state == AL_PAUSED)) + { + /* Add refcount on the new slot, and release the previous slot */ + if(slot) IncrementRef(&slot->ref); + slot = ExchangePtr((XchgPtr*)&Source->Send[values[1]].Slot, slot); + if(slot) DecrementRef(&slot->ref); + /* We must force an update if the auxiliary slot changed on a + * playing source, in case the slot is about to be deleted. + */ + UpdateSourceProps(Source, device->NumAuxSends); + } + else + { + if(slot) IncrementRef(&slot->ref); + slot = ExchangePtr((XchgPtr*)&Source->Send[values[1]].Slot, slot); + if(slot) DecrementRef(&slot->ref); + DO_UPDATEPROPS(); + } + return AL_TRUE; @@ -1078,10 +1098,8 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp p return AL_TRUE; case AL_STEREO_ANGLES: - LockContext(Context); values[0] = Source->StereoPan[0]; values[1] = Source->StereoPan[1]; - UnlockContext(Context); return AL_TRUE; case AL_SEC_OFFSET_LATENCY_SOFT: @@ -1093,38 +1111,30 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp p return AL_TRUE; case AL_POSITION: - LockContext(Context); - values[0] = Source->Position.v[0]; - values[1] = Source->Position.v[1]; - values[2] = Source->Position.v[2]; - UnlockContext(Context); + values[0] = Source->Position[0]; + values[1] = Source->Position[1]; + values[2] = Source->Position[2]; return AL_TRUE; case AL_VELOCITY: - LockContext(Context); - values[0] = Source->Velocity.v[0]; - values[1] = Source->Velocity.v[1]; - values[2] = Source->Velocity.v[2]; - UnlockContext(Context); + values[0] = Source->Velocity[0]; + values[1] = Source->Velocity[1]; + values[2] = Source->Velocity[2]; return AL_TRUE; case AL_DIRECTION: - LockContext(Context); - values[0] = Source->Direction.v[0]; - values[1] = Source->Direction.v[1]; - values[2] = Source->Direction.v[2]; - UnlockContext(Context); + values[0] = Source->Direction[0]; + values[1] = Source->Direction[1]; + values[2] = Source->Direction[2]; return AL_TRUE; case AL_ORIENTATION: - LockContext(Context); values[0] = Source->Orientation[0][0]; values[1] = Source->Orientation[0][1]; values[2] = Source->Orientation[0][2]; values[3] = Source->Orientation[1][0]; values[4] = Source->Orientation[1][1]; values[5] = Source->Orientation[1][2]; - UnlockContext(Context); return AL_TRUE; /* 1x int */ @@ -1522,9 +1532,8 @@ done: AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) { ALCcontext *context; - ALbufferlistitem *BufferList; ALsource *Source; - ALsizei i, j; + ALsizei i; context = GetContextRef(); if(!context) return; @@ -1559,22 +1568,7 @@ AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) } UnlockContext(context); - BufferList = ATOMIC_EXCHANGE(ALbufferlistitem*, &Source->queue, NULL); - while(BufferList != NULL) - { - ALbufferlistitem *next = BufferList->next; - if(BufferList->buffer != NULL) - DecrementRef(&BufferList->buffer->ref); - free(BufferList); - BufferList = next; - } - - for(j = 0;j < MAX_SENDS;++j) - { - if(Source->Send[j].Slot) - DecrementRef(&Source->Send[j].Slot->ref); - Source->Send[j].Slot = NULL; - } + DeinitSource(Source); memset(Source, 0, sizeof(*Source)); al_free(Source); @@ -1612,6 +1606,7 @@ AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value) Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1620,6 +1615,7 @@ AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value) else SetSourcefv(Source, Context, param, &value); UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1632,6 +1628,7 @@ AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1 Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1643,6 +1640,7 @@ AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1 SetSourcefv(Source, Context, param, fvals); } UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1655,6 +1653,7 @@ AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1665,6 +1664,7 @@ AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat else SetSourcefv(Source, Context, param, values); UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1678,6 +1678,7 @@ AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble va Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1689,6 +1690,7 @@ AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble va SetSourcefv(Source, Context, param, &fval); } UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1701,6 +1703,7 @@ AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble v Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1712,6 +1715,7 @@ AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble v SetSourcefv(Source, Context, param, fvals); } UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1725,6 +1729,7 @@ AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdo Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1742,6 +1747,7 @@ AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdo SetSourcefv(Source, Context, param, fvals); } UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1755,6 +1761,7 @@ AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value) Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1763,6 +1770,7 @@ AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value) else SetSourceiv(Source, Context, param, &value); UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1775,6 +1783,7 @@ AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, AL Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1786,6 +1795,7 @@ AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, AL SetSourceiv(Source, Context, param, ivals); } UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1798,6 +1808,7 @@ AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *val Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1808,6 +1819,7 @@ AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *val else SetSourceiv(Source, Context, param, values); UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1821,6 +1833,7 @@ AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SO Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1829,6 +1842,7 @@ AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SO else SetSourcei64v(Source, Context, param, &value); UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1841,6 +1855,7 @@ AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOF Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1852,6 +1867,7 @@ AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOF SetSourcei64v(Source, Context, param, i64vals); } UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1864,6 +1880,7 @@ AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALin Context = GetContextRef(); if(!Context) return; + WriteLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1874,6 +1891,7 @@ AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALin else SetSourcei64v(Source, Context, param, values); UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1887,6 +1905,7 @@ AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *val Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1901,6 +1920,7 @@ AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *val *value = (ALfloat)dval; } UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1914,6 +1934,7 @@ AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *va Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1932,6 +1953,7 @@ AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *va } } UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1946,6 +1968,7 @@ AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *va Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1964,6 +1987,7 @@ AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *va } } UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1977,6 +2001,7 @@ AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble * Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -1987,6 +2012,7 @@ AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble * else GetSourcedv(Source, Context, param, value); UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -1999,6 +2025,7 @@ AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -2017,6 +2044,7 @@ AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble } } UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -2029,6 +2057,7 @@ AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -2039,6 +2068,7 @@ AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble else GetSourcedv(Source, Context, param, values); UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -2052,6 +2082,7 @@ AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -2062,6 +2093,7 @@ AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value else GetSourceiv(Source, Context, param, value); UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -2075,6 +2107,7 @@ AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1 Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -2093,6 +2126,7 @@ AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1 } } UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -2106,6 +2140,7 @@ AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -2116,6 +2151,7 @@ AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values else GetSourceiv(Source, Context, param, values); UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -2129,6 +2165,7 @@ AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64S Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -2139,6 +2176,7 @@ AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64S else GetSourcei64v(Source, Context, param, value); UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -2151,6 +2189,7 @@ AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64 Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -2169,6 +2208,7 @@ AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64 } } UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -2181,6 +2221,7 @@ AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64 Context = GetContextRef(); if(!Context) return; + ReadLock(&Context->PropLock); LockSourcesRead(Context); if((Source=LookupSource(Context, source)) == NULL) alSetError(Context, AL_INVALID_NAME); @@ -2191,6 +2232,7 @@ AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64 else GetSourcei64v(Source, Context, param, values); UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); ALCcontext_DecRef(Context); } @@ -2241,8 +2283,10 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) for(i = 0;i < n;i++) { source = LookupSource(context, sources[i]); - if(context->DeferUpdates) source->new_state = AL_PLAYING; - else SetSourceState(source, context, AL_PLAYING); + if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + source->new_state = AL_PLAYING; + else + SetSourceState(source, context, AL_PLAYING); } UnlockContext(context); @@ -2277,8 +2321,10 @@ AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources) for(i = 0;i < n;i++) { source = LookupSource(context, sources[i]); - if(context->DeferUpdates) source->new_state = AL_PAUSED; - else SetSourceState(source, context, AL_PAUSED); + if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + source->new_state = AL_PAUSED; + else + SetSourceState(source, context, AL_PAUSED); } UnlockContext(context); @@ -2594,9 +2640,15 @@ static ALvoid InitSourceParams(ALsource *Source) Source->InnerAngle = 360.0f; Source->OuterAngle = 360.0f; Source->Pitch = 1.0f; - aluVectorSet(&Source->Position, 0.0f, 0.0f, 0.0f, 1.0f); - aluVectorSet(&Source->Velocity, 0.0f, 0.0f, 0.0f, 0.0f); - aluVectorSet(&Source->Direction, 0.0f, 0.0f, 0.0f, 0.0f); + Source->Position[0] = 0.0f; + Source->Position[1] = 0.0f; + Source->Position[2] = 0.0f; + Source->Velocity[0] = 0.0f; + Source->Velocity[1] = 0.0f; + Source->Velocity[2] = 0.0f; + Source->Direction[0] = 0.0f; + Source->Direction[1] = 0.0f; + Source->Direction[2] = 0.0f; Source->Orientation[0][0] = 0.0f; Source->Orientation[0][1] = 0.0f; Source->Orientation[0][2] = -1.0f; @@ -2628,15 +2680,6 @@ static ALvoid InitSourceParams(ALsource *Source) Source->DistanceModel = DefaultDistanceModel; - Source->state = AL_INITIAL; - Source->new_state = AL_NONE; - Source->SourceType = AL_UNDETERMINED; - Source->OffsetType = AL_NONE; - Source->Offset = 0.0; - - ATOMIC_INIT(&Source->queue, NULL); - ATOMIC_INIT(&Source->current_buffer, NULL); - Source->Direct.Gain = 1.0f; Source->Direct.GainHF = 1.0f; Source->Direct.HFReference = LOWPASSFREQREF; @@ -2651,7 +2694,170 @@ static ALvoid InitSourceParams(ALsource *Source) Source->Send[i].LFReference = HIGHPASSFREQREF; } - ATOMIC_INIT(&Source->NeedsUpdate, AL_TRUE); + Source->state = AL_INITIAL; + Source->new_state = AL_NONE; + Source->SourceType = AL_UNDETERMINED; + Source->OffsetType = AL_NONE; + Source->Offset = 0.0; + + ATOMIC_INIT(&Source->queue, NULL); + ATOMIC_INIT(&Source->current_buffer, NULL); + + ATOMIC_INIT(&Source->Update, NULL); + ATOMIC_INIT(&Source->FreeList, NULL); +} + +static ALvoid DeinitSource(ALsource *source) +{ + ALbufferlistitem *BufferList; + struct ALsourceProps *props; + size_t count = 0; + size_t i; + + props = ATOMIC_LOAD(&source->Update); + if(props) al_free(props); + + props = ATOMIC_LOAD(&source->FreeList, almemory_order_relaxed); + while(props) + { + struct ALsourceProps *next; + next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + al_free(props); + props = next; + ++count; + } + /* This is excessively spammy if it traces every source destruction, so + * just warn if it was unexpectedly large. + */ + if(count > 3) + WARN("Freed "SZFMT" Source property objects\n", count); + + BufferList = ATOMIC_EXCHANGE(ALbufferlistitem*, &source->queue, NULL); + while(BufferList != NULL) + { + ALbufferlistitem *next = BufferList->next; + if(BufferList->buffer != NULL) + DecrementRef(&BufferList->buffer->ref); + free(BufferList); + BufferList = next; + } + + for(i = 0;i < MAX_SENDS;++i) + { + if(source->Send[i].Slot) + DecrementRef(&source->Send[i].Slot->ref); + source->Send[i].Slot = NULL; + } +} + +void UpdateSourceProps(ALsource *source, ALuint num_sends) +{ + struct ALsourceProps *props; + size_t i; + + /* Get an unused property container, or allocate a new one as needed. */ + props = ATOMIC_LOAD(&source->FreeList, almemory_order_acquire); + if(!props) + props = al_calloc(16, sizeof(*props)); + else + { + struct ALsourceProps *next; + do { + next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps*, + &source->FreeList, &props, next, almemory_order_seq_cst, + almemory_order_consume) == 0); + } + + /* Copy in current property values. */ + ATOMIC_STORE(&props->Pitch, source->Pitch, almemory_order_relaxed); + ATOMIC_STORE(&props->Gain, source->Gain, almemory_order_relaxed); + ATOMIC_STORE(&props->OuterGain, source->OuterGain, almemory_order_relaxed); + ATOMIC_STORE(&props->MinGain, source->MinGain, almemory_order_relaxed); + ATOMIC_STORE(&props->MaxGain, source->MaxGain, almemory_order_relaxed); + ATOMIC_STORE(&props->InnerAngle, source->InnerAngle, almemory_order_relaxed); + ATOMIC_STORE(&props->OuterAngle, source->OuterAngle, almemory_order_relaxed); + ATOMIC_STORE(&props->RefDistance, source->RefDistance, almemory_order_relaxed); + ATOMIC_STORE(&props->MaxDistance, source->MaxDistance, almemory_order_relaxed); + ATOMIC_STORE(&props->RollOffFactor, source->RollOffFactor, almemory_order_relaxed); + for(i = 0;i < 3;i++) + ATOMIC_STORE(&props->Position[i], source->Position[i], almemory_order_relaxed); + for(i = 0;i < 3;i++) + ATOMIC_STORE(&props->Velocity[i], source->Velocity[i], almemory_order_relaxed); + for(i = 0;i < 3;i++) + ATOMIC_STORE(&props->Direction[i], source->Direction[i], almemory_order_relaxed); + for(i = 0;i < 2;i++) + { + size_t j; + for(j = 0;j < 3;j++) + ATOMIC_STORE(&props->Orientation[i][j], source->Orientation[i][j], + almemory_order_relaxed); + } + ATOMIC_STORE(&props->HeadRelative, source->HeadRelative, almemory_order_relaxed); + ATOMIC_STORE(&props->Looping, source->Looping, almemory_order_relaxed); + ATOMIC_STORE(&props->DistanceModel, source->DistanceModel, almemory_order_relaxed); + ATOMIC_STORE(&props->DirectChannels, source->DirectChannels, almemory_order_relaxed); + + ATOMIC_STORE(&props->DryGainHFAuto, source->DryGainHFAuto, almemory_order_relaxed); + ATOMIC_STORE(&props->WetGainAuto, source->WetGainAuto, almemory_order_relaxed); + ATOMIC_STORE(&props->WetGainHFAuto, source->WetGainHFAuto, almemory_order_relaxed); + ATOMIC_STORE(&props->OuterGainHF, source->OuterGainHF, almemory_order_relaxed); + + ATOMIC_STORE(&props->AirAbsorptionFactor, source->AirAbsorptionFactor, almemory_order_relaxed); + ATOMIC_STORE(&props->RoomRolloffFactor, source->RoomRolloffFactor, almemory_order_relaxed); + ATOMIC_STORE(&props->DopplerFactor, source->DopplerFactor, almemory_order_relaxed); + + ATOMIC_STORE(&props->StereoPan[0], source->StereoPan[0], almemory_order_relaxed); + ATOMIC_STORE(&props->StereoPan[1], source->StereoPan[1], almemory_order_relaxed); + + ATOMIC_STORE(&props->Radius, source->Radius, almemory_order_relaxed); + + ATOMIC_STORE(&props->Direct.Gain, source->Direct.Gain, almemory_order_relaxed); + ATOMIC_STORE(&props->Direct.GainHF, source->Direct.GainHF, almemory_order_relaxed); + ATOMIC_STORE(&props->Direct.HFReference, source->Direct.HFReference, almemory_order_relaxed); + ATOMIC_STORE(&props->Direct.GainLF, source->Direct.GainLF, almemory_order_relaxed); + ATOMIC_STORE(&props->Direct.LFReference, source->Direct.LFReference, almemory_order_relaxed); + + for(i = 0;i < num_sends;i++) + { + ATOMIC_STORE(&props->Send[i].Slot, source->Send[i].Slot, almemory_order_relaxed); + ATOMIC_STORE(&props->Send[i].Gain, source->Send[i].Gain, almemory_order_relaxed); + ATOMIC_STORE(&props->Send[i].GainHF, source->Send[i].GainHF, almemory_order_relaxed); + ATOMIC_STORE(&props->Send[i].HFReference, source->Send[i].HFReference, + almemory_order_relaxed); + ATOMIC_STORE(&props->Send[i].GainLF, source->Send[i].GainLF, almemory_order_relaxed); + ATOMIC_STORE(&props->Send[i].LFReference, source->Send[i].LFReference, + almemory_order_relaxed); + } + + /* Set the new container for updating internal parameters. */ + props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->Update, props, almemory_order_acq_rel); + if(props) + { + /* If there was an unused update container, put it back in the + * freelist. + */ + struct ALsourceProps *first = ATOMIC_LOAD(&source->FreeList); + do { + ATOMIC_STORE(&props->next, first, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps*, + &source->FreeList, &first, props) == 0); + } +} + +void UpdateAllSourceProps(ALCcontext *context) +{ + ALuint num_sends = context->Device->NumAuxSends; + ALsizei pos; + for(pos = 0;pos < context->VoiceCount;pos++) + { + ALvoice *voice = &context->Voices[pos]; + ALsource *source = voice->Source; + if(source != NULL && (source->state == AL_PLAYING || + source->state == AL_PAUSED)) + UpdateSourceProps(source, num_sends); + } + } @@ -2749,11 +2955,10 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) } if(BufferList->buffer->FmtChannels == FmtMono) - voice->Update = CalcSourceParams; + voice->Update = CalcAttnSourceParams; else voice->Update = CalcNonAttnSourceParams; - - ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); + UpdateSourceProps(Source, device->NumAuxSends); } else if(state == AL_PAUSED) { @@ -3084,30 +3289,13 @@ static ALboolean GetSampleOffset(ALsource *Source, ALuint *offset, ALuint *frac) */ ALvoid ReleaseALSources(ALCcontext *Context) { - ALbufferlistitem *item; ALsizei pos; - ALuint j; for(pos = 0;pos < Context->SourceMap.size;pos++) { ALsource *temp = Context->SourceMap.array[pos].value; Context->SourceMap.array[pos].value = NULL; - item = ATOMIC_EXCHANGE(ALbufferlistitem*, &temp->queue, NULL); - while(item != NULL) - { - ALbufferlistitem *next = item->next; - if(item->buffer != NULL) - DecrementRef(&item->buffer->ref); - free(item); - item = next; - } - - for(j = 0;j < MAX_SENDS;++j) - { - if(temp->Send[j].Slot) - DecrementRef(&temp->Send[j].Slot->ref); - temp->Send[j].Slot = NULL; - } + DeinitSource(temp); FreeThunkEntry(temp->id); memset(temp, 0, sizeof(*temp)); diff --git a/OpenAL32/alState.c b/OpenAL32/alState.c index c0c2ca82..e8a8d391 100644 --- a/OpenAL32/alState.c +++ b/OpenAL32/alState.c @@ -62,7 +62,11 @@ AL_API ALvoid AL_APIENTRY alEnable(ALenum capability) default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } - UpdateListenerProps(context); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } done: WriteUnlock(&context->PropLock); @@ -86,7 +90,11 @@ AL_API ALvoid AL_APIENTRY alDisable(ALenum capability) default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } - UpdateListenerProps(context); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } done: WriteUnlock(&context->PropLock); @@ -148,7 +156,7 @@ AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname) break; case AL_DEFERRED_UPDATES_SOFT: - value = context->DeferUpdates; + value = ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire); break; default: @@ -188,7 +196,7 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname) break; case AL_DEFERRED_UPDATES_SOFT: - value = (ALdouble)context->DeferUpdates; + value = (ALdouble)ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire); break; default: @@ -228,7 +236,7 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname) break; case AL_DEFERRED_UPDATES_SOFT: - value = (ALfloat)context->DeferUpdates; + value = (ALfloat)ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire); break; default: @@ -268,7 +276,7 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname) break; case AL_DEFERRED_UPDATES_SOFT: - value = (ALint)context->DeferUpdates; + value = (ALint)ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire); break; default: @@ -308,7 +316,7 @@ AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname) break; case AL_DEFERRED_UPDATES_SOFT: - value = (ALint64SOFT)context->DeferUpdates; + value = (ALint64SOFT)ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire); break; default: @@ -554,7 +562,11 @@ AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value) WriteLock(&context->PropLock); context->DopplerFactor = value; - UpdateListenerProps(context); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } WriteUnlock(&context->PropLock); done: @@ -573,7 +585,11 @@ AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value) WriteLock(&context->PropLock); context->DopplerVelocity = value; - UpdateListenerProps(context); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } WriteUnlock(&context->PropLock); done: @@ -592,7 +608,11 @@ AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value) WriteLock(&context->PropLock); context->SpeedOfSound = value; - UpdateListenerProps(context); + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } WriteUnlock(&context->PropLock); done: @@ -615,7 +635,13 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value) WriteLock(&context->PropLock); context->DistanceModel = value; if(!context->SourceDistanceModel) - UpdateListenerProps(context); + { + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + UpdateListenerProps(context); + UpdateAllSourceProps(context); + } + } WriteUnlock(&context->PropLock); done: |