aboutsummaryrefslogtreecommitdiffstats
path: root/al/error.cpp
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-11-28 12:51:46 +0100
committerSven Gothel <[email protected]>2023-11-28 12:51:46 +0100
commit1aaf4f070011490bcece50394b9b32dfa593fd9e (patch)
tree17d68284e401a35eea3d3a574d986d446a60763a /al/error.cpp
parent6e7cee4fa9a8af03f28ca26cd89f8357390dfc90 (diff)
parent571b546f35eead77ce109f8d4dd6c3de3199d573 (diff)
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'al/error.cpp')
-rw-r--r--al/error.cpp54
1 files changed, 45 insertions, 9 deletions
diff --git a/al/error.cpp b/al/error.cpp
index afa7019a..c2359477 100644
--- a/al/error.cpp
+++ b/al/error.cpp
@@ -29,25 +29,32 @@
#include <csignal>
#include <cstdarg>
#include <cstdio>
+#include <cstdlib>
#include <cstring>
+#include <limits>
#include <mutex>
+#include <vector>
#include "AL/al.h"
#include "AL/alc.h"
+#include "al/debug.h"
+#include "alc/alconfig.h"
#include "alc/context.h"
#include "almalloc.h"
+#include "alstring.h"
#include "core/except.h"
#include "core/logging.h"
+#include "direct_defs.h"
#include "opthelpers.h"
-#include "vector.h"
+#include "strutils.h"
bool TrapALError{false};
void ALCcontext::setError(ALenum errorCode, const char *msg, ...)
{
- auto message = al::vector<char>(256);
+ auto message = std::vector<char>(256);
va_list args, args2;
va_start(args, msg);
@@ -61,8 +68,13 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...)
va_end(args2);
va_end(args);
- if(msglen >= 0) msg = message.data();
- else msg = "<internal error constructing message>";
+ if(msglen >= 0)
+ msg = message.data();
+ else
+ {
+ msg = "<internal error constructing message>";
+ msglen = static_cast<int>(strlen(msg));
+ }
WARN("Error generated on context %p, code 0x%04x, \"%s\"\n",
decltype(std::declval<void*>()){this}, errorCode, msg);
@@ -79,15 +91,36 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...)
ALenum curerr{AL_NO_ERROR};
mLastError.compare_exchange_strong(curerr, errorCode);
+
+ debugMessage(DebugSource::API, DebugType::Error, 0, DebugSeverity::High,
+ {msg, static_cast<uint>(msglen)});
}
-AL_API ALenum AL_APIENTRY alGetError(void)
-START_API_FUNC
+/* Special-case alGetError since it (potentially) raises a debug signal and
+ * returns a non-default value for a null context.
+ */
+AL_API ALenum AL_APIENTRY alGetError(void) noexcept
{
- ContextRef context{GetContextRef()};
+ auto context = GetContextRef();
if(!context) UNLIKELY
{
- static constexpr ALenum deferror{AL_INVALID_OPERATION};
+ static const ALenum deferror{[](const char *envname, const char *optname) -> ALenum
+ {
+ auto optstr = al::getenv(envname);
+ if(!optstr)
+ optstr = ConfigValueStr(nullptr, "game_compat", optname);
+
+ if(optstr)
+ {
+ char *end{};
+ auto value = std::strtoul(optstr->c_str(), &end, 0);
+ if(end && *end == '\0' && value <= std::numeric_limits<ALenum>::max())
+ return static_cast<ALenum>(value);
+ ERR("Invalid default error value: \"%s\"", optstr->c_str());
+ }
+ return AL_INVALID_OPERATION;
+ }("__ALSOFT_DEFAULT_ERROR", "default-error")};
+
WARN("Querying error state on null context (implicitly 0x%04x)\n", deferror);
if(TrapALError)
{
@@ -100,7 +133,10 @@ START_API_FUNC
}
return deferror;
}
+ return alGetErrorDirect(context.get());
+}
+FORCE_ALIGN ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) noexcept
+{
return context->mLastError.exchange(AL_NO_ERROR);
}
-END_API_FUNC