diff options
-rw-r--r-- | al/auxeffectslot.cpp | 110 | ||||
-rw-r--r-- | al/effect.cpp | 86 | ||||
-rw-r--r-- | al/error.cpp | 3 | ||||
-rw-r--r-- | al/filter.cpp | 81 | ||||
-rw-r--r-- | al/state.cpp | 20 |
5 files changed, 156 insertions, 144 deletions
diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 06627bc8..f2801329 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -27,6 +27,7 @@ #include <iterator> #include <memory> #include <mutex> +#include <numeric> #include <thread> #include "AL/al.h" @@ -158,58 +159,52 @@ void RemoveActiveEffectSlots(const ALuint *slotids, size_t count, ALCcontext *co } -ALeffectslot *AllocEffectSlot(ALCcontext *context) +bool EnsureEffectSlots(ALCcontext *context, size_t needed) { - ALCdevice *device{context->mDevice.get()}; - std::lock_guard<std::mutex> _{context->mEffectSlotLock}; - if(context->mNumEffectSlots >= device->AuxiliaryEffectSlotMax) - { - context->setError(AL_OUT_OF_MEMORY, "Exceeding %u effect slot limit", - device->AuxiliaryEffectSlotMax); - return nullptr; - } - auto sublist = std::find_if(context->mEffectSlotList.begin(), context->mEffectSlotList.end(), - [](const EffectSlotSubList &entry) noexcept -> bool - { return entry.FreeMask != 0; } - ); - auto lidx = static_cast<ALuint>(std::distance(context->mEffectSlotList.begin(), sublist)); - ALuint slidx; - if LIKELY(sublist != context->mEffectSlotList.end()) - slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask)); - else + size_t count{std::accumulate(context->mEffectSlotList.cbegin(), + context->mEffectSlotList.cend(), size_t{0}, + [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t + { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); } + )}; + + while(needed > count) { - /* Don't allocate so many list entries that the 32-bit ID could - * overflow... - */ if UNLIKELY(context->mEffectSlotList.size() >= 1<<25) - { - context->setError(AL_OUT_OF_MEMORY, "Too many effect slots allocated"); - return nullptr; - } - context->mEffectSlotList.emplace_back(); - sublist = context->mEffectSlotList.end() - 1; + return false; + context->mEffectSlotList.emplace_back(); + auto sublist = context->mEffectSlotList.end() - 1; sublist->FreeMask = ~0_u64; - sublist->EffectSlots = static_cast<ALeffectslot*>(al_calloc(16, sizeof(ALeffectslot)*64)); + sublist->EffectSlots = static_cast<ALeffectslot*>( + al_calloc(alignof(ALeffectslot), sizeof(ALeffectslot)*64)); if UNLIKELY(!sublist->EffectSlots) { context->mEffectSlotList.pop_back(); - context->setError(AL_OUT_OF_MEMORY, "Failed to allocate effect slot batch"); - return nullptr; + return false; } - - slidx = 0; + count += 64; } + return true; +} + +ALeffectslot *AllocEffectSlot(ALCcontext *context) +{ + auto sublist = std::find_if(context->mEffectSlotList.begin(), context->mEffectSlotList.end(), + [](const EffectSlotSubList &entry) noexcept -> bool + { return entry.FreeMask != 0; } + ); + + auto lidx = static_cast<ALuint>(std::distance(context->mEffectSlotList.begin(), sublist)); + auto slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask)); ALeffectslot *slot{::new (sublist->EffectSlots + slidx) ALeffectslot{}}; - ALenum err{InitEffectSlot(slot)}; - if(err != AL_NO_ERROR) + if(ALenum err{InitEffectSlot(slot)}) { al::destroy_at(slot); context->setError(err, "Effect slot object initialization failed"); return nullptr; } - aluInitEffectPanning(slot, device); + aluInitEffectPanning(slot, context->mDevice.get()); /* Add 1 to avoid source ID 0. */ slot->id = ((lidx<<6) | slidx) + 1; @@ -224,7 +219,7 @@ void FreeEffectSlot(ALCcontext *context, ALeffectslot *slot) { const ALuint id{slot->id - 1}; const size_t lidx{id >> 6}; - const size_t slidx{id & 0x3f}; + const ALuint slidx{id & 0x3f}; al::destroy_at(slot); @@ -262,6 +257,21 @@ START_API_FUNC SETERR_RETURN(context, AL_INVALID_VALUE,, "Generating %d effect slots", n); if(n == 0) return; + std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock}; + ALCdevice *device{context->mDevice.get()}; + if(static_cast<ALuint>(n) > device->AuxiliaryEffectSlotMax-context->mNumEffectSlots) + { + context->setError(AL_OUT_OF_MEMORY, "Exceeding %u effect slot limit (%u + %d)", + device->AuxiliaryEffectSlotMax, context->mNumEffectSlots, n); + return; + } + if(!EnsureEffectSlots(context.get(), static_cast<ALuint>(n))) + { + context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d effectslot%s", n, + (n==1) ? "" : "s"); + return; + } + if(n == 1) { ALeffectslot *slot{AllocEffectSlot(context.get())}; @@ -270,27 +280,21 @@ START_API_FUNC } else { - auto tempids = al::vector<ALuint>(static_cast<ALuint>(n)); - auto alloc_end = std::find_if_not(tempids.begin(), tempids.end(), - [&context](ALuint &id) -> bool + al::vector<ALuint> ids; + ids.reserve(static_cast<ALuint>(n)); + do { + ALeffectslot *slot{AllocEffectSlot(context.get())}; + if(!slot) { - ALeffectslot *slot{AllocEffectSlot(context.get())}; - if(!slot) return false; - id = slot->id; - return true; + slotlock.unlock(); + alDeleteAuxiliaryEffectSlots(static_cast<ALsizei>(ids.size()), ids.data()); + return; } - ); - if(alloc_end != tempids.end()) - { - auto count = static_cast<ALsizei>(std::distance(tempids.begin(), alloc_end)); - alDeleteAuxiliaryEffectSlots(count, tempids.data()); - return; - } - - std::copy(tempids.cbegin(), tempids.cend(), effectslots); + ids.emplace_back(slot->id); + } while(--n); + std::copy(ids.cbegin(), ids.cend(), effectslots); } - std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock}; AddActiveEffectSlots(effectslots, static_cast<ALuint>(n), context.get()); } END_API_FUNC diff --git a/al/effect.cpp b/al/effect.cpp index 3836a5e4..c27fc8df 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -29,6 +29,7 @@ #include <memory> #include <mutex> #include <new> +#include <numeric> #include <utility> #include "AL/al.h" @@ -136,42 +137,41 @@ void InitEffectParams(ALeffect *effect, ALenum type) effect->type = type; } -ALeffect *AllocEffect(ALCcontext *context) +bool EnsureEffects(ALCdevice *device, size_t needed) { - ALCdevice *device{context->mDevice.get()}; - std::lock_guard<std::mutex> _{device->EffectLock}; - auto sublist = std::find_if(device->EffectList.begin(), device->EffectList.end(), - [](const EffectSubList &entry) noexcept -> bool - { return entry.FreeMask != 0; } - ); + size_t count{std::accumulate(device->EffectList.cbegin(), device->EffectList.cend(), size_t{0}, + [](size_t cur, const EffectSubList &sublist) noexcept -> size_t + { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); } + )}; - auto lidx = static_cast<ALsizei>(std::distance(device->EffectList.begin(), sublist)); - ALsizei slidx{0}; - if LIKELY(sublist != device->EffectList.end()) - slidx = CTZ64(sublist->FreeMask); - else + while(needed > count) { - /* Don't allocate so many list entries that the 32-bit ID could - * overflow... - */ if UNLIKELY(device->EffectList.size() >= 1<<25) - { - context->setError(AL_OUT_OF_MEMORY, "Too many effects allocated"); - return nullptr; - } + return false; + device->EffectList.emplace_back(); - sublist = device->EffectList.end() - 1; + auto sublist = device->EffectList.end() - 1; sublist->FreeMask = ~0_u64; - sublist->Effects = static_cast<ALeffect*>(al_calloc(16, sizeof(ALeffect)*64)); + sublist->Effects = static_cast<ALeffect*>(al_calloc(alignof(ALeffect), sizeof(ALeffect)*64)); if UNLIKELY(!sublist->Effects) { device->EffectList.pop_back(); - context->setError(AL_OUT_OF_MEMORY, "Failed to allocate effect batch"); - return nullptr; + return false; } - - slidx = 0; + count += 64; } + return true; +} + +ALeffect *AllocEffect(ALCdevice *device) +{ + auto sublist = std::find_if(device->EffectList.begin(), device->EffectList.end(), + [](const EffectSubList &entry) noexcept -> bool + { return entry.FreeMask != 0; } + ); + + auto lidx = static_cast<ALuint>(std::distance(device->EffectList.begin(), sublist)); + auto slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask)); ALeffect *effect{::new (sublist->Effects + slidx) ALeffect{}}; InitEffectParams(effect, AL_EFFECT_NULL); @@ -186,9 +186,9 @@ ALeffect *AllocEffect(ALCcontext *context) void FreeEffect(ALCdevice *device, ALeffect *effect) { - ALuint id = effect->id - 1; - ALsizei lidx = id >> 6; - ALsizei slidx = id & 0x3f; + const ALuint id{effect->id - 1}; + const size_t lidx{id >> 6}; + const ALuint slidx{id & 0x3f}; al::destroy_at(effect); @@ -197,8 +197,8 @@ void FreeEffect(ALCdevice *device, ALeffect *effect) inline ALeffect *LookupEffect(ALCdevice *device, ALuint id) { - ALuint lidx = (id-1) >> 6; - ALsizei slidx = (id-1) & 0x3f; + const size_t lidx{(id-1) >> 6}; + const ALuint slidx{(id-1) & 0x3f}; if UNLIKELY(lidx >= device->EffectList.size()) return nullptr; @@ -220,11 +220,19 @@ START_API_FUNC context->setError(AL_INVALID_VALUE, "Generating %d effects", n); if UNLIKELY(n <= 0) return; + ALCdevice *device{context->mDevice.get()}; + std::lock_guard<std::mutex> _{device->EffectLock}; + if(!EnsureEffects(device, static_cast<ALuint>(n))) + { + context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d effect%s", n, (n==1)?"":"s"); + return; + } + if LIKELY(n == 1) { /* Special handling for the easy and normal case. */ - ALeffect *effect = AllocEffect(context.get()); - if(effect) effects[0] = effect->id; + ALeffect *effect{AllocEffect(device)}; + effects[0] = effect->id; } else { @@ -232,18 +240,12 @@ START_API_FUNC * modifying the user storage in case of failure. */ al::vector<ALuint> ids; - ids.reserve(n); + ids.reserve(static_cast<ALuint>(n)); do { - ALeffect *effect = AllocEffect(context.get()); - if(!effect) - { - alDeleteEffects(static_cast<ALsizei>(ids.size()), ids.data()); - return; - } - + ALeffect *effect{AllocEffect(device)}; ids.emplace_back(effect->id); } while(--n); - std::copy(ids.begin(), ids.end(), effects); + std::copy(ids.cbegin(), ids.cend(), effects); } } END_API_FUNC @@ -722,7 +724,7 @@ void LoadReverbPreset(const char *name, ALeffect *effect) effect->Props.Reverb.HFReference = props->flHFReference; effect->Props.Reverb.LFReference = props->flLFReference; effect->Props.Reverb.RoomRolloffFactor = props->flRoomRolloffFactor; - effect->Props.Reverb.DecayHFLimit = props->iDecayHFLimit; + effect->Props.Reverb.DecayHFLimit = props->iDecayHFLimit ? AL_TRUE : AL_FALSE; return; } diff --git a/al/error.cpp b/al/error.cpp index a7080493..f3e2dbb3 100644 --- a/al/error.cpp +++ b/al/error.cpp @@ -86,7 +86,8 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...) std::lock_guard<std::mutex> _{mEventCbLock}; ALbitfieldSOFT enabledevts{mEnabledEvts.load(std::memory_order_relaxed)}; if((enabledevts&EventType_Error) && mEventCb) - (*mEventCb)(AL_EVENT_TYPE_ERROR_SOFT, 0, errorCode, msglen, msg, mEventParam); + (*mEventCb)(AL_EVENT_TYPE_ERROR_SOFT, 0, static_cast<ALuint>(errorCode), msglen, msg, + mEventParam); } } diff --git a/al/filter.cpp b/al/filter.cpp index abb2795b..920b4ca1 100644 --- a/al/filter.cpp +++ b/al/filter.cpp @@ -28,6 +28,7 @@ #include <memory> #include <mutex> #include <new> +#include <numeric> #include "AL/al.h" #include "AL/alc.h" @@ -278,42 +279,42 @@ void InitFilterParams(ALfilter *filter, ALenum type) filter->type = type; } -ALfilter *AllocFilter(ALCcontext *context) +bool EnsureFilters(ALCdevice *device, size_t needed) { - ALCdevice *device{context->mDevice.get()}; - std::lock_guard<std::mutex> _{device->FilterLock}; - auto sublist = std::find_if(device->FilterList.begin(), device->FilterList.end(), - [](const FilterSubList &entry) noexcept -> bool - { return entry.FreeMask != 0; } - ); + size_t count{std::accumulate(device->FilterList.cbegin(), device->FilterList.cend(), size_t{0}, + [](size_t cur, const FilterSubList &sublist) noexcept -> size_t + { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); } + )}; - auto lidx = static_cast<ALsizei>(std::distance(device->FilterList.begin(), sublist)); - ALsizei slidx{0}; - if LIKELY(sublist != device->FilterList.end()) - slidx = CTZ64(sublist->FreeMask); - else + while(needed > count) { - /* Don't allocate so many list entries that the 32-bit ID could - * overflow... - */ if UNLIKELY(device->FilterList.size() >= 1<<25) - { - context->setError(AL_OUT_OF_MEMORY, "Too many filters allocated"); - return nullptr; - } + return false; + device->FilterList.emplace_back(); - sublist = device->FilterList.end() - 1; + auto sublist = device->FilterList.end() - 1; sublist->FreeMask = ~0_u64; - sublist->Filters = static_cast<ALfilter*>(al_calloc(16, sizeof(ALfilter)*64)); + sublist->Filters = static_cast<ALfilter*>(al_calloc(alignof(ALfilter), sizeof(ALfilter)*64)); if UNLIKELY(!sublist->Filters) { device->FilterList.pop_back(); - context->setError(AL_OUT_OF_MEMORY, "Failed to allocate filter batch"); - return nullptr; + return false; } - - slidx = 0; + count += 64; } + return true; +} + + +ALfilter *AllocFilter(ALCdevice *device) +{ + auto sublist = std::find_if(device->FilterList.begin(), device->FilterList.end(), + [](const FilterSubList &entry) noexcept -> bool + { return entry.FreeMask != 0; } + ); + + auto lidx = static_cast<ALuint>(std::distance(device->FilterList.begin(), sublist)); + auto slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask)); ALfilter *filter{::new (sublist->Filters + slidx) ALfilter{}}; InitFilterParams(filter, AL_FILTER_NULL); @@ -328,9 +329,9 @@ ALfilter *AllocFilter(ALCcontext *context) void FreeFilter(ALCdevice *device, ALfilter *filter) { - ALuint id = filter->id - 1; - ALsizei lidx = id >> 6; - ALsizei slidx = id & 0x3f; + const ALuint id{filter->id - 1}; + const size_t lidx{id >> 6}; + const ALuint slidx{id & 0x3f}; al::destroy_at(filter); @@ -340,8 +341,8 @@ void FreeFilter(ALCdevice *device, ALfilter *filter) inline ALfilter *LookupFilter(ALCdevice *device, ALuint id) { - ALuint lidx = (id-1) >> 6; - ALsizei slidx = (id-1) & 0x3f; + const size_t lidx{(id-1) >> 6}; + const ALuint slidx{(id-1) & 0x3f}; if UNLIKELY(lidx >= device->FilterList.size()) return nullptr; @@ -363,10 +364,18 @@ START_API_FUNC context->setError(AL_INVALID_VALUE, "Generating %d filters", n); if UNLIKELY(n <= 0) return; + ALCdevice *device{context->mDevice.get()}; + std::lock_guard<std::mutex> _{device->EffectLock}; + if(!EnsureFilters(device, static_cast<ALuint>(n))) + { + context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d filter%s", n, (n==1)?"":"s"); + return; + } + if LIKELY(n == 1) { /* Special handling for the easy and normal case. */ - ALfilter *filter = AllocFilter(context.get()); + ALfilter *filter{AllocFilter(device)}; if(filter) filters[0] = filter->id; } else @@ -375,15 +384,9 @@ START_API_FUNC * modifying the user storage in case of failure. */ al::vector<ALuint> ids; - ids.reserve(n); + ids.reserve(static_cast<ALuint>(n)); do { - ALfilter *filter = AllocFilter(context.get()); - if(!filter) - { - alDeleteFilters(static_cast<ALsizei>(ids.size()), ids.data()); - return; - } - + ALfilter *filter{AllocFilter(device)}; ids.emplace_back(filter->id); } while(--n); std::copy(ids.begin(), ids.end(), filters); diff --git a/al/state.cpp b/al/state.cpp index cc5d8bac..74fb3b55 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -218,11 +218,11 @@ START_API_FUNC switch(pname) { case AL_DOPPLER_FACTOR: - value = static_cast<ALdouble>(context->mDopplerFactor); + value = context->mDopplerFactor; break; case AL_DOPPLER_VELOCITY: - value = static_cast<ALdouble>(context->mDopplerVelocity); + value = context->mDopplerVelocity; break; case AL_DISTANCE_MODEL: @@ -230,7 +230,7 @@ START_API_FUNC break; case AL_SPEED_OF_SOUND: - value = static_cast<ALdouble>(context->mSpeedOfSound); + value = context->mSpeedOfSound; break; case AL_DEFERRED_UPDATES_SOFT: @@ -239,7 +239,7 @@ START_API_FUNC break; case AL_GAIN_LIMIT_SOFT: - value = static_cast<ALdouble>GAIN_MIX_MAX/context->mGainBoost; + value = ALdouble{GAIN_MIX_MAX}/context->mGainBoost; break; case AL_NUM_RESAMPLERS_SOFT: @@ -337,7 +337,7 @@ START_API_FUNC case AL_DEFERRED_UPDATES_SOFT: if(context->mDeferUpdates.load(std::memory_order_acquire)) - value = static_cast<ALint>(AL_TRUE); + value = AL_TRUE; break; case AL_GAIN_LIMIT_SOFT: @@ -710,14 +710,16 @@ START_API_FUNC if((context->mEnabledEvts.load(std::memory_order_relaxed)&EventType_Deprecated)) { - static constexpr ALCchar msg[] = - "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound"; - const ALsizei msglen = static_cast<ALsizei>(strlen(msg)); std::lock_guard<std::mutex> _{context->mEventCbLock}; ALbitfieldSOFT enabledevts{context->mEnabledEvts.load(std::memory_order_relaxed)}; if((enabledevts&EventType_Deprecated) && context->mEventCb) + { + static constexpr ALCchar msg[] = + "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound"; + const ALsizei msglen{sizeof(msg)-1}; (*context->mEventCb)(AL_EVENT_TYPE_DEPRECATED_SOFT, 0, 0, msglen, msg, - context->mEventParam); + context->mEventParam); + } } if(!(value >= 0.0f && std::isfinite(value))) |