2018-11-17 23:02:27 -08:00
|
|
|
#ifndef ALCONTEXT_H
|
|
|
|
#define ALCONTEXT_H
|
|
|
|
|
2018-11-20 10:55:57 -08:00
|
|
|
#include <mutex>
|
|
|
|
#include <atomic>
|
2018-11-20 05:01:08 -08:00
|
|
|
#include <memory>
|
2018-11-18 18:04:27 -08:00
|
|
|
#include <thread>
|
|
|
|
|
2018-11-17 23:02:27 -08:00
|
|
|
#include "AL/al.h"
|
|
|
|
#include "AL/alc.h"
|
|
|
|
#include "AL/alext.h"
|
|
|
|
#include "inprogext.h"
|
|
|
|
|
|
|
|
#include "atomic.h"
|
|
|
|
#include "vector.h"
|
|
|
|
#include "threads.h"
|
2018-11-18 00:38:31 -08:00
|
|
|
#include "almalloc.h"
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-17 23:41:11 -08:00
|
|
|
#include "alListener.h"
|
|
|
|
|
2018-11-17 23:02:27 -08:00
|
|
|
|
|
|
|
struct ALsource;
|
|
|
|
struct ALeffectslot;
|
|
|
|
struct ALcontextProps;
|
|
|
|
struct ALlistenerProps;
|
|
|
|
struct ALvoiceProps;
|
|
|
|
struct ALeffectslotProps;
|
|
|
|
struct ALvoice;
|
|
|
|
struct ALeffectslotArray;
|
2018-12-26 21:22:17 -08:00
|
|
|
struct RingBuffer;
|
2018-11-17 23:02:27 -08:00
|
|
|
|
|
|
|
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 SourceSubList {
|
2018-11-25 07:40:15 -08:00
|
|
|
uint64_t FreeMask{~uint64_t{}};
|
2018-11-18 02:15:31 -08:00
|
|
|
ALsource *Sources{nullptr}; /* 64 */
|
2018-11-25 08:42:43 -08:00
|
|
|
|
|
|
|
SourceSubList() noexcept = default;
|
|
|
|
SourceSubList(const SourceSubList&) = delete;
|
|
|
|
SourceSubList(SourceSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Sources{rhs.Sources}
|
|
|
|
{ rhs.FreeMask = ~uint64_t{}; rhs.Sources = nullptr; }
|
|
|
|
~SourceSubList();
|
|
|
|
|
|
|
|
SourceSubList& operator=(const SourceSubList&) = delete;
|
|
|
|
SourceSubList& operator=(SourceSubList&& rhs) noexcept
|
|
|
|
{ std::swap(FreeMask, rhs.FreeMask); std::swap(Sources, rhs.Sources); return *this; }
|
2018-11-17 23:02:27 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Effect slots are rather large, and apps aren't likely to have more than one
|
|
|
|
* or two (let alone 64), so hold them individually.
|
|
|
|
*/
|
2018-11-20 10:01:20 -08:00
|
|
|
using ALeffectslotPtr = std::unique_ptr<ALeffectslot>;
|
2018-11-17 23:02:27 -08:00
|
|
|
|
|
|
|
struct ALCcontext_struct {
|
2018-11-18 05:40:00 -08:00
|
|
|
RefCount ref{1u};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-18 02:15:31 -08:00
|
|
|
al::vector<SourceSubList> SourceList;
|
2018-11-18 05:40:00 -08:00
|
|
|
ALuint NumSources{0};
|
2018-11-26 21:50:48 -08:00
|
|
|
std::mutex SourceLock;
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-18 02:39:27 -08:00
|
|
|
al::vector<ALeffectslotPtr> EffectSlotList;
|
2018-11-26 21:50:48 -08:00
|
|
|
std::mutex EffectSlotLock;
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-26 14:48:26 -08:00
|
|
|
std::atomic<ALenum> LastError{AL_NO_ERROR};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-18 05:40:00 -08:00
|
|
|
DistanceModel mDistanceModel{DistanceModel::Default};
|
|
|
|
ALboolean SourceDistanceModel{AL_FALSE};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-18 05:40:00 -08:00
|
|
|
ALfloat DopplerFactor{1.0f};
|
|
|
|
ALfloat DopplerVelocity{1.0f};
|
|
|
|
ALfloat SpeedOfSound{};
|
|
|
|
ALfloat MetersPerUnit{1.0f};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-20 10:45:01 -08:00
|
|
|
std::atomic_flag PropsClean{true};
|
|
|
|
std::atomic<bool> DeferUpdates{false};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-26 21:37:58 -08:00
|
|
|
std::mutex PropLock;
|
2018-11-17 23:02:27 -08:00
|
|
|
|
|
|
|
/* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
|
|
|
|
* indicates if updates are currently happening).
|
|
|
|
*/
|
2018-11-18 05:40:00 -08:00
|
|
|
RefCount UpdateCount{0u};
|
2018-11-26 14:48:26 -08:00
|
|
|
std::atomic<ALenum> HoldUpdates{AL_FALSE};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-18 05:40:00 -08:00
|
|
|
ALfloat GainBoost{1.0f};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-26 14:48:26 -08:00
|
|
|
std::atomic<ALcontextProps*> Update{nullptr};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
|
|
|
/* Linked lists of unused property containers, free to use for future
|
|
|
|
* updates.
|
|
|
|
*/
|
2018-11-26 14:48:26 -08:00
|
|
|
std::atomic<ALcontextProps*> FreeContextProps{nullptr};
|
|
|
|
std::atomic<ALlistenerProps*> FreeListenerProps{nullptr};
|
|
|
|
std::atomic<ALvoiceProps*> FreeVoiceProps{nullptr};
|
|
|
|
std::atomic<ALeffectslotProps*> FreeEffectslotProps{nullptr};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-18 05:40:00 -08:00
|
|
|
ALvoice **Voices{nullptr};
|
2018-11-23 16:16:31 -08:00
|
|
|
std::atomic<ALsizei> VoiceCount{0};
|
2018-11-18 05:40:00 -08:00
|
|
|
ALsizei MaxVoices{0};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-26 14:48:26 -08:00
|
|
|
std::atomic<ALeffectslotArray*> ActiveAuxSlots{nullptr};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-18 18:04:27 -08:00
|
|
|
std::thread EventThread;
|
2018-11-27 13:41:30 -08:00
|
|
|
al::semaphore EventSem;
|
2018-12-26 21:22:17 -08:00
|
|
|
RingBuffer *AsyncEvents{nullptr};
|
2018-11-26 14:48:26 -08:00
|
|
|
std::atomic<ALbitfieldSOFT> EnabledEvts{0u};
|
2018-11-20 10:55:57 -08:00
|
|
|
std::mutex EventCbLock;
|
2018-11-18 05:40:00 -08:00
|
|
|
ALEVENTPROCSOFT EventCb{};
|
|
|
|
void *EventParam{nullptr};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
|
|
|
/* Default effect slot */
|
2018-11-20 05:01:08 -08:00
|
|
|
std::unique_ptr<ALeffectslot> DefaultSlot;
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-18 05:40:00 -08:00
|
|
|
ALCdevice *const Device;
|
|
|
|
const ALCchar *ExtensionList{nullptr};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-26 14:48:26 -08:00
|
|
|
std::atomic<ALCcontext*> next{nullptr};
|
2018-11-17 23:02:27 -08:00
|
|
|
|
2018-11-18 05:40:00 -08:00
|
|
|
ALlistener Listener{};
|
|
|
|
|
|
|
|
|
2018-11-20 05:01:08 -08:00
|
|
|
ALCcontext_struct(ALCdevice *device);
|
2018-11-18 05:40:00 -08:00
|
|
|
ALCcontext_struct(const ALCcontext_struct&) = delete;
|
|
|
|
ALCcontext_struct& operator=(const ALCcontext_struct&) = delete;
|
|
|
|
~ALCcontext_struct();
|
2018-11-18 00:38:31 -08:00
|
|
|
|
|
|
|
DEF_NEWDEL(ALCcontext)
|
2018-11-17 23:02:27 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
void ALCcontext_DecRef(ALCcontext *context);
|
|
|
|
|
|
|
|
void UpdateContextProps(ALCcontext *context);
|
|
|
|
|
|
|
|
void ALCcontext_DeferUpdates(ALCcontext *context);
|
|
|
|
void ALCcontext_ProcessUpdates(ALCcontext *context);
|
|
|
|
|
|
|
|
|
|
|
|
/* Simple RAII context reference. Takes the reference of the provided
|
|
|
|
* ALCcontext, and decrements it when leaving scope. Movable (transfer
|
|
|
|
* reference) but not copyable (no new references).
|
|
|
|
*/
|
|
|
|
class ContextRef {
|
|
|
|
ALCcontext *mCtx{nullptr};
|
|
|
|
|
2018-11-21 00:40:41 -08:00
|
|
|
void reset() noexcept
|
2018-11-17 23:02:27 -08:00
|
|
|
{
|
|
|
|
if(mCtx)
|
|
|
|
ALCcontext_DecRef(mCtx);
|
|
|
|
mCtx = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
ContextRef() noexcept = default;
|
2018-11-21 02:02:53 -08:00
|
|
|
ContextRef(ContextRef&& rhs) noexcept : mCtx{rhs.mCtx}
|
|
|
|
{ rhs.mCtx = nullptr; }
|
2018-11-17 23:02:27 -08:00
|
|
|
explicit ContextRef(ALCcontext *ctx) noexcept : mCtx(ctx) { }
|
2018-11-21 00:40:41 -08:00
|
|
|
~ContextRef() { reset(); }
|
2018-11-17 23:02:27 -08:00
|
|
|
|
|
|
|
ContextRef& operator=(const ContextRef&) = delete;
|
|
|
|
ContextRef& operator=(ContextRef&& rhs) noexcept
|
2018-11-27 10:08:25 -08:00
|
|
|
{ std::swap(mCtx, rhs.mCtx); return *this; }
|
2018-11-17 23:02:27 -08:00
|
|
|
|
|
|
|
operator bool() const noexcept { return mCtx != nullptr; }
|
|
|
|
|
|
|
|
ALCcontext* operator->() noexcept { return mCtx; }
|
|
|
|
ALCcontext* get() noexcept { return mCtx; }
|
2018-11-21 02:02:53 -08:00
|
|
|
|
|
|
|
ALCcontext* release() noexcept
|
|
|
|
{
|
|
|
|
ALCcontext *ret{mCtx};
|
|
|
|
mCtx = nullptr;
|
|
|
|
return ret;
|
|
|
|
}
|
2018-11-17 23:02:27 -08:00
|
|
|
};
|
|
|
|
|
2018-11-24 14:07:32 -08:00
|
|
|
ContextRef GetContextRef(void);
|
|
|
|
|
2018-11-17 23:02:27 -08:00
|
|
|
|
|
|
|
struct ALcontextProps {
|
|
|
|
ALfloat DopplerFactor;
|
|
|
|
ALfloat DopplerVelocity;
|
|
|
|
ALfloat SpeedOfSound;
|
|
|
|
ALboolean SourceDistanceModel;
|
2018-11-18 03:39:32 -08:00
|
|
|
DistanceModel mDistanceModel;
|
2018-11-17 23:02:27 -08:00
|
|
|
ALfloat MetersPerUnit;
|
|
|
|
|
2018-11-26 14:48:26 -08:00
|
|
|
std::atomic<ALcontextProps*> next;
|
2018-11-17 23:02:27 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* ALCONTEXT_H */
|