mirror of
https://github.com/love2d/megasource.git
synced 2026-08-19 20:20:11 +02:00
Update OpenAL-soft to 1.23.1-bc7cb17.
This commit is contained in:
+352
-300
@@ -1,11 +1,17 @@
|
||||
#ifndef ALC_CONTEXT_H
|
||||
#define ALC_CONTEXT_H
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
@@ -14,100 +20,71 @@
|
||||
#include "al/listener.h"
|
||||
#include "almalloc.h"
|
||||
#include "alnumeric.h"
|
||||
#include "althreads.h"
|
||||
#include "atomic.h"
|
||||
#include "core/context.h"
|
||||
#include "inprogext.h"
|
||||
#include "intrusive_ptr.h"
|
||||
#include "vector.h"
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include "al/eax_eax_call.h"
|
||||
#include "al/eax_fx_slot_index.h"
|
||||
#include "al/eax_fx_slots.h"
|
||||
#include "al/eax_utils.h"
|
||||
|
||||
|
||||
using EaxContextSharedDirtyFlagsValue = std::uint_least8_t;
|
||||
|
||||
struct EaxContextSharedDirtyFlags
|
||||
{
|
||||
using EaxIsBitFieldStruct = bool;
|
||||
|
||||
EaxContextSharedDirtyFlagsValue primary_fx_slot_id : 1;
|
||||
}; // EaxContextSharedDirtyFlags
|
||||
|
||||
|
||||
using ContextDirtyFlagsValue = std::uint_least8_t;
|
||||
|
||||
struct ContextDirtyFlags
|
||||
{
|
||||
using EaxIsBitFieldStruct = bool;
|
||||
|
||||
ContextDirtyFlagsValue guidPrimaryFXSlotID : 1;
|
||||
ContextDirtyFlagsValue flDistanceFactor : 1;
|
||||
ContextDirtyFlagsValue flAirAbsorptionHF : 1;
|
||||
ContextDirtyFlagsValue flHFReference : 1;
|
||||
ContextDirtyFlagsValue flMacroFXFactor : 1;
|
||||
}; // ContextDirtyFlags
|
||||
|
||||
|
||||
struct EaxAlIsExtensionPresentResult
|
||||
{
|
||||
ALboolean is_present;
|
||||
bool is_return;
|
||||
}; // EaxAlIsExtensionPresentResult
|
||||
#include "al/eax/call.h"
|
||||
#include "al/eax/exception.h"
|
||||
#include "al/eax/fx_slot_index.h"
|
||||
#include "al/eax/fx_slots.h"
|
||||
#include "al/eax/utils.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
struct ALeffect;
|
||||
struct ALeffectslot;
|
||||
struct ALsource;
|
||||
struct DebugGroup;
|
||||
struct EffectSlotSubList;
|
||||
struct SourceSubList;
|
||||
|
||||
enum class DebugSource : uint8_t;
|
||||
enum class DebugType : uint8_t;
|
||||
enum class DebugSeverity : uint8_t;
|
||||
|
||||
using uint = unsigned int;
|
||||
|
||||
|
||||
struct SourceSubList {
|
||||
uint64_t FreeMask{~0_u64};
|
||||
ALsource *Sources{nullptr}; /* 64 */
|
||||
enum ContextFlags {
|
||||
DebugBit = 0, /* ALC_CONTEXT_DEBUG_BIT_EXT */
|
||||
};
|
||||
using ContextFlagBitset = std::bitset<sizeof(ALuint)*8>;
|
||||
|
||||
SourceSubList() noexcept = default;
|
||||
SourceSubList(const SourceSubList&) = delete;
|
||||
SourceSubList(SourceSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Sources{rhs.Sources}
|
||||
{ rhs.FreeMask = ~0_u64; 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; }
|
||||
struct DebugLogEntry {
|
||||
const DebugSource mSource;
|
||||
const DebugType mType;
|
||||
const DebugSeverity mSeverity;
|
||||
const uint mId;
|
||||
|
||||
std::string mMessage;
|
||||
|
||||
template<typename T>
|
||||
DebugLogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message)
|
||||
: mSource{source}, mType{type}, mSeverity{severity}, mId{id}
|
||||
, mMessage{std::forward<T>(message)}
|
||||
{ }
|
||||
DebugLogEntry(const DebugLogEntry&) = default;
|
||||
DebugLogEntry(DebugLogEntry&&) = default;
|
||||
};
|
||||
|
||||
struct EffectSlotSubList {
|
||||
uint64_t FreeMask{~0_u64};
|
||||
ALeffectslot *EffectSlots{nullptr}; /* 64 */
|
||||
|
||||
EffectSlotSubList() noexcept = default;
|
||||
EffectSlotSubList(const EffectSlotSubList&) = delete;
|
||||
EffectSlotSubList(EffectSlotSubList&& rhs) noexcept
|
||||
: FreeMask{rhs.FreeMask}, EffectSlots{rhs.EffectSlots}
|
||||
{ rhs.FreeMask = ~0_u64; rhs.EffectSlots = nullptr; }
|
||||
~EffectSlotSubList();
|
||||
|
||||
EffectSlotSubList& operator=(const EffectSlotSubList&) = delete;
|
||||
EffectSlotSubList& operator=(EffectSlotSubList&& rhs) noexcept
|
||||
{ std::swap(FreeMask, rhs.FreeMask); std::swap(EffectSlots, rhs.EffectSlots); return *this; }
|
||||
};
|
||||
|
||||
struct ALCcontext : public al::intrusive_ref<ALCcontext>, ContextBase {
|
||||
const al::intrusive_ptr<ALCdevice> mALDevice;
|
||||
|
||||
/* Wet buffers used by effect slots. */
|
||||
al::vector<WetBufferPtr> mWetBuffers;
|
||||
|
||||
|
||||
bool mPropsDirty{true};
|
||||
bool mDeferUpdates{false};
|
||||
|
||||
std::mutex mPropLock;
|
||||
|
||||
std::atomic<ALenum> mLastError{AL_NO_ERROR};
|
||||
al::tss<ALenum> mLastThreadError{AL_NO_ERROR};
|
||||
|
||||
const ContextFlagBitset mContextFlags;
|
||||
std::atomic<bool> mDebugEnabled{false};
|
||||
|
||||
DistanceModel mDistanceModel{DistanceModel::Default};
|
||||
bool mSourceDistanceModel{false};
|
||||
@@ -121,23 +98,32 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext>, ContextBase {
|
||||
ALEVENTPROCSOFT mEventCb{};
|
||||
void *mEventParam{nullptr};
|
||||
|
||||
std::mutex mDebugCbLock;
|
||||
ALDEBUGPROCEXT mDebugCb{};
|
||||
void *mDebugParam{nullptr};
|
||||
std::vector<DebugGroup> mDebugGroups;
|
||||
std::deque<DebugLogEntry> mDebugLog;
|
||||
|
||||
ALlistener mListener{};
|
||||
|
||||
al::vector<SourceSubList> mSourceList;
|
||||
std::vector<SourceSubList> mSourceList;
|
||||
ALuint mNumSources{0};
|
||||
std::mutex mSourceLock;
|
||||
|
||||
al::vector<EffectSlotSubList> mEffectSlotList;
|
||||
std::vector<EffectSlotSubList> mEffectSlotList;
|
||||
ALuint mNumEffectSlots{0u};
|
||||
std::mutex mEffectSlotLock;
|
||||
|
||||
/* Default effect slot */
|
||||
std::unique_ptr<ALeffectslot> mDefaultSlot;
|
||||
|
||||
const char *mExtensionList{nullptr};
|
||||
std::vector<std::string_view> mExtensions;
|
||||
std::string mExtensionsString{};
|
||||
|
||||
std::unordered_map<ALuint,std::string> mSourceNames;
|
||||
std::unordered_map<ALuint,std::string> mEffectSlotNames;
|
||||
|
||||
ALCcontext(al::intrusive_ptr<ALCdevice> device);
|
||||
ALCcontext(al::intrusive_ptr<ALCdevice> device, ContextFlagBitset flags);
|
||||
ALCcontext(const ALCcontext&) = delete;
|
||||
ALCcontext& operator=(const ALCcontext&) = delete;
|
||||
~ALCcontext();
|
||||
@@ -145,10 +131,10 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext>, ContextBase {
|
||||
void init();
|
||||
/**
|
||||
* Removes the context from its device and removes it from being current on
|
||||
* the running thread or globally. Returns true if other contexts still
|
||||
* exist on the device.
|
||||
* the running thread or globally. Stops device playback if this was the
|
||||
* last context on its device.
|
||||
*/
|
||||
bool deinit();
|
||||
void deinit();
|
||||
|
||||
/**
|
||||
* Defers/suspends updates for the given context's listener and sources.
|
||||
@@ -173,19 +159,32 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext>, ContextBase {
|
||||
*/
|
||||
void applyAllUpdates();
|
||||
|
||||
#ifdef __USE_MINGW_ANSI_STDIO
|
||||
[[gnu::format(gnu_printf, 3, 4)]]
|
||||
#ifdef __MINGW32__
|
||||
[[gnu::format(__MINGW_PRINTF_FORMAT, 3, 4)]]
|
||||
#else
|
||||
[[gnu::format(printf, 3, 4)]]
|
||||
#endif
|
||||
void setError(ALenum errorCode, const char *msg, ...);
|
||||
|
||||
void sendDebugMessage(std::unique_lock<std::mutex> &debuglock, DebugSource source,
|
||||
DebugType type, ALuint id, DebugSeverity severity, std::string_view message);
|
||||
|
||||
void debugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity,
|
||||
std::string_view message)
|
||||
{
|
||||
if(!mDebugEnabled.load(std::memory_order_relaxed)) LIKELY
|
||||
return;
|
||||
std::unique_lock<std::mutex> debuglock{mDebugCbLock};
|
||||
sendDebugMessage(debuglock, source, type, id, severity, message);
|
||||
}
|
||||
|
||||
/* Process-wide current context */
|
||||
static std::atomic<bool> sGlobalContextLock;
|
||||
static std::atomic<ALCcontext*> sGlobalContext;
|
||||
|
||||
private:
|
||||
/* Thread-local current context. */
|
||||
static thread_local ALCcontext *sLocalContext;
|
||||
static inline 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.
|
||||
@@ -193,37 +192,29 @@ private:
|
||||
class ThreadCtx {
|
||||
public:
|
||||
~ThreadCtx();
|
||||
/* NOLINTBEGIN(readability-convert-member-functions-to-static)
|
||||
* This should be non-static to invoke construction of the thread-local
|
||||
* sThreadContext, so that it's destructor gets run at thread exit to
|
||||
* clear sLocalContext (which isn't a member variable to make read
|
||||
* access efficient).
|
||||
*/
|
||||
void set(ALCcontext *ctx) const noexcept { sLocalContext = ctx; }
|
||||
/* NOLINTEND(readability-convert-member-functions-to-static) */
|
||||
};
|
||||
static thread_local ThreadCtx sThreadContext;
|
||||
|
||||
public:
|
||||
/* HACK: MinGW generates bad code when accessing an extern thread_local
|
||||
* object. Add a wrapper function for it that only accesses it where it's
|
||||
* defined.
|
||||
*/
|
||||
#ifdef __MINGW32__
|
||||
static ALCcontext *getThreadContext() noexcept;
|
||||
static void setThreadContext(ALCcontext *context) noexcept;
|
||||
#else
|
||||
static ALCcontext *getThreadContext() noexcept { return sLocalContext; }
|
||||
static void setThreadContext(ALCcontext *context) noexcept { sThreadContext.set(context); }
|
||||
#endif
|
||||
|
||||
/* Default effect that applies to sources that don't have an effect on send 0. */
|
||||
static ALeffect sDefaultEffect;
|
||||
|
||||
DEF_NEWDEL(ALCcontext)
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
public:
|
||||
bool has_eax() const noexcept { return eax_is_initialized_; }
|
||||
|
||||
bool eax_is_capable() const noexcept;
|
||||
|
||||
|
||||
void eax_uninitialize() noexcept;
|
||||
bool hasEax() const noexcept { return mEaxIsInitialized; }
|
||||
bool eaxIsCapable() const noexcept;
|
||||
|
||||
void eaxUninitialize() noexcept;
|
||||
|
||||
ALenum eax_eax_set(
|
||||
const GUID* property_set_id,
|
||||
@@ -239,266 +230,327 @@ public:
|
||||
ALvoid* property_value,
|
||||
ALuint property_value_size);
|
||||
|
||||
void eaxSetLastError() noexcept;
|
||||
|
||||
void eax_update_filters();
|
||||
EaxFxSlotIndex eaxGetPrimaryFxSlotIndex() const noexcept
|
||||
{ return mEaxPrimaryFxSlotIndex; }
|
||||
|
||||
void eax_commit_and_update_sources();
|
||||
const ALeffectslot& eaxGetFxSlot(EaxFxSlotIndexValue fx_slot_index) const
|
||||
{ return mEaxFxSlots.get(fx_slot_index); }
|
||||
ALeffectslot& eaxGetFxSlot(EaxFxSlotIndexValue fx_slot_index)
|
||||
{ return mEaxFxSlots.get(fx_slot_index); }
|
||||
|
||||
bool eaxNeedsCommit() const noexcept { return mEaxNeedsCommit; }
|
||||
void eaxCommit();
|
||||
|
||||
void eax_set_last_error() noexcept;
|
||||
|
||||
|
||||
EaxFxSlotIndex eax_get_previous_primary_fx_slot_index() const noexcept
|
||||
{ return eax_previous_primary_fx_slot_index_; }
|
||||
EaxFxSlotIndex eax_get_primary_fx_slot_index() const noexcept
|
||||
{ return eax_primary_fx_slot_index_; }
|
||||
|
||||
const ALeffectslot& eax_get_fx_slot(EaxFxSlotIndexValue fx_slot_index) const
|
||||
{ return eax_fx_slots_.get(fx_slot_index); }
|
||||
ALeffectslot& eax_get_fx_slot(EaxFxSlotIndexValue fx_slot_index)
|
||||
{ return eax_fx_slots_.get(fx_slot_index); }
|
||||
|
||||
void eax_commit_fx_slots()
|
||||
{ eax_fx_slots_.commit(); }
|
||||
void eaxCommitFxSlots()
|
||||
{ mEaxFxSlots.commit(); }
|
||||
|
||||
private:
|
||||
struct Eax
|
||||
static constexpr auto eax_primary_fx_slot_id_dirty_bit = EaxDirtyFlags{1} << 0;
|
||||
static constexpr auto eax_distance_factor_dirty_bit = EaxDirtyFlags{1} << 1;
|
||||
static constexpr auto eax_air_absorption_hf_dirty_bit = EaxDirtyFlags{1} << 2;
|
||||
static constexpr auto eax_hf_reference_dirty_bit = EaxDirtyFlags{1} << 3;
|
||||
static constexpr auto eax_macro_fx_factor_dirty_bit = EaxDirtyFlags{1} << 4;
|
||||
|
||||
using Eax4Props = EAX40CONTEXTPROPERTIES;
|
||||
|
||||
struct Eax4State {
|
||||
Eax4Props i; // Immediate.
|
||||
Eax4Props d; // Deferred.
|
||||
};
|
||||
|
||||
using Eax5Props = EAX50CONTEXTPROPERTIES;
|
||||
|
||||
struct Eax5State {
|
||||
Eax5Props i; // Immediate.
|
||||
Eax5Props d; // Deferred.
|
||||
};
|
||||
|
||||
class ContextException : public EaxException
|
||||
{
|
||||
EAX50CONTEXTPROPERTIES context{};
|
||||
}; // Eax
|
||||
public:
|
||||
explicit ContextException(const char* message)
|
||||
: EaxException{"EAX_CONTEXT", message}
|
||||
{}
|
||||
};
|
||||
|
||||
struct Eax4PrimaryFxSlotIdValidator {
|
||||
void operator()(const GUID& guidPrimaryFXSlotID) const
|
||||
{
|
||||
if(guidPrimaryFXSlotID != EAX_NULL_GUID &&
|
||||
guidPrimaryFXSlotID != EAXPROPERTYID_EAX40_FXSlot0 &&
|
||||
guidPrimaryFXSlotID != EAXPROPERTYID_EAX40_FXSlot1 &&
|
||||
guidPrimaryFXSlotID != EAXPROPERTYID_EAX40_FXSlot2 &&
|
||||
guidPrimaryFXSlotID != EAXPROPERTYID_EAX40_FXSlot3)
|
||||
{
|
||||
eax_fail_unknown_primary_fx_slot_id();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool eax_is_initialized_{};
|
||||
bool eax_is_tried_{};
|
||||
bool eax_are_legacy_fx_slots_unlocked_{};
|
||||
struct Eax4DistanceFactorValidator {
|
||||
void operator()(float flDistanceFactor) const
|
||||
{
|
||||
eax_validate_range<ContextException>(
|
||||
"Distance Factor",
|
||||
flDistanceFactor,
|
||||
EAXCONTEXT_MINDISTANCEFACTOR,
|
||||
EAXCONTEXT_MAXDISTANCEFACTOR);
|
||||
}
|
||||
};
|
||||
|
||||
long eax_last_error_{};
|
||||
unsigned long eax_speaker_config_{};
|
||||
struct Eax4AirAbsorptionHfValidator {
|
||||
void operator()(float flAirAbsorptionHF) const
|
||||
{
|
||||
eax_validate_range<ContextException>(
|
||||
"Air Absorption HF",
|
||||
flAirAbsorptionHF,
|
||||
EAXCONTEXT_MINAIRABSORPTIONHF,
|
||||
EAXCONTEXT_MAXAIRABSORPTIONHF);
|
||||
}
|
||||
};
|
||||
|
||||
EaxFxSlotIndex eax_previous_primary_fx_slot_index_{};
|
||||
EaxFxSlotIndex eax_primary_fx_slot_index_{};
|
||||
EaxFxSlots eax_fx_slots_{};
|
||||
struct Eax4HfReferenceValidator {
|
||||
void operator()(float flHFReference) const
|
||||
{
|
||||
eax_validate_range<ContextException>(
|
||||
"HF Reference",
|
||||
flHFReference,
|
||||
EAXCONTEXT_MINHFREFERENCE,
|
||||
EAXCONTEXT_MAXHFREFERENCE);
|
||||
}
|
||||
};
|
||||
|
||||
EaxContextSharedDirtyFlags eax_context_shared_dirty_flags_{};
|
||||
struct Eax4AllValidator {
|
||||
void operator()(const EAX40CONTEXTPROPERTIES& all) const
|
||||
{
|
||||
Eax4PrimaryFxSlotIdValidator{}(all.guidPrimaryFXSlotID);
|
||||
Eax4DistanceFactorValidator{}(all.flDistanceFactor);
|
||||
Eax4AirAbsorptionHfValidator{}(all.flAirAbsorptionHF);
|
||||
Eax4HfReferenceValidator{}(all.flHFReference);
|
||||
}
|
||||
};
|
||||
|
||||
Eax eax_{};
|
||||
Eax eax_d_{};
|
||||
EAXSESSIONPROPERTIES eax_session_{};
|
||||
struct Eax5PrimaryFxSlotIdValidator {
|
||||
void operator()(const GUID& guidPrimaryFXSlotID) const
|
||||
{
|
||||
if(guidPrimaryFXSlotID != EAX_NULL_GUID &&
|
||||
guidPrimaryFXSlotID != EAXPROPERTYID_EAX50_FXSlot0 &&
|
||||
guidPrimaryFXSlotID != EAXPROPERTYID_EAX50_FXSlot1 &&
|
||||
guidPrimaryFXSlotID != EAXPROPERTYID_EAX50_FXSlot2 &&
|
||||
guidPrimaryFXSlotID != EAXPROPERTYID_EAX50_FXSlot3)
|
||||
{
|
||||
eax_fail_unknown_primary_fx_slot_id();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ContextDirtyFlags eax_context_dirty_flags_{};
|
||||
struct Eax5MacroFxFactorValidator {
|
||||
void operator()(float flMacroFXFactor) const
|
||||
{
|
||||
eax_validate_range<ContextException>(
|
||||
"Macro FX Factor",
|
||||
flMacroFXFactor,
|
||||
EAXCONTEXT_MINMACROFXFACTOR,
|
||||
EAXCONTEXT_MAXMACROFXFACTOR);
|
||||
}
|
||||
};
|
||||
|
||||
std::string eax_extension_list_{};
|
||||
struct Eax5AllValidator {
|
||||
void operator()(const EAX50CONTEXTPROPERTIES& all) const
|
||||
{
|
||||
Eax5PrimaryFxSlotIdValidator{}(all.guidPrimaryFXSlotID);
|
||||
Eax4DistanceFactorValidator{}(all.flDistanceFactor);
|
||||
Eax4AirAbsorptionHfValidator{}(all.flAirAbsorptionHF);
|
||||
Eax4HfReferenceValidator{}(all.flHFReference);
|
||||
Eax5MacroFxFactorValidator{}(all.flMacroFXFactor);
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax5EaxVersionValidator {
|
||||
void operator()(unsigned long ulEAXVersion) const
|
||||
{
|
||||
eax_validate_range<ContextException>(
|
||||
"EAX version",
|
||||
ulEAXVersion,
|
||||
EAXCONTEXT_MINEAXSESSION,
|
||||
EAXCONTEXT_MAXEAXSESSION);
|
||||
}
|
||||
};
|
||||
|
||||
[[noreturn]]
|
||||
static void eax_fail(
|
||||
const char* message);
|
||||
struct Eax5MaxActiveSendsValidator {
|
||||
void operator()(unsigned long ulMaxActiveSends) const
|
||||
{
|
||||
eax_validate_range<ContextException>(
|
||||
"Max Active Sends",
|
||||
ulMaxActiveSends,
|
||||
EAXCONTEXT_MINMAXACTIVESENDS,
|
||||
EAXCONTEXT_MAXMAXACTIVESENDS);
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax5SessionAllValidator {
|
||||
void operator()(const EAXSESSIONPROPERTIES& all) const
|
||||
{
|
||||
Eax5EaxVersionValidator{}(all.ulEAXVersion);
|
||||
Eax5MaxActiveSendsValidator{}(all.ulMaxActiveSends);
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax5SpeakerConfigValidator {
|
||||
void operator()(unsigned long ulSpeakerConfig) const
|
||||
{
|
||||
eax_validate_range<ContextException>(
|
||||
"Speaker Config",
|
||||
ulSpeakerConfig,
|
||||
EAXCONTEXT_MINSPEAKERCONFIG,
|
||||
EAXCONTEXT_MAXSPEAKERCONFIG);
|
||||
}
|
||||
};
|
||||
|
||||
bool mEaxIsInitialized{};
|
||||
bool mEaxIsTried{};
|
||||
|
||||
long mEaxLastError{};
|
||||
unsigned long mEaxSpeakerConfig{};
|
||||
|
||||
EaxFxSlotIndex mEaxPrimaryFxSlotIndex{};
|
||||
EaxFxSlots mEaxFxSlots{};
|
||||
|
||||
int mEaxVersion{}; // Current EAX version.
|
||||
bool mEaxNeedsCommit{};
|
||||
EaxDirtyFlags mEaxDf{}; // Dirty flags for the current EAX version.
|
||||
Eax5State mEax123{}; // EAX1/EAX2/EAX3 state.
|
||||
Eax4State mEax4{}; // EAX4 state.
|
||||
Eax5State mEax5{}; // EAX5 state.
|
||||
Eax5Props mEax{}; // Current EAX state.
|
||||
EAXSESSIONPROPERTIES mEaxSession{};
|
||||
|
||||
[[noreturn]] static void eax_fail(const char* message);
|
||||
[[noreturn]] static void eax_fail_unknown_property_set_id();
|
||||
[[noreturn]] static void eax_fail_unknown_primary_fx_slot_id();
|
||||
[[noreturn]] static void eax_fail_unknown_property_id();
|
||||
[[noreturn]] static void eax_fail_unknown_version();
|
||||
|
||||
// Gets a value from EAX call,
|
||||
// validates it,
|
||||
// and updates the current value.
|
||||
template<typename TValidator, typename TProperty>
|
||||
static void eax_set(const EaxCall& call, TProperty& property)
|
||||
{
|
||||
const auto& value = call.get_value<ContextException, const TProperty>();
|
||||
TValidator{}(value);
|
||||
property = value;
|
||||
}
|
||||
|
||||
// Gets a new value from EAX call,
|
||||
// validates it,
|
||||
// updates the deferred value,
|
||||
// updates a dirty flag.
|
||||
template<
|
||||
typename TValidator,
|
||||
EaxDirtyFlags TDirtyBit,
|
||||
typename TMemberResult,
|
||||
typename TProps,
|
||||
typename TState>
|
||||
void eax_defer(const EaxCall& call, TState& state, TMemberResult TProps::*member)
|
||||
{
|
||||
const auto& src = call.get_value<ContextException, const TMemberResult>();
|
||||
TValidator{}(src);
|
||||
const auto& dst_i = state.i.*member;
|
||||
auto& dst_d = state.d.*member;
|
||||
dst_d = src;
|
||||
|
||||
if(dst_i != dst_d)
|
||||
mEaxDf |= TDirtyBit;
|
||||
}
|
||||
|
||||
template<
|
||||
EaxDirtyFlags TDirtyBit,
|
||||
typename TMemberResult,
|
||||
typename TProps,
|
||||
typename TState>
|
||||
void eax_context_commit_property(TState& state, EaxDirtyFlags& dst_df,
|
||||
TMemberResult TProps::*member) noexcept
|
||||
{
|
||||
if((mEaxDf & TDirtyBit) != EaxDirtyFlags{})
|
||||
{
|
||||
dst_df |= TDirtyBit;
|
||||
const auto& src_d = state.d.*member;
|
||||
state.i.*member = src_d;
|
||||
mEax.*member = src_d;
|
||||
}
|
||||
}
|
||||
|
||||
void eax_initialize_extensions();
|
||||
|
||||
void eax_initialize();
|
||||
|
||||
|
||||
bool eax_has_no_default_effect_slot() const noexcept;
|
||||
|
||||
void eax_ensure_no_default_effect_slot() const;
|
||||
|
||||
bool eax_has_enough_aux_sends() const noexcept;
|
||||
|
||||
void eax_ensure_enough_aux_sends() const;
|
||||
|
||||
void eax_ensure_compatibility();
|
||||
|
||||
|
||||
unsigned long eax_detect_speaker_configuration() const;
|
||||
void eax_update_speaker_configuration();
|
||||
|
||||
|
||||
void eax_set_last_error_defaults() noexcept;
|
||||
void eax_session_set_defaults() noexcept;
|
||||
static void eax4_context_set_defaults(Eax4Props& props) noexcept;
|
||||
static void eax4_context_set_defaults(Eax4State& state) noexcept;
|
||||
static void eax5_context_set_defaults(Eax5Props& props) noexcept;
|
||||
static void eax5_context_set_defaults(Eax5State& state) noexcept;
|
||||
void eax_context_set_defaults();
|
||||
void eax_set_defaults();
|
||||
|
||||
void eax_set_session_defaults() noexcept;
|
||||
void eax_dispatch_fx_slot(const EaxCall& call);
|
||||
void eax_dispatch_source(const EaxCall& call);
|
||||
|
||||
void eax_set_context_defaults() noexcept;
|
||||
void eax_get_misc(const EaxCall& call);
|
||||
void eax4_get(const EaxCall& call, const Eax4Props& props);
|
||||
void eax5_get(const EaxCall& call, const Eax5Props& props);
|
||||
void eax_get(const EaxCall& call);
|
||||
|
||||
void eax_set_defaults() noexcept;
|
||||
|
||||
void eax_initialize_sources();
|
||||
|
||||
|
||||
void eax_unlock_legacy_fx_slots(const EaxEaxCall& eax_call) noexcept;
|
||||
|
||||
|
||||
void eax_dispatch_fx_slot(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_dispatch_source(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
|
||||
void eax_get_primary_fx_slot_id(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_get_distance_factor(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_get_air_absorption_hf(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_get_hf_reference(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_get_last_error(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_get_speaker_config(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_get_session(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_get_macro_fx_factor(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_get_context_all(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_get(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
|
||||
void eax_set_primary_fx_slot_id();
|
||||
|
||||
void eax_set_distance_factor();
|
||||
|
||||
void eax_set_air_absorbtion_hf();
|
||||
|
||||
void eax_set_hf_reference();
|
||||
|
||||
void eax_set_macro_fx_factor();
|
||||
|
||||
void eax_set_context();
|
||||
void eax_context_commit_primary_fx_slot_id();
|
||||
void eax_context_commit_distance_factor();
|
||||
void eax_context_commit_air_absorbtion_hf();
|
||||
void eax_context_commit_hf_reference();
|
||||
void eax_context_commit_macro_fx_factor();
|
||||
|
||||
void eax_initialize_fx_slots();
|
||||
|
||||
|
||||
void eax_update_sources();
|
||||
|
||||
void eax_set_misc(const EaxCall& call);
|
||||
void eax4_defer_all(const EaxCall& call, Eax4State& state);
|
||||
void eax4_defer(const EaxCall& call, Eax4State& state);
|
||||
void eax5_defer_all(const EaxCall& call, Eax5State& state);
|
||||
void eax5_defer(const EaxCall& call, Eax5State& state);
|
||||
void eax_set(const EaxCall& call);
|
||||
|
||||
void eax_validate_primary_fx_slot_id(
|
||||
const GUID& primary_fx_slot_id);
|
||||
|
||||
void eax_validate_distance_factor(
|
||||
float distance_factor);
|
||||
|
||||
void eax_validate_air_absorption_hf(
|
||||
float air_absorption_hf);
|
||||
|
||||
void eax_validate_hf_reference(
|
||||
float hf_reference);
|
||||
|
||||
void eax_validate_speaker_config(
|
||||
unsigned long speaker_config);
|
||||
|
||||
void eax_validate_session_eax_version(
|
||||
unsigned long eax_version);
|
||||
|
||||
void eax_validate_session_max_active_sends(
|
||||
unsigned long max_active_sends);
|
||||
|
||||
void eax_validate_session(
|
||||
const EAXSESSIONPROPERTIES& eax_session);
|
||||
|
||||
void eax_validate_macro_fx_factor(
|
||||
float macro_fx_factor);
|
||||
|
||||
void eax_validate_context_all(
|
||||
const EAX40CONTEXTPROPERTIES& context_all);
|
||||
|
||||
void eax_validate_context_all(
|
||||
const EAX50CONTEXTPROPERTIES& context_all);
|
||||
|
||||
|
||||
void eax_defer_primary_fx_slot_id(
|
||||
const GUID& primary_fx_slot_id);
|
||||
|
||||
void eax_defer_distance_factor(
|
||||
float distance_factor);
|
||||
|
||||
void eax_defer_air_absorption_hf(
|
||||
float air_absorption_hf);
|
||||
|
||||
void eax_defer_hf_reference(
|
||||
float hf_reference);
|
||||
|
||||
void eax_defer_macro_fx_factor(
|
||||
float macro_fx_factor);
|
||||
|
||||
void eax_defer_context_all(
|
||||
const EAX40CONTEXTPROPERTIES& context_all);
|
||||
|
||||
void eax_defer_context_all(
|
||||
const EAX50CONTEXTPROPERTIES& context_all);
|
||||
|
||||
|
||||
void eax_defer_context_all(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_defer_primary_fx_slot_id(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_defer_distance_factor(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_defer_air_absorption_hf(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_defer_hf_reference(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_set_session(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_defer_macro_fx_factor(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_set(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_apply_deferred();
|
||||
void eax4_context_commit(Eax4State& state, EaxDirtyFlags& dst_df);
|
||||
void eax5_context_commit(Eax5State& state, EaxDirtyFlags& dst_df);
|
||||
void eax_context_commit();
|
||||
#endif // ALSOFT_EAX
|
||||
};
|
||||
|
||||
#define SETERR_RETURN(ctx, err, retval, ...) do { \
|
||||
(ctx)->setError((err), __VA_ARGS__); \
|
||||
return retval; \
|
||||
} while(0)
|
||||
|
||||
|
||||
using ContextRef = al::intrusive_ptr<ALCcontext>;
|
||||
|
||||
ContextRef GetContextRef(void);
|
||||
ContextRef GetContextRef() noexcept;
|
||||
|
||||
void UpdateContextProps(ALCcontext *context);
|
||||
|
||||
|
||||
extern bool TrapALError;
|
||||
inline bool TrapALError{false};
|
||||
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
ALenum AL_APIENTRY EAXSet(
|
||||
const GUID* property_set_id,
|
||||
ALuint property_id,
|
||||
ALuint property_source_id,
|
||||
ALvoid* property_value,
|
||||
ALuint property_value_size) noexcept;
|
||||
auto AL_APIENTRY EAXSet(const GUID *property_set_id, ALuint property_id,
|
||||
ALuint source_id, ALvoid *value, ALuint value_size) noexcept -> ALenum;
|
||||
|
||||
ALenum AL_APIENTRY EAXGet(
|
||||
const GUID* property_set_id,
|
||||
ALuint property_id,
|
||||
ALuint property_source_id,
|
||||
ALvoid* property_value,
|
||||
ALuint property_value_size) noexcept;
|
||||
auto AL_APIENTRY EAXGet(const GUID *property_set_id, ALuint property_id,
|
||||
ALuint source_id, ALvoid *value, ALuint value_size) noexcept -> ALenum;
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
#endif /* ALC_CONTEXT_H */
|
||||
|
||||
Reference in New Issue
Block a user