Fix alcontext.h
This commit is contained in:
parent
0300824dd4
commit
8bfc9832e8
176
alc/alcontext.h
176
alc/alcontext.h
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user