diff options
Diffstat (limited to 'alc')
-rw-r--r-- | alc/alc.cpp | 21 | ||||
-rw-r--r-- | alc/context.cpp | 147 | ||||
-rw-r--r-- | alc/context.h | 9 | ||||
-rw-r--r-- | alc/inprogext.h | 3 |
4 files changed, 179 insertions, 1 deletions
diff --git a/alc/alc.cpp b/alc/alc.cpp index 33531afb..b6dc111d 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -461,6 +461,8 @@ const struct { DECL(alBufferDataStatic), DECL(alDebugMessageCallbackSOFT), + DECL(alDebugMessageInsertSOFT), + DECL(alDebugMessageControlSOFT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), @@ -917,7 +919,26 @@ constexpr struct { DECL(AL_FORMAT_UHJ4CHN_MULAW_SOFT), DECL(AL_FORMAT_UHJ4CHN_ALAW_SOFT), + DECL(AL_DONT_CARE_SOFT), DECL(AL_DEBUG_OUTPUT_SOFT), + DECL(AL_DEBUG_CALLBACK_FUNCTION_SOFT), + DECL(AL_DEBUG_CALLBACK_USER_PARAM_SOFT), + DECL(AL_DEBUG_SOURCE_API_SOFT), + DECL(AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT), + DECL(AL_DEBUG_SOURCE_THIRD_PARTY_SOFT), + DECL(AL_DEBUG_SOURCE_APPLICATION_SOFT), + DECL(AL_DEBUG_SOURCE_OTHER_SOFT), + DECL(AL_DEBUG_TYPE_ERROR_SOFT), + DECL(AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT), + DECL(AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT), + DECL(AL_DEBUG_TYPE_PORTABILITY_SOFT), + DECL(AL_DEBUG_TYPE_PERFORMANCE_SOFT), + DECL(AL_DEBUG_TYPE_MARKER_SOFT), + DECL(AL_DEBUG_TYPE_OTHER_SOFT), + DECL(AL_DEBUG_SEVERITY_HIGH_SOFT), + DECL(AL_DEBUG_SEVERITY_MEDIUM_SOFT), + DECL(AL_DEBUG_SEVERITY_LOW_SOFT), + DECL(AL_DEBUG_SEVERITY_NOTIFICATION_SOFT), DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), diff --git a/alc/context.cpp b/alc/context.cpp index e2a2e2d2..3f7b456d 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -4,11 +4,13 @@ #include "context.h" #include <algorithm> +#include <array> #include <functional> #include <limits> #include <numeric> #include <stddef.h> #include <stdexcept> +#include <utility> #include "AL/efx.h" @@ -19,6 +21,7 @@ #include "al/listener.h" #include "albit.h" #include "alc/alu.h" +#include "alspan.h" #include "core/async_event.h" #include "core/device.h" #include "core/effectslot.h" @@ -27,6 +30,7 @@ #include "core/voice_change.h" #include "device.h" #include "ringbuffer.h" +#include "threads.h" #include "vecmat.h" #ifdef ALSOFT_EAX @@ -295,11 +299,45 @@ void ALCcontext::applyAllUpdates() mHoldUpdates.store(false, std::memory_order_release); } + void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message) { + static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); + std::lock_guard<std::mutex> _{mDebugCbLock}; - if(!mDebugEnabled.load()) + if(!mDebugEnabled.load()) UNLIKELY + return; + + uint filter{0}; + switch(source) + { + case DebugSource::API: filter |= 1<<(DebugSourceBase+0); break; + case DebugSource::System: filter |= 1<<(DebugSourceBase+1); break; + case DebugSource::ThirdParty: filter |= 1<<(DebugSourceBase+2); break; + case DebugSource::Application: filter |= 1<<(DebugSourceBase+3); break; + case DebugSource::Other: filter |= 1<<(DebugSourceBase+4); break; + } + switch(type) + { + case DebugType::Error: filter |= 1<<(DebugTypeBase+0); break; + case DebugType::DeprecatedBehavior: filter |= 1<<(DebugTypeBase+1); break; + case DebugType::UndefinedBehavior: filter |= 1<<(DebugTypeBase+2); break; + case DebugType::Portability: filter |= 1<<(DebugTypeBase+3); break; + case DebugType::Performance: filter |= 1<<(DebugTypeBase+4); break; + case DebugType::Marker: filter |= 1<<(DebugTypeBase+5); break; + case DebugType::Other: filter |= 1<<(DebugTypeBase+6); break; + } + switch(severity) + { + case DebugSeverity::High: filter |= 1<<(DebugSeverityBase+0); break; + case DebugSeverity::Medium: filter |= 1<<(DebugSeverityBase+1); break; + case DebugSeverity::Low: filter |= 1<<(DebugSeverityBase+2); break; + case DebugSeverity::Notification: filter |= 1<<(DebugSeverityBase+3); break; + } + + auto iter = std::lower_bound(mDebugFilters.cbegin(), mDebugFilters.cend(), filter); + if(iter != mDebugFilters.cend() && *iter == filter) return; if(mDebugCb) @@ -371,6 +409,113 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type context->debugMessage(dsource, dtype, id, dseverity, length, message); } + +namespace { + +template<typename T, T ...Vals> +constexpr auto make_array(std::integer_sequence<T, Vals...>) +{ return std::array<T,sizeof...(Vals)>{Vals...}; } + +template<typename T, size_t N, typename Indices = std::make_integer_sequence<T,N>> +constexpr auto make_array() +{ return make_array(Indices{}); } + +} // namespace + +FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, + ALsizei count, const ALuint *ids, ALboolean enable) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + if(count > 0) + { + if(!ids) + return context->setError(AL_INVALID_VALUE, "IDs is null with non-0 count"); + if(source == AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug source cannot be AL_DONT_CARE_SOFT with IDs"); + if(type == AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug type cannot be AL_DONT_CARE_SOFT with IDs"); + if(severity != AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug severity must be AL_DONT_CARE_SOFT with IDs"); + + return context->setError(AL_INVALID_VALUE, "Debug ID filtering not supported"); + return; + } + + if(enable != AL_TRUE && enable != AL_FALSE) + return context->setError(AL_INVALID_VALUE, "Invalid debug enable %d", enable); + + static constexpr size_t ElemCount{DebugSourceCount + DebugTypeCount + DebugSeverityCount}; + static constexpr auto Values = make_array<uint,ElemCount>(); + + al::span<const uint> srcIndices{al::as_span(Values).subspan<DebugSourceBase,DebugSourceCount>()}; + switch(source) + { + case AL_DEBUG_SOURCE_API_SOFT: srcIndices = srcIndices.subspan(0, 1); break; + case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: srcIndices = srcIndices.subspan(1, 1); break; + case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: srcIndices = srcIndices.subspan(2, 1); break; + case AL_DEBUG_SOURCE_APPLICATION_SOFT: srcIndices = srcIndices.subspan(3, 1); break; + case AL_DEBUG_SOURCE_OTHER_SOFT: srcIndices = srcIndices.subspan(4, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug source 0x%04x", source); + } + + al::span<const uint> typeIndices{al::as_span(Values).subspan<DebugTypeBase,DebugTypeCount>()}; + switch(type) + { + case AL_DEBUG_TYPE_ERROR_SOFT: typeIndices = typeIndices.subspan(0, 1); break; + case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(1, 1); break; + case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(2, 1); break; + case AL_DEBUG_TYPE_PORTABILITY_SOFT: typeIndices = typeIndices.subspan(3, 1); break; + case AL_DEBUG_TYPE_PERFORMANCE_SOFT: typeIndices = typeIndices.subspan(4, 1); break; + case AL_DEBUG_TYPE_MARKER_SOFT: typeIndices = typeIndices.subspan(5, 1); break; + case AL_DEBUG_TYPE_OTHER_SOFT: typeIndices = typeIndices.subspan(6, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug type 0x%04x", type); + } + + al::span<const uint> svrIndices{al::as_span(Values).subspan<DebugSeverityBase,DebugSeverityCount>()}; + switch(severity) + { + case AL_DEBUG_SEVERITY_HIGH_SOFT: svrIndices = svrIndices.subspan(0, 1); break; + case AL_DEBUG_SEVERITY_MEDIUM_SOFT: svrIndices = svrIndices.subspan(1, 1); break; + case AL_DEBUG_SEVERITY_LOW_SOFT: svrIndices = svrIndices.subspan(2, 1); break; + case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: svrIndices = svrIndices.subspan(3, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug severity 0x%04x", severity); + } + + std::lock_guard<std::mutex> _{context->mDebugCbLock}; + auto apply_filter = [enable,&context](const uint filter) + { + auto iter = std::lower_bound(context->mDebugFilters.cbegin(), + context->mDebugFilters.cend(), filter); + if(enable && (iter == context->mDebugFilters.cend() || *iter != filter)) + context->mDebugFilters.insert(iter, filter); + else if(!enable && iter != context->mDebugFilters.cend() && *iter == filter) + context->mDebugFilters.erase(iter); + }; + auto apply_severity = [apply_filter,svrIndices](const uint filter) + { + std::for_each(svrIndices.cbegin(), svrIndices.cend(), + [apply_filter,filter](const uint idx){ apply_filter(filter | (1<<idx)); }); + }; + auto apply_type = [apply_severity,typeIndices](const uint filter) + { + std::for_each(typeIndices.cbegin(), typeIndices.cend(), + [apply_severity,filter](const uint idx){ apply_severity(filter | (1<<idx)); }); + }; + std::for_each(srcIndices.cbegin(), srcIndices.cend(), + [apply_type](const uint idx){ apply_type(1<<idx); }); +} + #ifdef ALSOFT_EAX namespace { diff --git a/alc/context.h b/alc/context.h index 0dd9efb0..8613c2a3 100644 --- a/alc/context.h +++ b/alc/context.h @@ -35,6 +35,7 @@ struct ALsource; using uint = unsigned int; +constexpr size_t DebugSourceBase{0}; enum class DebugSource : ALenum { API = AL_DEBUG_SOURCE_API_SOFT, System = AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT, @@ -42,6 +43,9 @@ enum class DebugSource : ALenum { Application = AL_DEBUG_SOURCE_APPLICATION_SOFT, Other = AL_DEBUG_SOURCE_OTHER_SOFT, }; +constexpr size_t DebugSourceCount{5}; + +constexpr size_t DebugTypeBase{DebugSourceBase + DebugSourceCount}; enum class DebugType : ALenum { Error = AL_DEBUG_TYPE_ERROR_SOFT, DeprecatedBehavior = AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT, @@ -51,12 +55,16 @@ enum class DebugType : ALenum { Marker = AL_DEBUG_TYPE_MARKER_SOFT, Other = AL_DEBUG_TYPE_OTHER_SOFT, }; +constexpr size_t DebugTypeCount{7}; + +constexpr size_t DebugSeverityBase{DebugTypeBase + DebugTypeCount}; enum class DebugSeverity : ALenum { High = AL_DEBUG_SEVERITY_HIGH_SOFT, Medium = AL_DEBUG_SEVERITY_MEDIUM_SOFT, Low = AL_DEBUG_SEVERITY_LOW_SOFT, Notification = AL_DEBUG_SEVERITY_NOTIFICATION_SOFT, }; +constexpr size_t DebugSeverityCount{4}; struct SourceSubList { @@ -118,6 +126,7 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext>, ContextBase { std::mutex mDebugCbLock; ALDEBUGPROCSOFT mDebugCb{}; void *mDebugParam{nullptr}; + std::vector<uint> mDebugFilters; ALlistener mListener{}; diff --git a/alc/inprogext.h b/alc/inprogext.h index 53dc9f0c..a4e2c353 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -56,6 +56,7 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #ifndef AL_SOFT_debug #define AL_SOFT_debug +#define AL_DONT_CARE_SOFT 0x0002 #define AL_DEBUG_OUTPUT_SOFT 0x19B2 #define AL_DEBUG_CALLBACK_FUNCTION_SOFT 0x19B3 #define AL_DEBUG_CALLBACK_USER_PARAM_SOFT 0x19B4 @@ -79,9 +80,11 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * typedef void (AL_APIENTRY*ALDEBUGPROCSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam); typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKSOFT)(ALDEBUGPROCSOFT callback, void *userParam); typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLSOFT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable); #ifdef AL_ALEXT_PROTOTYPES void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept; void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; +void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept; #endif #endif |