1 // 2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // debug.h: Debugging utilities. 8 9 #ifndef COMMON_DEBUG_H_ 10 #define COMMON_DEBUG_H_ 11 12 #include <assert.h> 13 #include <stdio.h> 14 #include <string> 15 16 #include "common/angleutils.h" 17 18 #if !defined(TRACE_OUTPUT_FILE) 19 #define TRACE_OUTPUT_FILE "angle_debug.txt" 20 #endif 21 22 namespace gl 23 { 24 25 enum MessageType 26 { 27 MESSAGE_TRACE, 28 MESSAGE_FIXME, 29 MESSAGE_ERR, 30 MESSAGE_EVENT, 31 }; 32 33 // Outputs text to the debugging log, or the debugging window 34 void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...); 35 36 // Pairs a D3D begin event with an end event. 37 class ScopedPerfEventHelper : angle::NonCopyable 38 { 39 public: 40 ScopedPerfEventHelper(const char* format, ...); 41 ~ScopedPerfEventHelper(); 42 }; 43 44 // Wraps the D3D9/D3D11 debug annotation functions. 45 class DebugAnnotator : angle::NonCopyable 46 { 47 public: DebugAnnotator()48 DebugAnnotator() { }; ~DebugAnnotator()49 virtual ~DebugAnnotator() { }; 50 virtual void beginEvent(const wchar_t *eventName) = 0; 51 virtual void endEvent() = 0; 52 virtual void setMarker(const wchar_t *markerName) = 0; 53 virtual bool getStatus() = 0; 54 }; 55 56 void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator); 57 void UninitializeDebugAnnotations(); 58 bool DebugAnnotationsActive(); 59 60 // This class is used to explicitly ignore values in the conditional logging macros. This avoids 61 // compiler warnings like "value computed is not used" and "statement has no effect". 62 class LogMessageVoidify 63 { 64 public: LogMessageVoidify()65 LogMessageVoidify() {} 66 // This has to be an operator with a precedence lower than << but higher than ?: 67 void operator&(std::ostream &) {} 68 }; 69 70 // This can be any ostream, it is unused, but needs to be a valid reference. 71 std::ostream &DummyStream(); 72 73 } // namespace gl 74 75 #if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) 76 #define ANGLE_TRACE_ENABLED 77 #endif 78 79 #define ANGLE_EMPTY_STATEMENT for (;;) break 80 #if !defined(NDEBUG) || defined(ANGLE_ENABLE_RELEASE_ASSERTS) 81 #define ANGLE_ENABLE_ASSERTS 82 #endif 83 84 // A macro to output a trace of a function call and its arguments to the debugging log 85 #if defined(ANGLE_TRACE_ENABLED) 86 #define TRACE(message, ...) gl::trace(true, gl::MESSAGE_TRACE, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) 87 #else 88 #define TRACE(message, ...) (void(0)) 89 #endif 90 91 // A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing. 92 #if defined(ANGLE_TRACE_ENABLED) 93 #define FIXME(message, ...) gl::trace(false, gl::MESSAGE_FIXME, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) 94 #else 95 #define FIXME(message, ...) (void(0)) 96 #endif 97 98 // A macro to output a function call and its arguments to the debugging log, in case of error. 99 #if defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS) 100 #define ERR(message, ...) gl::trace(false, gl::MESSAGE_ERR, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) 101 #else 102 #define ERR(message, ...) (void(0)) 103 #endif 104 105 // A macro to log a performance event around a scope. 106 #if defined(ANGLE_TRACE_ENABLED) 107 #if defined(_MSC_VER) 108 #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__); 109 #else 110 #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper("%s" message "\n", __FUNCTION__, ##__VA_ARGS__); 111 #endif // _MSC_VER 112 #else 113 #define EVENT(message, ...) (void(0)) 114 #endif 115 116 #if defined(ANGLE_TRACE_ENABLED) 117 #undef ANGLE_TRACE_ENABLED 118 #endif 119 120 #if defined(COMPILER_GCC) || defined(__clang__) 121 #define ANGLE_CRASH() __builtin_trap() 122 #else 123 #define ANGLE_CRASH() ((void)(*(volatile char *)0 = 0)) 124 #endif 125 126 #if !defined(NDEBUG) 127 #define ANGLE_ASSERT_IMPL(expression) assert(expression) 128 #else 129 // TODO(jmadill): Detect if debugger is attached and break. 130 #define ANGLE_ASSERT_IMPL(expression) ANGLE_CRASH() 131 #endif // !defined(NDEBUG) 132 133 // Helper macro which avoids evaluating the arguments to a stream if the condition doesn't hold. 134 // Condition is evaluated once and only once. 135 #define ANGLE_LAZY_STREAM(stream, condition) \ 136 !(condition) ? static_cast<void>(0) : ::gl::LogMessageVoidify() & (stream) 137 138 #if defined(NDEBUG) && !defined(ANGLE_ENABLE_ASSERTS) 139 #define ANGLE_ASSERTS_ON 0 140 #else 141 #define ANGLE_ASSERTS_ON 1 142 #endif 143 144 // A macro asserting a condition and outputting failures to the debug log 145 #if ANGLE_ASSERTS_ON 146 #define ASSERT(expression) \ 147 (expression ? static_cast<void>(0) \ 148 : (ERR("\t! Assert failed in %s(%d): %s\n", __FUNCTION__, __LINE__, #expression), \ 149 ANGLE_ASSERT_IMPL(expression))) 150 #else 151 #define ASSERT(condition) \ 152 ANGLE_LAZY_STREAM(::gl::DummyStream(), ANGLE_ASSERTS_ON ? !(condition) : false) \ 153 << "Check failed: " #condition ". " 154 #endif // ANGLE_ASSERTS_ON 155 156 #define UNUSED_VARIABLE(variable) ((void)variable) 157 158 // A macro to indicate unimplemented functionality 159 #ifndef NOASSERT_UNIMPLEMENTED 160 #define NOASSERT_UNIMPLEMENTED 1 161 #endif 162 163 #define UNIMPLEMENTED() \ 164 { \ 165 ERR("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \ 166 ASSERT(NOASSERT_UNIMPLEMENTED); \ 167 } \ 168 ANGLE_EMPTY_STATEMENT 169 170 // A macro for code which is not expected to be reached under valid assumptions 171 #define UNREACHABLE() \ 172 (ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__), ASSERT(false)) 173 174 #endif // COMMON_DEBUG_H_ 175