Don't inline the utf8 converters
[openal-soft.git] / alc / alcontext.h
blobdd6226548dafc3d73896bbff0a71d8dda810a8d3
1 #ifndef ALCONTEXT_H
2 #define ALCONTEXT_H
4 #include <atomic>
5 #include <cstddef>
6 #include <cstdint>
7 #include <memory>
8 #include <mutex>
9 #include <thread>
10 #include <utility>
12 #include "AL/al.h"
13 #include "AL/alc.h"
15 #include "al/listener.h"
16 #include "almalloc.h"
17 #include "alnumeric.h"
18 #include "alu.h"
19 #include "atomic.h"
20 #include "inprogext.h"
21 #include "intrusive_ptr.h"
22 #include "logging.h"
23 #include "threads.h"
24 #include "vector.h"
26 struct ALeffectslot;
27 struct ALeffectslotProps;
28 struct ALsource;
29 struct RingBuffer;
32 enum class DistanceModel {
33 InverseClamped = AL_INVERSE_DISTANCE_CLAMPED,
34 LinearClamped = AL_LINEAR_DISTANCE_CLAMPED,
35 ExponentClamped = AL_EXPONENT_DISTANCE_CLAMPED,
36 Inverse = AL_INVERSE_DISTANCE,
37 Linear = AL_LINEAR_DISTANCE,
38 Exponent = AL_EXPONENT_DISTANCE,
39 Disable = AL_NONE,
41 Default = InverseClamped
45 struct ALcontextProps {
46 ALfloat DopplerFactor;
47 ALfloat DopplerVelocity;
48 ALfloat SpeedOfSound;
49 ALboolean SourceDistanceModel;
50 DistanceModel mDistanceModel;
52 std::atomic<ALcontextProps*> next;
54 DEF_NEWDEL(ALcontextProps)
58 struct SourceSubList {
59 uint64_t FreeMask{~0_u64};
60 ALsource *Sources{nullptr}; /* 64 */
62 SourceSubList() noexcept = default;
63 SourceSubList(const SourceSubList&) = delete;
64 SourceSubList(SourceSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Sources{rhs.Sources}
65 { rhs.FreeMask = ~0_u64; rhs.Sources = nullptr; }
66 ~SourceSubList();
68 SourceSubList& operator=(const SourceSubList&) = delete;
69 SourceSubList& operator=(SourceSubList&& rhs) noexcept
70 { std::swap(FreeMask, rhs.FreeMask); std::swap(Sources, rhs.Sources); return *this; }
73 struct EffectSlotSubList {
74 uint64_t FreeMask{~0_u64};
75 ALeffectslot *EffectSlots{nullptr}; /* 64 */
77 EffectSlotSubList() noexcept = default;
78 EffectSlotSubList(const EffectSlotSubList&) = delete;
79 EffectSlotSubList(EffectSlotSubList&& rhs) noexcept
80 : FreeMask{rhs.FreeMask}, EffectSlots{rhs.EffectSlots}
81 { rhs.FreeMask = ~0_u64; rhs.EffectSlots = nullptr; }
82 ~EffectSlotSubList();
84 EffectSlotSubList& operator=(const EffectSlotSubList&) = delete;
85 EffectSlotSubList& operator=(EffectSlotSubList&& rhs) noexcept
86 { std::swap(FreeMask, rhs.FreeMask); std::swap(EffectSlots, rhs.EffectSlots); return *this; }
89 struct ALCcontext : public al::intrusive_ref<ALCcontext> {
90 al::vector<SourceSubList> mSourceList;
91 ALuint mNumSources{0};
92 std::mutex mSourceLock;
94 al::vector<EffectSlotSubList> mEffectSlotList;
95 ALuint mNumEffectSlots{0u};
96 std::mutex mEffectSlotLock;
98 std::atomic<ALenum> mLastError{AL_NO_ERROR};
100 DistanceModel mDistanceModel{DistanceModel::Default};
101 ALboolean mSourceDistanceModel{AL_FALSE};
103 ALfloat mDopplerFactor{1.0f};
104 ALfloat mDopplerVelocity{1.0f};
105 ALfloat mSpeedOfSound{SPEEDOFSOUNDMETRESPERSEC};
107 std::atomic_flag mPropsClean;
108 std::atomic<bool> mDeferUpdates{false};
110 std::mutex mPropLock;
112 /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
113 * indicates if updates are currently happening).
115 RefCount mUpdateCount{0u};
116 std::atomic<bool> mHoldUpdates{false};
118 ALfloat mGainBoost{1.0f};
120 std::atomic<ALcontextProps*> mUpdate{nullptr};
122 /* Linked lists of unused property containers, free to use for future
123 * updates.
125 std::atomic<ALcontextProps*> mFreeContextProps{nullptr};
126 std::atomic<ALlistenerProps*> mFreeListenerProps{nullptr};
127 std::atomic<ALvoiceProps*> mFreeVoiceProps{nullptr};
128 std::atomic<ALeffectslotProps*> mFreeEffectslotProps{nullptr};
130 al::vector<ALvoice> mVoices;
132 using ALeffectslotArray = al::FlexArray<ALeffectslot*>;
133 std::atomic<ALeffectslotArray*> mActiveAuxSlots{nullptr};
135 std::thread mEventThread;
136 al::semaphore mEventSem;
137 std::unique_ptr<RingBuffer> mAsyncEvents;
138 std::atomic<ALbitfieldSOFT> mEnabledEvts{0u};
139 std::mutex mEventCbLock;
140 ALEVENTPROCSOFT mEventCb{};
141 void *mEventParam{nullptr};
143 /* Default effect slot */
144 std::unique_ptr<ALeffectslot> mDefaultSlot;
146 const al::intrusive_ptr<ALCdevice> mDevice;
147 const ALCchar *mExtensionList{nullptr};
149 ALlistener mListener{};
152 ALCcontext(al::intrusive_ptr<ALCdevice> device);
153 ALCcontext(const ALCcontext&) = delete;
154 ALCcontext& operator=(const ALCcontext&) = delete;
155 ~ALCcontext();
157 void init();
159 * Removes the context from its device and removes it from being current on
160 * the running thread or globally. Returns true if other contexts still
161 * exist on the device.
163 bool deinit();
166 * Defers/suspends updates for the given context's listener and sources.
167 * This does *NOT* stop mixing, but rather prevents certain property
168 * changes from taking effect.
170 void deferUpdates() noexcept { mDeferUpdates.store(true); }
172 /** Resumes update processing after being deferred. */
173 void processUpdates();
175 void setError(ALenum errorCode, const char *msg, ...) DECL_FORMAT(printf, 3, 4);
177 DEF_NEWDEL(ALCcontext)
180 #define SETERR_RETURN(ctx, err, retval, ...) do { \
181 (ctx)->setError((err), __VA_ARGS__); \
182 return retval; \
183 } while(0)
186 using ContextRef = al::intrusive_ptr<ALCcontext>;
188 ContextRef GetContextRef(void);
190 void UpdateContextProps(ALCcontext *context);
193 extern bool TrapALError;
195 #endif /* ALCONTEXT_H */