🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
5.7 KiB

  1. #ifndef ALCONTEXT_H
  2. #define ALCONTEXT_H
  3. #include <mutex>
  4. #include <atomic>
  5. #include <memory>
  6. #include <thread>
  7. #include "AL/al.h"
  8. #include "AL/alc.h"
  9. #include "AL/alext.h"
  10. #include "inprogext.h"
  11. #include "atomic.h"
  12. #include "vector.h"
  13. #include "threads.h"
  14. #include "almalloc.h"
  15. #include "alnumeric.h"
  16. #include "alListener.h"
  17. struct ALsource;
  18. struct ALeffectslot;
  19. struct ALcontextProps;
  20. struct ALlistenerProps;
  21. struct ALvoiceProps;
  22. struct ALeffectslotProps;
  23. struct ALvoice;
  24. struct RingBuffer;
  25. enum class DistanceModel {
  26. InverseClamped = AL_INVERSE_DISTANCE_CLAMPED,
  27. LinearClamped = AL_LINEAR_DISTANCE_CLAMPED,
  28. ExponentClamped = AL_EXPONENT_DISTANCE_CLAMPED,
  29. Inverse = AL_INVERSE_DISTANCE,
  30. Linear = AL_LINEAR_DISTANCE,
  31. Exponent = AL_EXPONENT_DISTANCE,
  32. Disable = AL_NONE,
  33. Default = InverseClamped
  34. };
  35. struct SourceSubList {
  36. uint64_t FreeMask{~0_u64};
  37. ALsource *Sources{nullptr}; /* 64 */
  38. SourceSubList() noexcept = default;
  39. SourceSubList(const SourceSubList&) = delete;
  40. SourceSubList(SourceSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Sources{rhs.Sources}
  41. { rhs.FreeMask = ~0_u64; rhs.Sources = nullptr; }
  42. ~SourceSubList();
  43. SourceSubList& operator=(const SourceSubList&) = delete;
  44. SourceSubList& operator=(SourceSubList&& rhs) noexcept
  45. { std::swap(FreeMask, rhs.FreeMask); std::swap(Sources, rhs.Sources); return *this; }
  46. };
  47. struct EffectSlotSubList {
  48. uint64_t FreeMask{~0_u64};
  49. ALeffectslot *EffectSlots{nullptr}; /* 64 */
  50. EffectSlotSubList() noexcept = default;
  51. EffectSlotSubList(const EffectSlotSubList&) = delete;
  52. EffectSlotSubList(EffectSlotSubList&& rhs) noexcept
  53. : FreeMask{rhs.FreeMask}, EffectSlots{rhs.EffectSlots}
  54. { rhs.FreeMask = ~0_u64; rhs.EffectSlots = nullptr; }
  55. ~EffectSlotSubList();
  56. EffectSlotSubList& operator=(const EffectSlotSubList&) = delete;
  57. EffectSlotSubList& operator=(EffectSlotSubList&& rhs) noexcept
  58. { std::swap(FreeMask, rhs.FreeMask); std::swap(EffectSlots, rhs.EffectSlots); return *this; }
  59. };
  60. struct ALCcontext {
  61. RefCount ref{1u};
  62. al::vector<SourceSubList> SourceList;
  63. ALuint NumSources{0};
  64. std::mutex SourceLock;
  65. al::vector<EffectSlotSubList> EffectSlotList;
  66. ALuint NumEffectSlots{0u};
  67. std::mutex EffectSlotLock;
  68. std::atomic<ALenum> LastError{AL_NO_ERROR};
  69. DistanceModel mDistanceModel{DistanceModel::Default};
  70. ALboolean SourceDistanceModel{AL_FALSE};
  71. ALfloat DopplerFactor{1.0f};
  72. ALfloat DopplerVelocity{1.0f};
  73. ALfloat SpeedOfSound{};
  74. ALfloat MetersPerUnit{1.0f};
  75. std::atomic_flag PropsClean;
  76. std::atomic<bool> DeferUpdates{false};
  77. std::mutex PropLock;
  78. /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
  79. * indicates if updates are currently happening).
  80. */
  81. RefCount UpdateCount{0u};
  82. std::atomic<bool> HoldUpdates{false};
  83. ALfloat GainBoost{1.0f};
  84. std::atomic<ALcontextProps*> Update{nullptr};
  85. /* Linked lists of unused property containers, free to use for future
  86. * updates.
  87. */
  88. std::atomic<ALcontextProps*> FreeContextProps{nullptr};
  89. std::atomic<ALlistenerProps*> FreeListenerProps{nullptr};
  90. std::atomic<ALvoiceProps*> FreeVoiceProps{nullptr};
  91. std::atomic<ALeffectslotProps*> FreeEffectslotProps{nullptr};
  92. ALvoice **Voices{nullptr};
  93. std::atomic<ALsizei> VoiceCount{0};
  94. ALsizei MaxVoices{0};
  95. using ALeffectslotArray = al::FlexArray<ALeffectslot*>;
  96. std::atomic<ALeffectslotArray*> ActiveAuxSlots{nullptr};
  97. std::thread EventThread;
  98. al::semaphore EventSem;
  99. std::unique_ptr<RingBuffer> AsyncEvents;
  100. std::atomic<ALbitfieldSOFT> EnabledEvts{0u};
  101. std::mutex EventCbLock;
  102. ALEVENTPROCSOFT EventCb{};
  103. void *EventParam{nullptr};
  104. /* Default effect slot */
  105. std::unique_ptr<ALeffectslot> DefaultSlot;
  106. ALCdevice *const Device;
  107. const ALCchar *ExtensionList{nullptr};
  108. std::atomic<ALCcontext*> next{nullptr};
  109. ALlistener Listener{};
  110. ALCcontext(ALCdevice *device);
  111. ALCcontext(const ALCcontext&) = delete;
  112. ALCcontext& operator=(const ALCcontext&) = delete;
  113. ~ALCcontext();
  114. static constexpr inline const char *CurrentPrefix() noexcept { return "ALCcontext::"; }
  115. DEF_NEWDEL(ALCcontext)
  116. };
  117. void ALCcontext_DecRef(ALCcontext *context);
  118. void UpdateContextProps(ALCcontext *context);
  119. void ALCcontext_DeferUpdates(ALCcontext *context);
  120. void ALCcontext_ProcessUpdates(ALCcontext *context);
  121. /* Simple RAII context reference. Takes the reference of the provided
  122. * ALCcontext, and decrements it when leaving scope. Movable (transfer
  123. * reference) but not copyable (no new references).
  124. */
  125. class ContextRef {
  126. ALCcontext *mCtx{nullptr};
  127. void reset() noexcept
  128. {
  129. if(mCtx)
  130. ALCcontext_DecRef(mCtx);
  131. mCtx = nullptr;
  132. }
  133. public:
  134. ContextRef() noexcept = default;
  135. ContextRef(ContextRef&& rhs) noexcept : mCtx{rhs.mCtx}
  136. { rhs.mCtx = nullptr; }
  137. explicit ContextRef(ALCcontext *ctx) noexcept : mCtx(ctx) { }
  138. ~ContextRef() { reset(); }
  139. ContextRef& operator=(const ContextRef&) = delete;
  140. ContextRef& operator=(ContextRef&& rhs) noexcept
  141. { std::swap(mCtx, rhs.mCtx); return *this; }
  142. operator bool() const noexcept { return mCtx != nullptr; }
  143. ALCcontext* operator->() noexcept { return mCtx; }
  144. ALCcontext* get() noexcept { return mCtx; }
  145. ALCcontext* release() noexcept
  146. {
  147. ALCcontext *ret{mCtx};
  148. mCtx = nullptr;
  149. return ret;
  150. }
  151. };
  152. ContextRef GetContextRef(void);
  153. struct ALcontextProps {
  154. ALfloat DopplerFactor;
  155. ALfloat DopplerVelocity;
  156. ALfloat SpeedOfSound;
  157. ALboolean SourceDistanceModel;
  158. DistanceModel mDistanceModel;
  159. ALfloat MetersPerUnit;
  160. std::atomic<ALcontextProps*> next;
  161. };
  162. #endif /* ALCONTEXT_H */