15 #include "al/listener.h"
17 #include "alnumeric.h"
20 #include "inprogext.h"
21 #include "intrusive_ptr.h"
27 struct ALeffectslotProps
;
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
,
41 Default
= InverseClamped
45 struct ALcontextProps
{
46 ALfloat DopplerFactor
;
47 ALfloat DopplerVelocity
;
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; }
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; }
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
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;
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.
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__); \
186 using ContextRef
= al::intrusive_ptr
<ALCcontext
>;
188 ContextRef
GetContextRef(void);
190 void UpdateContextProps(ALCcontext
*context
);
193 extern bool TrapALError
;
195 #endif /* ALCONTEXT_H */