xref: /aosp_15_r20/external/angle/src/libANGLE/Debug.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2015 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: Defines debug state used for GL_KHR_debug
8 
9 #ifndef LIBANGLE_DEBUG_H_
10 #define LIBANGLE_DEBUG_H_
11 
12 #include "angle_gl.h"
13 #include "common/PackedEnums.h"
14 #include "common/SimpleMutex.h"
15 #include "common/angleutils.h"
16 #include "libANGLE/AttributeMap.h"
17 #include "libANGLE/Error.h"
18 
19 #include <atomic>
20 #include <deque>
21 #include <string>
22 #include <vector>
23 
24 namespace gl
25 {
26 class Context;
27 
28 class LabeledObject
29 {
30   public:
~LabeledObject()31     virtual ~LabeledObject() {}
32     virtual angle::Result setLabel(const Context *context, const std::string &label) = 0;
33     virtual const std::string &getLabel() const                                      = 0;
34 };
35 
36 class Debug : angle::NonCopyable
37 {
38   public:
39     Debug(bool initialDebugState);
40     ~Debug();
41 
42     void setMaxLoggedMessages(GLuint maxLoggedMessages);
43 
44     void setOutputEnabled(bool enabled);
45     bool isOutputEnabled() const;
46 
47     void setOutputSynchronous(bool synchronous);
48     bool isOutputSynchronous() const;
49 
50     void setCallback(GLDEBUGPROCKHR callback, const void *userParam);
51     GLDEBUGPROCKHR getCallback() const;
52     const void *getUserParam() const;
53 
54     void insertMessage(GLenum source,
55                        GLenum type,
56                        GLuint id,
57                        GLenum severity,
58                        const std::string &message,
59                        gl::LogSeverity logSeverity,
60                        angle::EntryPoint entryPoint) const;
61     void insertMessage(GLenum source,
62                        GLenum type,
63                        GLuint id,
64                        GLenum severity,
65                        std::string &&message,
66                        gl::LogSeverity logSeverity,
67                        angle::EntryPoint entryPoint) const;
68 
69     void setMessageControl(GLenum source,
70                            GLenum type,
71                            GLenum severity,
72                            std::vector<GLuint> &&ids,
73                            bool enabled);
74     size_t getMessages(GLuint count,
75                        GLsizei bufSize,
76                        GLenum *sources,
77                        GLenum *types,
78                        GLuint *ids,
79                        GLenum *severities,
80                        GLsizei *lengths,
81                        GLchar *messageLog);
82     size_t getNextMessageLength() const;
83     size_t getMessageCount() const;
84 
85     void pushGroup(GLenum source, GLuint id, std::string &&message);
86     void popGroup();
87     size_t getGroupStackDepth() const;
88 
89     // Helper for ANGLE_PERF_WARNING
90     void insertPerfWarning(GLenum severity, bool isLastRepeat, const char *message) const;
91 
92   private:
93     bool isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const;
94 
95     void pushDefaultGroup();
96 
97     struct Message
98     {
99         GLenum source;
100         GLenum type;
101         GLuint id;
102         GLenum severity;
103         std::string message;
104     };
105 
106     struct Control
107     {
108         Control();
109         ~Control();
110         Control(const Control &other);
111 
112         GLenum source;
113         GLenum type;
114         GLenum severity;
115         std::vector<GLuint> ids;
116         bool enabled;
117     };
118 
119     struct Group
120     {
121         Group();
122         ~Group();
123         Group(const Group &other);
124 
125         GLenum source;
126         GLuint id;
127         std::string message;
128 
129         std::vector<Control> controls;
130     };
131 
132     bool mOutputEnabled;
133     mutable angle::SimpleMutex mMutex;
134     GLDEBUGPROCKHR mCallbackFunction;
135     const void *mCallbackUserParam;
136     mutable std::deque<Message> mMessages;
137     GLuint mMaxLoggedMessages;
138     bool mOutputSynchronous;
139     std::vector<Group> mGroups;
140 };
141 }  // namespace gl
142 
143 namespace egl
144 {
145 class LabeledObject
146 {
147   public:
~LabeledObject()148     virtual ~LabeledObject() {}
149     virtual void setLabel(EGLLabelKHR label) = 0;
150     virtual EGLLabelKHR getLabel() const     = 0;
151 };
152 
153 class Debug : angle::NonCopyable
154 {
155   public:
156     Debug();
157 
158     void setCallback(EGLDEBUGPROCKHR callback, const AttributeMap &attribs);
159     EGLDEBUGPROCKHR getCallback() const;
160     bool isMessageTypeEnabled(MessageType type) const;
161 
162     void insertMessage(EGLenum error,
163                        const char *command,
164                        MessageType messageType,
165                        EGLLabelKHR threadLabel,
166                        EGLLabelKHR objectLabel,
167                        const std::string &message) const;
168 
169   private:
170     EGLDEBUGPROCKHR mCallback;
171     angle::PackedEnumBitSet<MessageType> mEnabledMessageTypes;
172 };
173 }  // namespace egl
174 
175 namespace
176 {
PerfCounterBelowMaxRepeat(std::atomic<uint32_t> * counter,bool * isLastRepeat)177 ANGLE_INLINE bool PerfCounterBelowMaxRepeat(std::atomic<uint32_t> *counter, bool *isLastRepeat)
178 {
179     constexpr uint32_t kMaxPerfRepeat = 4;
180     // Stop incrementing the counter after max value to avoid unnecessary cache effects
181     if (counter->load(std::memory_order_relaxed) < kMaxPerfRepeat)
182     {
183         uint32_t count = counter->fetch_add(1, std::memory_order_relaxed);
184         // Check not strictly necessary as worst case is an additional log, but is good practice.
185         if (count < kMaxPerfRepeat)
186         {
187             if (count == kMaxPerfRepeat - 1)
188             {
189                 *isLastRepeat = true;
190             }
191             return true;
192         }
193     }
194     return false;
195 }
196 }  // namespace
197 
198 // Generate a perf warning.  Only outputs the same message a few times to avoid spamming the logs.
199 #define ANGLE_PERF_WARNING(debug, severity, ...)                              \
200     do                                                                        \
201     {                                                                         \
202         static std::atomic<uint32_t> sRepeatCount = 0;                        \
203         bool isLastRepeat                         = false;                    \
204         if (PerfCounterBelowMaxRepeat(&sRepeatCount, &isLastRepeat))          \
205         {                                                                     \
206             char ANGLE_MESSAGE[200];                                          \
207             snprintf(ANGLE_MESSAGE, sizeof(ANGLE_MESSAGE), __VA_ARGS__);      \
208             (debug).insertPerfWarning(severity, isLastRepeat, ANGLE_MESSAGE); \
209         }                                                                     \
210     } while (0)
211 
212 #endif  // LIBANGLE_DEBUG_H_
213