diff options
author | Chris Robinson <[email protected]> | 2017-09-27 11:13:18 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2017-09-27 11:13:18 -0700 |
commit | 1ab890262168444c2f6e1a9d84c3d65e5afe37f5 (patch) | |
tree | 201157974888052def0b8c24cc3f61efa0ba0f8d /Alc | |
parent | fd70b0bca6dcc97edf16d4567c84933576828230 (diff) |
Re-update effect slots when context properties change
Also keep all free property update structs together in the context instead of
per-object.
Diffstat (limited to 'Alc')
-rw-r--r-- | Alc/ALc.c | 74 | ||||
-rw-r--r-- | Alc/ALu.c | 95 |
2 files changed, 91 insertions, 78 deletions
@@ -2255,6 +2255,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) context = ATOMIC_LOAD_SEQ(&device->ContextList); while(context) { + struct ALvoiceProps *vprops; ALsizei pos; if(context->DefaultSlot) @@ -2267,7 +2268,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) if(V(state,deviceUpdate)(device) == AL_FALSE) update_failed = AL_TRUE; else - UpdateEffectSlotProps(slot); + UpdateEffectSlotProps(slot, context); } WriteLock(&context->PropLock); @@ -2282,7 +2283,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) if(V(state,deviceUpdate)(device) == AL_FALSE) update_failed = AL_TRUE; else - UpdateEffectSlotProps(slot); + UpdateEffectSlotProps(slot, context); } UnlockUIntMapRead(&context->EffectSlotMap); @@ -2321,26 +2322,25 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release); } + + /* Clear any pre-existing voice property structs, in case the number of + * auxiliary sends is changing. Active sources will have updates + * respecified in UpdateAllSourceProps. + */ + vprops = ATOMIC_EXCHANGE_PTR(&context->FreeVoiceProps, NULL, almemory_order_acq_rel); + while(vprops) + { + struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed); + al_free(vprops); + vprops = next; + } + AllocateVoices(context, context->MaxVoices, old_sends); for(pos = 0;pos < context->VoiceCount;pos++) { ALvoice *voice = context->Voices[pos]; - struct ALvoiceProps *props; - /* Clear any pre-existing voice property structs, in case the - * number of auxiliary sends changed. Active sources will have - * updates respecified in UpdateAllSourceProps. - */ - props = ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_relaxed); - al_free(props); - - props = ATOMIC_EXCHANGE_PTR(&voice->FreeList, NULL, almemory_order_relaxed); - while(props) - { - struct ALvoiceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); - al_free(props); - props = next; - } + al_free(ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_acq_rel)); if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL) continue; @@ -2540,7 +2540,6 @@ static ALvoid InitContext(ALCcontext *Context) ATOMIC_FLAG_TEST_AND_SET(&listener->PropsClean, almemory_order_relaxed); ATOMIC_INIT(&listener->Update, NULL); - ATOMIC_INIT(&listener->FreeList, NULL); //Validate Context InitRef(&Context->UpdateCount, 0); @@ -2575,7 +2574,10 @@ static ALvoid InitContext(ALCcontext *Context) ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE); ATOMIC_INIT(&Context->Update, NULL); - ATOMIC_INIT(&Context->FreeList, NULL); + ATOMIC_INIT(&Context->FreeContextProps, NULL); + ATOMIC_INIT(&Context->FreeListenerProps, NULL); + ATOMIC_INIT(&Context->FreeVoiceProps, NULL); + ATOMIC_INIT(&Context->FreeEffectslotProps, NULL); Context->ExtensionList = alExtList; @@ -2605,8 +2607,10 @@ static void FreeContext(ALCcontext *context) { ALlistener *listener = context->Listener; struct ALeffectslotArray *auxslots; + struct ALeffectslotProps *eprops; struct ALlistenerProps *lprops; struct ALcontextProps *cprops; + struct ALvoiceProps *vprops; size_t count; ALsizei i; @@ -2617,8 +2621,9 @@ static void FreeContext(ALCcontext *context) TRACE("Freed unapplied context update %p\n", cprops); al_free(cprops); } + count = 0; - cprops = ATOMIC_LOAD(&context->FreeList, almemory_order_acquire); + cprops = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire); while(cprops) { struct ALcontextProps *next = ATOMIC_LOAD(&cprops->next, almemory_order_acquire); @@ -2645,6 +2650,17 @@ static void FreeContext(ALCcontext *context) } ResetUIntMap(&context->SourceMap); + count = 0; + eprops = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed); + while(eprops) + { + struct ALeffectslotProps *next = ATOMIC_LOAD(&eprops->next, almemory_order_relaxed); + if(eprops->State) ALeffectState_DecRef(eprops->State); + al_free(eprops); + eprops = next; + ++count; + } + TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s"); if(context->EffectSlotMap.size > 0) { WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size, @@ -2653,6 +2669,17 @@ static void FreeContext(ALCcontext *context) } ResetUIntMap(&context->EffectSlotMap); + count = 0; + vprops = ATOMIC_LOAD(&context->FreeVoiceProps, almemory_order_relaxed); + while(vprops) + { + struct ALvoiceProps *next = ATOMIC_LOAD(&vprops->next, almemory_order_relaxed); + al_free(vprops); + vprops = next; + ++count; + } + TRACE("Freed "SZFMT" voice property object%s\n", count, (count==1)?"":"s"); + for(i = 0;i < context->VoiceCount;i++) DeinitVoice(context->Voices[i]); al_free(context->Voices); @@ -2666,7 +2693,7 @@ static void FreeContext(ALCcontext *context) al_free(lprops); } count = 0; - lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire); + lprops = ATOMIC_LOAD(&context->FreeListenerProps, almemory_order_acquire); while(lprops) { struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_acquire); @@ -2878,7 +2905,6 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) for(;v < num_voices;v++) { ATOMIC_INIT(&voice->Update, NULL); - ATOMIC_INIT(&voice->FreeList, NULL); voice->Props = props; voices[v] = voice; @@ -3725,8 +3751,8 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin if(ALContext->DefaultSlot) { - if(InitializeEffect(device, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR) - UpdateEffectSlotProps(ALContext->DefaultSlot); + if(InitializeEffect(ALContext, ALContext->DefaultSlot, &DefaultEffect) == AL_NO_ERROR) + UpdateEffectSlotProps(ALContext->DefaultSlot, ALContext); else ERR("Failed to initialize the default effect\n"); } @@ -111,26 +111,7 @@ static HrtfDirectMixerFunc MixDirectHrtf = MixDirectHrtf_C; void DeinitVoice(ALvoice *voice) { - struct ALvoiceProps *props; - size_t count = 0; - - props = ATOMIC_EXCHANGE_PTR_SEQ(&voice->Update, NULL); - if(props) al_free(props); - - props = ATOMIC_EXCHANGE_PTR(&voice->FreeList, NULL, almemory_order_relaxed); - while(props) - { - struct ALvoiceProps *next; - next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); - al_free(props); - props = next; - ++count; - } - /* This is excessively spammy if it traces every voice destruction, so just - * warn if it was unexpectedly large. - */ - if(count > 3) - WARN("Freed "SZFMT" voice property objects\n", count); + al_free(ATOMIC_EXCHANGE_PTR_SEQ(&voice->Update, NULL)); } @@ -290,7 +271,7 @@ static bool CalcContextParams(ALCcontext *Context) Listener->Params.SourceDistanceModel = props->SourceDistanceModel; Listener->Params.DistanceModel = props->DistanceModel; - ATOMIC_REPLACE_HEAD(struct ALcontextProps*, &Context->FreeList, props); + ATOMIC_REPLACE_HEAD(struct ALcontextProps*, &Context->FreeContextProps, props); return true; } @@ -335,48 +316,54 @@ static bool CalcListenerParams(ALCcontext *Context) Listener->Params.Gain = props->Gain * Context->GainBoost; - ATOMIC_REPLACE_HEAD(struct ALlistenerProps*, &Listener->FreeList, props); + ATOMIC_REPLACE_HEAD(struct ALlistenerProps*, &Context->FreeListenerProps, props); return true; } -static bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context) +static bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context, bool force) { struct ALeffectslotProps *props; ALeffectState *state; props = ATOMIC_EXCHANGE_PTR(&slot->Update, NULL, almemory_order_acq_rel); - if(!props) return false; + if(!props && !force) return false; - slot->Params.Gain = props->Gain; - slot->Params.AuxSendAuto = props->AuxSendAuto; - slot->Params.EffectType = props->Type; - if(IsReverbEffect(slot->Params.EffectType)) - { - slot->Params.RoomRolloff = props->Props.Reverb.RoomRolloffFactor; - slot->Params.DecayTime = props->Props.Reverb.DecayTime; - slot->Params.DecayHFRatio = props->Props.Reverb.DecayHFRatio; - slot->Params.DecayHFLimit = props->Props.Reverb.DecayHFLimit; - slot->Params.AirAbsorptionGainHF = props->Props.Reverb.AirAbsorptionGainHF; - } - else + if(props) { - slot->Params.RoomRolloff = 0.0f; - slot->Params.DecayTime = 0.0f; - slot->Params.DecayHFRatio = 0.0f; - slot->Params.DecayHFLimit = AL_FALSE; - slot->Params.AirAbsorptionGainHF = 1.0f; - } + slot->Params.Gain = props->Gain; + slot->Params.AuxSendAuto = props->AuxSendAuto; + slot->Params.EffectType = props->Type; + slot->Params.EffectProps = props->Props; + if(IsReverbEffect(props->Type)) + { + slot->Params.RoomRolloff = props->Props.Reverb.RoomRolloffFactor; + slot->Params.DecayTime = props->Props.Reverb.DecayTime; + slot->Params.DecayHFRatio = props->Props.Reverb.DecayHFRatio; + slot->Params.DecayHFLimit = props->Props.Reverb.DecayHFLimit; + slot->Params.AirAbsorptionGainHF = props->Props.Reverb.AirAbsorptionGainHF; + } + else + { + slot->Params.RoomRolloff = 0.0f; + slot->Params.DecayTime = 0.0f; + slot->Params.DecayHFRatio = 0.0f; + slot->Params.DecayHFLimit = AL_FALSE; + slot->Params.AirAbsorptionGainHF = 1.0f; + } - /* Swap effect states. No need to play with the ref counts since they keep - * the same number of refs. - */ - state = props->State; - props->State = slot->Params.EffectState; - slot->Params.EffectState = state; + /* Swap effect states. No need to play with the ref counts since they + * keep the same number of refs. + */ + state = props->State; + props->State = slot->Params.EffectState; + slot->Params.EffectState = state; - V(state,update)(context, slot, &props->Props); + ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &context->FreeEffectslotProps, props); + } + else + state = slot->Params.EffectState; - ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &slot->FreeList, props); + V(state,update)(context, slot, &slot->Params.EffectProps); return true; } @@ -1455,7 +1442,7 @@ static void CalcSourceParams(ALvoice *voice, ALCcontext *context, bool force) FAM_SIZE(struct ALvoiceProps, Send, context->Device->NumAuxSends) ); - ATOMIC_REPLACE_HEAD(struct ALvoiceProps*, &voice->FreeList, props); + ATOMIC_REPLACE_HEAD(struct ALvoiceProps*, &context->FreeVoiceProps, props); } props = voice->Props; @@ -1486,10 +1473,10 @@ static void UpdateContextSources(ALCcontext *ctx, const struct ALeffectslotArray IncrementRef(&ctx->UpdateCount); if(!ATOMIC_LOAD(&ctx->HoldUpdates, almemory_order_acquire)) { - ALboolean cforce = CalcContextParams(ctx); - ALboolean force = CalcListenerParams(ctx) | cforce; + bool cforce = CalcContextParams(ctx); + bool force = CalcListenerParams(ctx) | cforce; for(i = 0;i < slots->count;i++) - force |= CalcEffectSlotParams(slots->slot[i], ctx); + force |= CalcEffectSlotParams(slots->slot[i], ctx, cforce); voice = ctx->Voices; voice_end = voice + ctx->VoiceCount; |