summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/common/debug.h
diff options
context:
space:
mode:
authorMiguel Costa <miguel.costa@qt.io>2018-06-26 16:56:45 +0200
committerAndre de la Rocha <andre.rocha@qt.io>2018-10-13 21:36:35 +0000
commit0a7aebadfbb3534284546aa3ca8612314c08f136 (patch)
treee94ee33ae3bb9b96fc3047c6455d47ac4920bfbf /src/3rdparty/angle/src/common/debug.h
parent656e89f875ad2008ca16cc673b687a22daa294c9 (diff)
Update ANGLE to chromium/3280
Change-Id: I0802c0d7486f772d361f87a544d6c5af937f4ca1 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'src/3rdparty/angle/src/common/debug.h')
-rw-r--r--src/3rdparty/angle/src/common/debug.h266
1 files changed, 201 insertions, 65 deletions
diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h
index 64cfef4cd9..290a4e8bb7 100644
--- a/src/3rdparty/angle/src/common/debug.h
+++ b/src/3rdparty/angle/src/common/debug.h
@@ -11,6 +11,10 @@
#include <assert.h>
#include <stdio.h>
+
+#include <ios>
+#include <iomanip>
+#include <sstream>
#include <string>
#include "common/angleutils.h"
@@ -22,17 +26,6 @@
namespace gl
{
-enum MessageType
-{
- MESSAGE_TRACE,
- MESSAGE_FIXME,
- MESSAGE_ERR,
- MESSAGE_EVENT,
-};
-
-// Outputs text to the debugging log, or the debugging window
-void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...);
-
// Pairs a D3D begin event with an end event.
class ScopedPerfEventHelper : angle::NonCopyable
{
@@ -41,50 +34,177 @@ class ScopedPerfEventHelper : angle::NonCopyable
~ScopedPerfEventHelper();
};
+using LogSeverity = int;
+// Note: the log severities are used to index into the array of names,
+// see g_logSeverityNames.
+constexpr LogSeverity LOG_EVENT = 0;
+constexpr LogSeverity LOG_WARN = 1;
+constexpr LogSeverity LOG_ERR = 2;
+constexpr LogSeverity LOG_NUM_SEVERITIES = 3;
+
+void Trace(LogSeverity severity, const char *message);
+
+// This class more or less represents a particular log message. You
+// create an instance of LogMessage and then stream stuff to it.
+// When you finish streaming to it, ~LogMessage is called and the
+// full message gets streamed to the appropriate destination.
+//
+// You shouldn't actually use LogMessage's constructor to log things,
+// though. You should use the ERR() and WARN() macros.
+class LogMessage : angle::NonCopyable
+{
+ public:
+ // Used for ANGLE_LOG(severity).
+ LogMessage(const char *function, int line, LogSeverity severity);
+ ~LogMessage();
+ std::ostream &stream() { return mStream; }
+
+ LogSeverity getSeverity() const;
+ std::string getMessage() const;
+
+ private:
+ const char *mFunction;
+ const int mLine;
+ const LogSeverity mSeverity;
+
+ std::ostringstream mStream;
+};
+
// Wraps the D3D9/D3D11 debug annotation functions.
+// Also handles redirecting logging destination.
class DebugAnnotator : angle::NonCopyable
{
public:
- DebugAnnotator() { };
+ DebugAnnotator(){};
virtual ~DebugAnnotator() { };
virtual void beginEvent(const wchar_t *eventName) = 0;
virtual void endEvent() = 0;
virtual void setMarker(const wchar_t *markerName) = 0;
virtual bool getStatus() = 0;
+ // Log Message Handler that gets passed every log message,
+ // when debug annotations are initialized,
+ // replacing default handling by LogMessage.
+ virtual void logMessage(const LogMessage &msg) const = 0;
};
void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator);
void UninitializeDebugAnnotations();
bool DebugAnnotationsActive();
+bool DebugAnnotationsInitialized();
+
+namespace priv
+{
+// This class is used to explicitly ignore values in the conditional logging macros. This avoids
+// compiler warnings like "value computed is not used" and "statement has no effect".
+class LogMessageVoidify
+{
+ public:
+ LogMessageVoidify() {}
+ // This has to be an operator with a precedence lower than << but higher than ?:
+ void operator&(std::ostream &) {}
+};
+
+// Used by ANGLE_LOG_IS_ON to lazy-evaluate stream arguments.
+bool ShouldCreatePlatformLogMessage(LogSeverity severity);
+
+template <int N, typename T>
+std::ostream &FmtHex(std::ostream &os, T value)
+{
+ os << "0x";
+
+ std::ios_base::fmtflags oldFlags = os.flags();
+ std::streamsize oldWidth = os.width();
+ std::ostream::char_type oldFill = os.fill();
+
+ os << std::hex << std::uppercase << std::setw(N) << std::setfill('0') << value;
+
+ os.flags(oldFlags);
+ os.width(oldWidth);
+ os.fill(oldFill);
+
+ return os;
+}
+} // namespace priv
+
+#if defined(ANGLE_PLATFORM_WINDOWS)
+class FmtHR
+{
+ public:
+ explicit FmtHR(HRESULT hresult) : mHR(hresult) {}
+ private:
+ HRESULT mHR;
+ friend std::ostream &operator<<(std::ostream &os, const FmtHR &fmt);
+};
+
+class FmtErr
+{
+ public:
+ explicit FmtErr(DWORD err) : mErr(err) {}
+
+ private:
+ DWORD mErr;
+ friend std::ostream &operator<<(std::ostream &os, const FmtErr &fmt);
+};
+#endif // defined(ANGLE_PLATFORM_WINDOWS)
+
+template <typename T>
+std::ostream &FmtHexShort(std::ostream &os, T value)
+{
+ return priv::FmtHex<4>(os, value);
+}
+template <typename T>
+std::ostream &FmtHexInt(std::ostream &os, T value)
+{
+ return priv::FmtHex<8>(os, value);
}
+// A few definitions of macros that don't generate much code. These are used
+// by ANGLE_LOG(). Since these are used all over our code, it's
+// better to have compact code for these operations.
+#define COMPACT_ANGLE_LOG_EX_EVENT(ClassName, ...) \
+ ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_EVENT, ##__VA_ARGS__)
+#define COMPACT_ANGLE_LOG_EX_WARN(ClassName, ...) \
+ ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_WARN, ##__VA_ARGS__)
+#define COMPACT_ANGLE_LOG_EX_ERR(ClassName, ...) \
+ ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_ERR, ##__VA_ARGS__)
+
+#define COMPACT_ANGLE_LOG_EVENT COMPACT_ANGLE_LOG_EX_EVENT(LogMessage)
+#define COMPACT_ANGLE_LOG_WARN COMPACT_ANGLE_LOG_EX_WARN(LogMessage)
+#define COMPACT_ANGLE_LOG_ERR COMPACT_ANGLE_LOG_EX_ERR(LogMessage)
+
+#define ANGLE_LOG_IS_ON(severity) (::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_##severity))
+
+// Helper macro which avoids evaluating the arguments to a stream if the condition doesn't hold.
+// Condition is evaluated once and only once.
+#define ANGLE_LAZY_STREAM(stream, condition) \
+ !(condition) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify() & (stream)
+
+// We use the preprocessor's merging operator, "##", so that, e.g.,
+// ANGLE_LOG(EVENT) becomes the token COMPACT_ANGLE_LOG_EVENT. There's some funny
+// subtle difference between ostream member streaming functions (e.g.,
+// ostream::operator<<(int) and ostream non-member streaming functions
+// (e.g., ::operator<<(ostream&, string&): it turns out that it's
+// impossible to stream something like a string directly to an unnamed
+// ostream. We employ a neat hack by calling the stream() member
+// function of LogMessage which seems to avoid the problem.
+#define ANGLE_LOG_STREAM(severity) COMPACT_ANGLE_LOG_##severity.stream()
+
+#define ANGLE_LOG(severity) ANGLE_LAZY_STREAM(ANGLE_LOG_STREAM(severity), ANGLE_LOG_IS_ON(severity))
+
+} // namespace gl
+
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define ANGLE_TRACE_ENABLED
#endif
#define ANGLE_EMPTY_STATEMENT for (;;) break
-
-// A macro to output a trace of a function call and its arguments to the debugging log
-#if defined(ANGLE_TRACE_ENABLED)
-#define TRACE(message, ...) gl::trace(true, gl::MESSAGE_TRACE, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else
-#define TRACE(message, ...) (void(0))
-#endif
-
-// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
-#if defined(ANGLE_TRACE_ENABLED)
-#define FIXME(message, ...) gl::trace(false, gl::MESSAGE_FIXME, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else
-#define FIXME(message, ...) (void(0))
+#if !defined(NDEBUG) || defined(ANGLE_ENABLE_RELEASE_ASSERTS)
+#define ANGLE_ENABLE_ASSERTS
#endif
-// A macro to output a function call and its arguments to the debugging log, in case of error.
-#if defined(ANGLE_TRACE_ENABLED)
-#define ERR(message, ...) gl::trace(false, gl::MESSAGE_ERR, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else
-#define ERR(message, ...) (void(0))
-#endif
+#define WARN() ANGLE_LOG(WARN)
+#define ERR() ANGLE_LOG(ERR)
// A macro to log a performance event around a scope.
#if defined(ANGLE_TRACE_ENABLED)
@@ -97,54 +217,70 @@ bool DebugAnnotationsActive();
#define EVENT(message, ...) (void(0))
#endif
-#if defined(ANGLE_TRACE_ENABLED)
-#undef ANGLE_TRACE_ENABLED
+#if defined(COMPILER_GCC) || defined(__clang__)
+#define ANGLE_CRASH() __builtin_trap()
+#else
+#define ANGLE_CRASH() ((void)(*(volatile char *)0 = 0))
#endif
-// A macro asserting a condition and outputting failures to the debug log
#if !defined(NDEBUG)
-#define ASSERT(expression) { \
- if(!(expression)) \
- ERR("\t! Assert failed in %s(%d): %s\n", __FUNCTION__, __LINE__, #expression); \
- assert(expression); \
- } ANGLE_EMPTY_STATEMENT
-#define UNUSED_ASSERTION_VARIABLE(variable)
+#define ANGLE_ASSERT_IMPL(expression) assert(expression)
#else
-#define ASSERT(expression) (void(0))
-#define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable)
-#endif
+// TODO(jmadill): Detect if debugger is attached and break.
+#define ANGLE_ASSERT_IMPL(expression) ANGLE_CRASH()
+#endif // !defined(NDEBUG)
+
+// A macro asserting a condition and outputting failures to the debug log
+#if defined(ANGLE_ENABLE_ASSERTS)
+#define ASSERT(expression) \
+ (expression ? static_cast<void>(0) : ((ERR() << "\t! Assert failed in " << __FUNCTION__ << "(" \
+ << __LINE__ << "): " << #expression), \
+ ANGLE_ASSERT_IMPL(expression)))
+#else
+// These are just dummy values.
+#define COMPACT_ANGLE_LOG_EX_ASSERT(ClassName, ...) \
+ COMPACT_ANGLE_LOG_EX_EVENT(ClassName, ##__VA_ARGS__)
+#define COMPACT_ANGLE_LOG_ASSERT COMPACT_ANGLE_LOG_EVENT
+namespace gl
+{
+constexpr LogSeverity LOG_ASSERT = LOG_EVENT;
+} // namespace gl
+
+#define ASSERT(condition) \
+ ANGLE_LAZY_STREAM(ANGLE_LOG_STREAM(ASSERT), false ? !(condition) : false) \
+ << "Check failed: " #condition ". "
+#endif // defined(ANGLE_ENABLE_ASSERTS)
#define UNUSED_VARIABLE(variable) ((void)variable)
// A macro to indicate unimplemented functionality
-
-#if defined (ANGLE_TEST_CONFIG)
+#ifndef NOASSERT_UNIMPLEMENTED
#define NOASSERT_UNIMPLEMENTED 1
#endif
-// Define NOASSERT_UNIMPLEMENTED to non zero to skip the assert fail in the unimplemented checks
-// This will allow us to test with some automated test suites (eg dEQP) without crashing
-#ifndef NOASSERT_UNIMPLEMENTED
-#define NOASSERT_UNIMPLEMENTED 0
-#endif
+#if defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
+#define UNIMPLEMENTED() \
+ { \
+ ERR() << "\t! Unimplemented: " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ \
+ << ")"; \
+ ASSERT(NOASSERT_UNIMPLEMENTED); \
+ } \
+ ANGLE_EMPTY_STATEMENT
-#if !defined(NDEBUG)
-#define UNIMPLEMENTED() { \
- FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \
- assert(NOASSERT_UNIMPLEMENTED); \
- } ANGLE_EMPTY_STATEMENT
+// A macro for code which is not expected to be reached under valid assumptions
+#define UNREACHABLE() \
+ ((ERR() << "\t! Unreachable reached: " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ \
+ << ")"), \
+ ASSERT(false))
#else
- #define UNIMPLEMENTED() FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__)
-#endif
+#define UNIMPLEMENTED() \
+ { \
+ ASSERT(NOASSERT_UNIMPLEMENTED); \
+ } \
+ ANGLE_EMPTY_STATEMENT
// A macro for code which is not expected to be reached under valid assumptions
-#if !defined(NDEBUG)
-#define UNREACHABLE() { \
- ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
- assert(false); \
- } ANGLE_EMPTY_STATEMENT
-#else
- #define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__)
-#endif
+#define UNREACHABLE() ASSERT(false)
+#endif // defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
#endif // COMMON_DEBUG_H_