Fix alcontext.h

This commit is contained in:
Reece Wilson 2021-06-06 14:34:05 +01:00
parent 0300824dd4
commit 8bfc9832e8

View File

@ -1,70 +1,29 @@
#ifndef ALCONTEXT_H
#define ALCONTEXT_H
#ifndef ALC_CONTEXT_H
#define ALC_CONTEXT_H
#include <atomic>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <mutex>
#include <thread>
#include <stdint.h>
#include <utility>
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include "al/listener.h"
#include "almalloc.h"
#include "alnumeric.h"
#include "alu.h"
#include "atomic.h"
#include "inprogext.h"
#include "core/context.h"
#include "intrusive_ptr.h"
#include "threads.h"
#include "vector.h"
#include "voice.h"
struct ALeffect;
struct ALeffectslot;
struct ALeffectslotProps;
struct ALsource;
struct RingBuffer;
enum class DistanceModel {
InverseClamped = AL_INVERSE_DISTANCE_CLAMPED,
LinearClamped = AL_LINEAR_DISTANCE_CLAMPED,
ExponentClamped = AL_EXPONENT_DISTANCE_CLAMPED,
Inverse = AL_INVERSE_DISTANCE,
Linear = AL_LINEAR_DISTANCE,
Exponent = AL_EXPONENT_DISTANCE,
Disable = AL_NONE,
Default = InverseClamped
};
struct ALcontextProps {
float DopplerFactor;
float DopplerVelocity;
float SpeedOfSound;
bool SourceDistanceModel;
DistanceModel mDistanceModel;
std::atomic<ALcontextProps*> next;
DEF_NEWDEL(ALcontextProps)
};
struct VoiceChange {
Voice *mOldVoice{nullptr};
Voice *mVoice{nullptr};
ALuint mSourceID{0};
ALenum mState{0};
std::atomic<VoiceChange*> mNext{nullptr};
DEF_NEWDEL(VoiceChange)
};
using uint = unsigned int;
struct SourceSubList {
@ -98,14 +57,17 @@ struct EffectSlotSubList {
{ std::swap(FreeMask, rhs.FreeMask); std::swap(EffectSlots, rhs.EffectSlots); return *this; }
};
struct ALCcontext : public al::intrusive_ref<ALCcontext> {
al::vector<SourceSubList> mSourceList;
ALuint mNumSources{0};
std::mutex mSourceLock;
struct ALCcontext : public al::intrusive_ref<ALCcontext>, ContextBase {
const al::intrusive_ptr<ALCdevice> mALDevice;
al::vector<EffectSlotSubList> mEffectSlotList;
ALuint mNumEffectSlots{0u};
std::mutex mEffectSlotLock;
/* Wet buffers used by effect slots. */
al::vector<WetBufferPtr> mWetBuffers;
al::atomic_invflag mPropsDirty;
std::atomic<bool> mDeferUpdates{false};
std::mutex mPropLock;
std::atomic<ALenum> mLastError{AL_NO_ERROR};
@ -114,89 +76,27 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext> {
float mDopplerFactor{1.0f};
float mDopplerVelocity{1.0f};
float mSpeedOfSound{SPEEDOFSOUNDMETRESPERSEC};
float mSpeedOfSound{SpeedOfSoundMetersPerSec};
std::atomic_flag mPropsClean;
std::atomic<bool> mDeferUpdates{false};
std::mutex mPropLock;
/* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
* indicates if updates are currently happening).
*/
RefCount mUpdateCount{0u};
std::atomic<bool> mHoldUpdates{false};
float mGainBoost{1.0f};
std::atomic<ALcontextProps*> mUpdate{nullptr};
/* Linked lists of unused property containers, free to use for future
* updates.
*/
std::atomic<ALcontextProps*> mFreeContextProps{nullptr};
std::atomic<ALlistenerProps*> mFreeListenerProps{nullptr};
std::atomic<VoicePropsItem*> mFreeVoiceProps{nullptr};
std::atomic<ALeffectslotProps*> mFreeEffectslotProps{nullptr};
/* Asynchronous voice change actions are processed as a linked list of
* VoiceChange objects by the mixer, which is atomically appended to.
* However, to avoid allocating each object individually, they're allocated
* in clusters that are stored in a vector for easy automatic cleanup.
*/
using VoiceChangeCluster = std::unique_ptr<VoiceChange[]>;
al::vector<VoiceChangeCluster> mVoiceChangeClusters;
/* The voice change tail is the beginning of the "free" elements, up to and
* *excluding* the current. If tail==current, there's no free elements and
* new ones need to be allocated. The current voice change is the element
* last processed, and any after are pending.
*/
VoiceChange *mVoiceChangeTail{};
std::atomic<VoiceChange*> mCurrentVoiceChange{};
void allocVoiceChanges(size_t addcount);
using VoiceCluster = std::unique_ptr<Voice[]>;
al::vector<VoiceCluster> mVoiceClusters;
using VoiceArray = al::FlexArray<Voice*>;
std::atomic<VoiceArray*> mVoices{};
std::atomic<size_t> mActiveVoiceCount{};
void allocVoices(size_t addcount);
al::span<Voice*> getVoicesSpan() const noexcept
{
return {mVoices.load(std::memory_order_relaxed)->data(),
mActiveVoiceCount.load(std::memory_order_relaxed)};
}
al::span<Voice*> getVoicesSpanAcquired() const noexcept
{
return {mVoices.load(std::memory_order_acquire)->data(),
mActiveVoiceCount.load(std::memory_order_acquire)};
}
using ALeffectslotArray = al::FlexArray<ALeffectslot*>;
std::atomic<ALeffectslotArray*> mActiveAuxSlots{nullptr};
std::thread mEventThread;
al::semaphore mEventSem;
std::unique_ptr<RingBuffer> mAsyncEvents;
std::atomic<ALbitfieldSOFT> mEnabledEvts{0u};
std::mutex mEventCbLock;
ALEVENTPROCSOFT mEventCb{};
void *mEventParam{nullptr};
ALlistener mListener{};
al::vector<SourceSubList> mSourceList;
ALuint mNumSources{0};
std::mutex mSourceLock;
al::vector<EffectSlotSubList> mEffectSlotList;
ALuint mNumEffectSlots{0u};
std::mutex mEffectSlotLock;
/* Default effect slot */
std::unique_ptr<ALeffectslot> mDefaultSlot;
const al::intrusive_ptr<ALCdevice> mDevice;
const char *mExtensionList{nullptr};
ALlistener mListener{};
ALCcontext(al::intrusive_ptr<ALCdevice> device);
ALCcontext(const ALCcontext&) = delete;
@ -223,6 +123,24 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext> {
void setError(ALenum errorCode, const char *msg, ...);
/* Process-wide current context */
static std::atomic<ALCcontext*> sGlobalContext;
/* Thread-local current context. */
static thread_local ALCcontext *sLocalContext;
/* Thread-local context handling. This handles attempting to release the
* context which may have been left current when the thread is destroyed.
*/
class ThreadCtx {
public:
~ThreadCtx();
void set(ALCcontext *ctx) const noexcept { sLocalContext = ctx; }
};
static thread_local ThreadCtx sThreadContext;
/* Default effect that applies to sources that don't have an effect on send 0. */
static ALeffect sDefaultEffect;
DEF_NEWDEL(ALCcontext)
};
@ -241,4 +159,4 @@ void UpdateContextProps(ALCcontext *context);
extern bool TrapALError;
#endif /* ALCONTEXT_H */
#endif /* ALC_CONTEXT_H */