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