diff options
Diffstat (limited to 'OpenAL32/alSource.c')
-rw-r--r-- | OpenAL32/alSource.c | 452 |
1 files changed, 320 insertions, 132 deletions
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)); |