15 #include "al/listener.h"
17 #include "alnumeric.h"
20 #include "inprogext.h"
21 #include "intrusive_ptr.h"
28 struct ALeffectslotProps
;
33 enum class DistanceModel
{
34 InverseClamped
= AL_INVERSE_DISTANCE_CLAMPED
,
35 LinearClamped
= AL_LINEAR_DISTANCE_CLAMPED
,
36 ExponentClamped
= AL_EXPONENT_DISTANCE_CLAMPED
,
37 Inverse
= AL_INVERSE_DISTANCE
,
38 Linear
= AL_LINEAR_DISTANCE
,
39 Exponent
= AL_EXPONENT_DISTANCE
,
42 Default
= InverseClamped
46 struct ALcontextProps
{
47 ALfloat DopplerFactor
;
48 ALfloat DopplerVelocity
;
50 ALboolean SourceDistanceModel
;
51 DistanceModel mDistanceModel
;
53 std::atomic
<ALcontextProps
*> next
;
55 DEF_NEWDEL(ALcontextProps
)
59 struct SourceSubList
{
60 uint64_t FreeMask
{~0_u64
};
61 ALsource
*Sources
{nullptr}; /* 64 */
63 SourceSubList() noexcept
= default;
64 SourceSubList(const SourceSubList
&) = delete;
65 SourceSubList(SourceSubList
&& rhs
) noexcept
: FreeMask
{rhs
.FreeMask
}, Sources
{rhs
.Sources
}
66 { rhs
.FreeMask
= ~0_u64
; rhs
.Sources
= nullptr; }
69 SourceSubList
& operator=(const SourceSubList
&) = delete;
70 SourceSubList
& operator=(SourceSubList
&& rhs
) noexcept
71 { std::swap(FreeMask
, rhs
.FreeMask
); std::swap(Sources
, rhs
.Sources
); return *this; }
74 struct EffectSlotSubList
{
75 uint64_t FreeMask
{~0_u64
};
76 ALeffectslot
*EffectSlots
{nullptr}; /* 64 */
78 EffectSlotSubList() noexcept
= default;
79 EffectSlotSubList(const EffectSlotSubList
&) = delete;
80 EffectSlotSubList(EffectSlotSubList
&& rhs
) noexcept
81 : FreeMask
{rhs
.FreeMask
}, EffectSlots
{rhs
.EffectSlots
}
82 { rhs
.FreeMask
= ~0_u64
; rhs
.EffectSlots
= nullptr; }
85 EffectSlotSubList
& operator=(const EffectSlotSubList
&) = delete;
86 EffectSlotSubList
& operator=(EffectSlotSubList
&& rhs
) noexcept
87 { std::swap(FreeMask
, rhs
.FreeMask
); std::swap(EffectSlots
, rhs
.EffectSlots
); return *this; }
90 struct ALCcontext
: public al::intrusive_ref
<ALCcontext
> {
91 al::vector
<SourceSubList
> mSourceList
;
92 ALuint mNumSources
{0};
93 std::mutex mSourceLock
;
95 al::vector
<EffectSlotSubList
> mEffectSlotList
;
96 ALuint mNumEffectSlots
{0u};
97 std::mutex mEffectSlotLock
;
99 std::atomic
<ALenum
> mLastError
{AL_NO_ERROR
};
101 DistanceModel mDistanceModel
{DistanceModel::Default
};
102 ALboolean mSourceDistanceModel
{AL_FALSE
};
104 ALfloat mDopplerFactor
{1.0f
};
105 ALfloat mDopplerVelocity
{1.0f
};
106 ALfloat mSpeedOfSound
{SPEEDOFSOUNDMETRESPERSEC
};
108 std::atomic_flag mPropsClean
;
109 std::atomic
<bool> mDeferUpdates
{false};
111 std::mutex mPropLock
;
113 /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
114 * indicates if updates are currently happening).
116 RefCount mUpdateCount
{0u};
117 std::atomic
<bool> mHoldUpdates
{false};
119 ALfloat mGainBoost
{1.0f
};
121 std::atomic
<ALcontextProps
*> mUpdate
{nullptr};
123 /* Linked lists of unused property containers, free to use for future
126 std::atomic
<ALcontextProps
*> mFreeContextProps
{nullptr};
127 std::atomic
<ALlistenerProps
*> mFreeListenerProps
{nullptr};
128 std::atomic
<ALvoiceProps
*> mFreeVoiceProps
{nullptr};
129 std::atomic
<ALeffectslotProps
*> mFreeEffectslotProps
{nullptr};
131 al::vector
<ALvoice
> mVoices
;
133 using ALeffectslotArray
= al::FlexArray
<ALeffectslot
*>;
134 std::atomic
<ALeffectslotArray
*> mActiveAuxSlots
{nullptr};
136 std::thread mEventThread
;
137 al::semaphore mEventSem
;
138 std::unique_ptr
<RingBuffer
> mAsyncEvents
;
139 std::atomic
<ALbitfieldSOFT
> mEnabledEvts
{0u};
140 std::mutex mEventCbLock
;
141 ALEVENTPROCSOFT mEventCb
{};
142 void *mEventParam
{nullptr};
144 /* Default effect slot */
145 std::unique_ptr
<ALeffectslot
> mDefaultSlot
;
147 const al::intrusive_ptr
<ALCdevice
> mDevice
;
148 const ALCchar
*mExtensionList
{nullptr};
150 ALlistener mListener
{};
153 ALCcontext(al::intrusive_ptr
<ALCdevice
> device
);
154 ALCcontext(const ALCcontext
&) = delete;
155 ALCcontext
& operator=(const ALCcontext
&) = delete;
160 * Removes the context from its device and removes it from being current on
161 * the running thread or globally. Returns true if other contexts still
162 * exist on the device.
167 * Defers/suspends updates for the given context's listener and sources.
168 * This does *NOT* stop mixing, but rather prevents certain property
169 * changes from taking effect.
171 void deferUpdates() noexcept
{ mDeferUpdates
.store(true); }
173 /** Resumes update processing after being deferred. */
174 void processUpdates();
176 void setError(ALenum errorCode
, const char *msg
, ...) DECL_FORMAT(printf
, 3, 4);
178 DEF_NEWDEL(ALCcontext
)
181 #define SETERR_RETURN(ctx, err, retval, ...) do { \
182 (ctx)->setError((err), __VA_ARGS__); \
187 using ContextRef
= al::intrusive_ptr
<ALCcontext
>;
189 ContextRef
GetContextRef(void);
191 void UpdateContextProps(ALCcontext
*context
);
194 extern bool TrapALError
;
196 #endif /* ALCONTEXT_H */