diff options
Diffstat (limited to 'gfx/angle/checkout/src/common/debug.cpp')
-rw-r--r-- | gfx/angle/checkout/src/common/debug.cpp | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/common/debug.cpp b/gfx/angle/checkout/src/common/debug.cpp new file mode 100644 index 0000000000..23424d443a --- /dev/null +++ b/gfx/angle/checkout/src/common/debug.cpp @@ -0,0 +1,349 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// debug.cpp: Debugging utilities. + +#include "common/debug.h" + +#include <stdarg.h> + +#include <array> +#include <cstdio> +#include <cstring> +#include <fstream> +#include <ostream> +#include <vector> + +#if defined(ANGLE_PLATFORM_ANDROID) +# include <android/log.h> +#endif + +#if defined(ANGLE_PLATFORM_APPLE) +# include <os/log.h> +#endif + +#if defined(ANGLE_PLATFORM_WINDOWS) +# include <windows.h> +#endif + +#include "anglebase/no_destructor.h" +#include "common/Optional.h" +#include "common/angleutils.h" +#include "common/entry_points_enum_autogen.h" +#include "common/system_utils.h" + +namespace gl +{ + +namespace +{ + +DebugAnnotator *g_debugAnnotator = nullptr; + +std::mutex *g_debugMutex = nullptr; + +constexpr std::array<const char *, LOG_NUM_SEVERITIES> g_logSeverityNames = { + {"EVENT", "INFO", "WARN", "ERR", "FATAL"}}; + +constexpr const char *LogSeverityName(int severity) +{ + return (severity >= 0 && severity < LOG_NUM_SEVERITIES) ? g_logSeverityNames[severity] + : "UNKNOWN"; +} + +bool ShouldCreateLogMessage(LogSeverity severity) +{ +#if defined(ANGLE_TRACE_ENABLED) + return true; +#elif defined(ANGLE_ENABLE_ASSERTS) + return severity == LOG_FATAL || severity == LOG_ERR || severity == LOG_WARN; +#else + return severity == LOG_FATAL || severity == LOG_ERR; +#endif +} + +} // namespace + +namespace priv +{ + +bool ShouldCreatePlatformLogMessage(LogSeverity severity) +{ +#if defined(ANGLE_TRACE_ENABLED) + return true; +#else + return severity != LOG_EVENT; +#endif +} + +// This is never instantiated, it's just used for EAT_STREAM_PARAMETERS to an object of the correct +// type on the LHS of the unused part of the ternary operator. +std::ostream *gSwallowStream; +} // namespace priv + +bool DebugAnnotationsActive(const gl::Context *context) +{ +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) || defined(ANGLE_ENABLE_DEBUG_TRACE) + return g_debugAnnotator != nullptr && g_debugAnnotator->getStatus(context); +#else + return false; +#endif +} + +bool ShouldBeginScopedEvent(const gl::Context *context) +{ +#if defined(ANGLE_ENABLE_ANNOTATOR_RUN_TIME_CHECKS) + return DebugAnnotationsActive(context); +#else + return true; +#endif // defined(ANGLE_ENABLE_ANNOTATOR_RUN_TIME_CHECKS) +} + +bool DebugAnnotationsInitialized() +{ + return g_debugAnnotator != nullptr; +} + +void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator) +{ + UninitializeDebugAnnotations(); + g_debugAnnotator = debugAnnotator; +} + +void UninitializeDebugAnnotations() +{ + // Pointer is not managed. + g_debugAnnotator = nullptr; +} + +void InitializeDebugMutexIfNeeded() +{ + if (g_debugMutex == nullptr) + { + g_debugMutex = new std::mutex(); + } +} + +std::mutex &GetDebugMutex() +{ + ASSERT(g_debugMutex); + return *g_debugMutex; +} + +ScopedPerfEventHelper::ScopedPerfEventHelper(gl::Context *context, angle::EntryPoint entryPoint) + : mContext(context), mEntryPoint(entryPoint), mFunctionName(nullptr), mCalledBeginEvent(false) +{} + +ScopedPerfEventHelper::~ScopedPerfEventHelper() +{ + // EGL_Initialize() and EGL_Terminate() can change g_debugAnnotator. Must check the value of + // g_debugAnnotator and whether ScopedPerfEventHelper::begin() initiated a begine that must be + // ended now. + if (DebugAnnotationsInitialized() && mCalledBeginEvent) + { + g_debugAnnotator->endEvent(mContext, mFunctionName, mEntryPoint); + } +} + +void ScopedPerfEventHelper::begin(const char *format, ...) +{ + mFunctionName = GetEntryPointName(mEntryPoint); + + va_list vararg; + va_start(vararg, format); + + std::vector<char> buffer; + size_t len = FormatStringIntoVector(format, vararg, buffer); + va_end(vararg); + + ANGLE_LOG(EVENT) << std::string(&buffer[0], len); + if (DebugAnnotationsInitialized()) + { + mCalledBeginEvent = true; + g_debugAnnotator->beginEvent(mContext, mEntryPoint, mFunctionName, buffer.data()); + } +} + +LogMessage::LogMessage(const char *file, const char *function, int line, LogSeverity severity) + : mFile(file), mFunction(function), mLine(line), mSeverity(severity) +{ + // INFO() and EVENT() do not require additional function(line) info. + if (mSeverity > LOG_INFO) + { + const char *slash = std::max(strrchr(mFile, '/'), strrchr(mFile, '\\')); + mStream << (slash ? (slash + 1) : mFile) << ":" << mLine << " (" << mFunction << "): "; + } +} + +LogMessage::~LogMessage() +{ + { + std::unique_lock<std::mutex> lock; + if (g_debugMutex != nullptr) + { + lock = std::unique_lock<std::mutex>(*g_debugMutex); + } + + if (DebugAnnotationsInitialized() && (mSeverity > LOG_INFO)) + { + g_debugAnnotator->logMessage(*this); + } + else + { + Trace(getSeverity(), getMessage().c_str()); + } + } + + if (mSeverity == LOG_FATAL) + { + if (angle::IsDebuggerAttached()) + { + angle::BreakDebugger(); + } + else + { + ANGLE_CRASH(); + } + } +} + +void Trace(LogSeverity severity, const char *message) +{ + if (!ShouldCreateLogMessage(severity)) + { + return; + } + + std::string str(message); + + if (DebugAnnotationsActive(/*context=*/nullptr)) + { + + switch (severity) + { + case LOG_EVENT: + // Debugging logging done in ScopedPerfEventHelper + break; + default: + g_debugAnnotator->setMarker(/*context=*/nullptr, message); + break; + } + } + + if (severity == LOG_FATAL || severity == LOG_ERR || severity == LOG_WARN || +#if defined(ANGLE_ENABLE_TRACE_ANDROID_LOGCAT) || defined(ANGLE_ENABLE_TRACE_EVENTS) + severity == LOG_EVENT || +#endif + severity == LOG_INFO) + { +#if defined(ANGLE_PLATFORM_ANDROID) + android_LogPriority android_priority = ANDROID_LOG_ERROR; + switch (severity) + { + case LOG_INFO: + case LOG_EVENT: + android_priority = ANDROID_LOG_INFO; + break; + case LOG_WARN: + android_priority = ANDROID_LOG_WARN; + break; + case LOG_ERR: + android_priority = ANDROID_LOG_ERROR; + break; + case LOG_FATAL: + android_priority = ANDROID_LOG_FATAL; + break; + default: + UNREACHABLE(); + } + __android_log_print(android_priority, "ANGLE", "%s: %s\n", LogSeverityName(severity), + str.c_str()); +#elif defined(ANGLE_PLATFORM_APPLE) + if (__builtin_available(macOS 10.12, iOS 10.0, *)) + { + os_log_type_t apple_log_type = OS_LOG_TYPE_DEFAULT; + switch (severity) + { + case LOG_INFO: + apple_log_type = OS_LOG_TYPE_INFO; + break; + case LOG_WARN: + apple_log_type = OS_LOG_TYPE_DEFAULT; + break; + case LOG_ERR: + apple_log_type = OS_LOG_TYPE_ERROR; + break; + case LOG_FATAL: + // OS_LOG_TYPE_FAULT is too severe - grabs the entire process tree. + apple_log_type = OS_LOG_TYPE_ERROR; + break; + default: + UNREACHABLE(); + } + os_log_with_type(OS_LOG_DEFAULT, apple_log_type, "ANGLE: %s: %s\n", + LogSeverityName(severity), str.c_str()); + } +#else + // Note: we use fprintf because <iostream> includes static initializers. + fprintf((severity >= LOG_WARN) ? stderr : stdout, "%s: %s\n", LogSeverityName(severity), + str.c_str()); +#endif + } + +#if defined(ANGLE_PLATFORM_WINDOWS) && \ + (defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) || !defined(NDEBUG)) +# if !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) + if (severity >= LOG_ERR) +# endif // !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) + { + OutputDebugStringA(str.c_str()); + OutputDebugStringA("\n"); + } +#endif + +#if defined(ANGLE_ENABLE_DEBUG_TRACE) +# if defined(NDEBUG) + if (severity == LOG_EVENT || severity == LOG_WARN || severity == LOG_INFO) + { + return; + } +# endif // defined(NDEBUG) + static angle::base::NoDestructor<std::ofstream> file(TRACE_OUTPUT_FILE, std::ofstream::app); + if (file->good()) + { + if (severity > LOG_EVENT) + { + *file << LogSeverityName(severity) << ": "; + } + *file << str << "\n"; + file->flush(); + } +#endif // defined(ANGLE_ENABLE_DEBUG_TRACE) +} + +LogSeverity LogMessage::getSeverity() const +{ + return mSeverity; +} + +std::string LogMessage::getMessage() const +{ + return mStream.str(); +} + +#if defined(ANGLE_PLATFORM_WINDOWS) +priv::FmtHexHelper<HRESULT, char> FmtHR(HRESULT value) +{ + return priv::FmtHexHelper<HRESULT, char>("HRESULT: ", value); +} + +priv::FmtHexHelper<DWORD, char> FmtErr(DWORD value) +{ + return priv::FmtHexHelper<DWORD, char>("error: ", value); +} +#endif // defined(ANGLE_PLATFORM_WINDOWS) + +} // namespace gl |