2 // Copyright 2002 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.
7 // debug.cpp: Debugging utilities.
9 #include "common/debug.h"
20 #if defined(ANGLE_PLATFORM_ANDROID)
21 # include <android/log.h>
24 #if defined(ANGLE_PLATFORM_APPLE)
28 #if defined(ANGLE_PLATFORM_WINDOWS)
32 #include "anglebase/no_destructor.h"
33 #include "common/Optional.h"
34 #include "common/angleutils.h"
35 #include "common/entry_points_enum_autogen.h"
36 #include "common/system_utils.h"
44 DebugAnnotator *g_debugAnnotator = nullptr;
46 std::mutex *g_debugMutex = nullptr;
48 constexpr std::array<const char *, LOG_NUM_SEVERITIES> g_logSeverityNames = {
49 {"EVENT", "INFO", "WARN", "ERR", "FATAL"}};
51 constexpr const char *LogSeverityName(int severity)
53 return (severity >= 0 && severity < LOG_NUM_SEVERITIES) ? g_logSeverityNames[severity]
57 bool ShouldCreateLogMessage(LogSeverity severity)
59 #if defined(ANGLE_TRACE_ENABLED)
61 #elif defined(ANGLE_ENABLE_ASSERTS)
62 return severity == LOG_FATAL || severity == LOG_ERR || severity == LOG_WARN;
73 bool ShouldCreatePlatformLogMessage(LogSeverity severity)
75 #if defined(ANGLE_TRACE_ENABLED)
78 return severity != LOG_EVENT;
82 // This is never instantiated, it's just used for EAT_STREAM_PARAMETERS to an object of the correct
83 // type on the LHS of the unused part of the ternary operator.
84 std::ostream *gSwallowStream;
87 bool DebugAnnotationsActive()
89 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) || defined(ANGLE_ENABLE_DEBUG_TRACE)
90 return g_debugAnnotator != nullptr && g_debugAnnotator->getStatus();
96 bool ShouldBeginScopedEvent()
98 #if defined(ANGLE_ENABLE_ANNOTATOR_RUN_TIME_CHECKS)
99 return DebugAnnotationsActive();
102 #endif // defined(ANGLE_ENABLE_ANNOTATOR_RUN_TIME_CHECKS)
105 bool DebugAnnotationsInitialized()
107 return g_debugAnnotator != nullptr;
110 void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator)
112 UninitializeDebugAnnotations();
113 g_debugAnnotator = debugAnnotator;
116 void UninitializeDebugAnnotations()
118 // Pointer is not managed.
119 g_debugAnnotator = nullptr;
122 void InitializeDebugMutexIfNeeded()
124 if (g_debugMutex == nullptr)
126 g_debugMutex = new std::mutex();
130 std::mutex &GetDebugMutex()
132 ASSERT(g_debugMutex);
133 return *g_debugMutex;
136 ScopedPerfEventHelper::ScopedPerfEventHelper(gl::Context *context, angle::EntryPoint entryPoint)
137 : mContext(context), mEntryPoint(entryPoint), mFunctionName(nullptr), mCalledBeginEvent(false)
140 ScopedPerfEventHelper::~ScopedPerfEventHelper()
142 // EGL_Initialize() and EGL_Terminate() can change g_debugAnnotator. Must check the value of
143 // g_debugAnnotator and whether ScopedPerfEventHelper::begin() initiated a begine that must be
145 if (DebugAnnotationsInitialized() && mCalledBeginEvent)
147 g_debugAnnotator->endEvent(mContext, mFunctionName, mEntryPoint);
151 void ScopedPerfEventHelper::begin(const char *format, ...)
153 mFunctionName = GetEntryPointName(mEntryPoint);
156 va_start(vararg, format);
158 std::vector<char> buffer;
159 size_t len = FormatStringIntoVector(format, vararg, buffer);
162 ANGLE_LOG(EVENT) << std::string(&buffer[0], len);
163 if (DebugAnnotationsInitialized())
165 mCalledBeginEvent = true;
166 g_debugAnnotator->beginEvent(mContext, mEntryPoint, mFunctionName, buffer.data());
170 LogMessage::LogMessage(const char *file, const char *function, int line, LogSeverity severity)
171 : mFile(file), mFunction(function), mLine(line), mSeverity(severity)
173 // INFO() and EVENT() do not require additional function(line) info.
174 if (mSeverity > LOG_INFO)
176 const char *slash = std::max(strrchr(mFile, '/'), strrchr(mFile, '\\'));
177 mStream << (slash ? (slash + 1) : mFile) << ":" << mLine << " (" << mFunction << "): ";
181 LogMessage::~LogMessage()
183 std::unique_lock<std::mutex> lock;
184 if (g_debugMutex != nullptr)
186 lock = std::unique_lock<std::mutex>(*g_debugMutex);
189 if (DebugAnnotationsInitialized() && (mSeverity > LOG_INFO))
191 g_debugAnnotator->logMessage(*this);
195 Trace(getSeverity(), getMessage().c_str());
198 if (mSeverity == LOG_FATAL)
200 if (angle::IsDebuggerAttached())
202 angle::BreakDebugger();
211 void Trace(LogSeverity severity, const char *message)
213 if (!ShouldCreateLogMessage(severity))
218 std::string str(message);
220 if (DebugAnnotationsActive())
226 // Debugging logging done in ScopedPerfEventHelper
229 g_debugAnnotator->setMarker(message);
234 if (severity == LOG_FATAL || severity == LOG_ERR || severity == LOG_WARN ||
235 #if defined(ANGLE_ENABLE_TRACE_ANDROID_LOGCAT) || defined(ANGLE_ENABLE_TRACE_EVENTS)
236 severity == LOG_EVENT ||
238 severity == LOG_INFO)
240 #if defined(ANGLE_PLATFORM_ANDROID)
241 android_LogPriority android_priority = ANDROID_LOG_ERROR;
246 android_priority = ANDROID_LOG_INFO;
249 android_priority = ANDROID_LOG_WARN;
252 android_priority = ANDROID_LOG_ERROR;
255 android_priority = ANDROID_LOG_FATAL;
260 __android_log_print(android_priority, "ANGLE", "%s: %s\n", LogSeverityName(severity),
262 #elif defined(ANGLE_PLATFORM_APPLE)
263 if (__builtin_available(macOS 10.12, iOS 10.0, *))
265 os_log_type_t apple_log_type = OS_LOG_TYPE_DEFAULT;
269 apple_log_type = OS_LOG_TYPE_INFO;
272 apple_log_type = OS_LOG_TYPE_DEFAULT;
275 apple_log_type = OS_LOG_TYPE_ERROR;
278 // OS_LOG_TYPE_FAULT is too severe - grabs the entire process tree.
279 apple_log_type = OS_LOG_TYPE_ERROR;
284 os_log_with_type(OS_LOG_DEFAULT, apple_log_type, "ANGLE: %s: %s\n",
285 LogSeverityName(severity), str.c_str());
288 // Note: we use fprintf because <iostream> includes static initializers.
289 fprintf((severity >= LOG_WARN) ? stderr : stdout, "%s: %s\n", LogSeverityName(severity),
294 #if defined(ANGLE_PLATFORM_WINDOWS) && \
295 (defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) || !defined(NDEBUG))
296 # if !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
297 if (severity >= LOG_ERR)
298 # endif // !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
300 OutputDebugStringA(str.c_str());
301 OutputDebugStringA("\n");
305 #if defined(ANGLE_ENABLE_DEBUG_TRACE)
307 if (severity == LOG_EVENT || severity == LOG_WARN || severity == LOG_INFO)
311 # endif // defined(NDEBUG)
312 static angle::base::NoDestructor<std::ofstream> file(TRACE_OUTPUT_FILE, std::ofstream::app);
315 if (severity > LOG_EVENT)
317 *file << LogSeverityName(severity) << ": ";
319 *file << str << "\n";
322 #endif // defined(ANGLE_ENABLE_DEBUG_TRACE)
325 LogSeverity LogMessage::getSeverity() const
330 std::string LogMessage::getMessage() const
332 return mStream.str();
335 #if defined(ANGLE_PLATFORM_WINDOWS)
336 priv::FmtHexHelper<HRESULT, char> FmtHR(HRESULT value)
338 return priv::FmtHexHelper<HRESULT, char>("HRESULT: ", value);
341 priv::FmtHexHelper<DWORD, char> FmtErr(DWORD value)
343 return priv::FmtHexHelper<DWORD, char>("error: ", value);
345 #endif // defined(ANGLE_PLATFORM_WINDOWS)