alcontext.h 5.4 KB

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