1cb93a386Sopenharmony_ci//
2cb93a386Sopenharmony_ci// Copyright 2015 The ANGLE Project Authors. All rights reserved.
3cb93a386Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
4cb93a386Sopenharmony_ci// found in the LICENSE file.
5cb93a386Sopenharmony_ci//
6cb93a386Sopenharmony_ci
7cb93a386Sopenharmony_ci// Debug.cpp: Defines debug state used for GL_KHR_debug
8cb93a386Sopenharmony_ci
9cb93a386Sopenharmony_ci#include "libANGLE/Debug.h"
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "common/debug.h"
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_ci#include <algorithm>
14cb93a386Sopenharmony_ci#include <tuple>
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_cinamespace
17cb93a386Sopenharmony_ci{
18cb93a386Sopenharmony_ciconst char *GLSeverityToString(GLenum severity)
19cb93a386Sopenharmony_ci{
20cb93a386Sopenharmony_ci    switch (severity)
21cb93a386Sopenharmony_ci    {
22cb93a386Sopenharmony_ci        case GL_DEBUG_SEVERITY_HIGH:
23cb93a386Sopenharmony_ci            return "HIGH";
24cb93a386Sopenharmony_ci        case GL_DEBUG_SEVERITY_MEDIUM:
25cb93a386Sopenharmony_ci            return "MEDIUM";
26cb93a386Sopenharmony_ci        case GL_DEBUG_SEVERITY_LOW:
27cb93a386Sopenharmony_ci            return "LOW";
28cb93a386Sopenharmony_ci        case GL_DEBUG_SEVERITY_NOTIFICATION:
29cb93a386Sopenharmony_ci        default:
30cb93a386Sopenharmony_ci            return "NOTIFICATION";
31cb93a386Sopenharmony_ci    }
32cb93a386Sopenharmony_ci}
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ciconst char *EGLMessageTypeToString(egl::MessageType messageType)
35cb93a386Sopenharmony_ci{
36cb93a386Sopenharmony_ci    switch (messageType)
37cb93a386Sopenharmony_ci    {
38cb93a386Sopenharmony_ci        case egl::MessageType::Critical:
39cb93a386Sopenharmony_ci            return "CRITICAL";
40cb93a386Sopenharmony_ci        case egl::MessageType::Error:
41cb93a386Sopenharmony_ci            return "ERROR";
42cb93a386Sopenharmony_ci        case egl::MessageType::Warn:
43cb93a386Sopenharmony_ci            return "WARNING";
44cb93a386Sopenharmony_ci        case egl::MessageType::Info:
45cb93a386Sopenharmony_ci        default:
46cb93a386Sopenharmony_ci            return "INFO";
47cb93a386Sopenharmony_ci    }
48cb93a386Sopenharmony_ci}
49cb93a386Sopenharmony_ci
50cb93a386Sopenharmony_ciconst char *GLMessageTypeToString(GLenum type)
51cb93a386Sopenharmony_ci{
52cb93a386Sopenharmony_ci    switch (type)
53cb93a386Sopenharmony_ci    {
54cb93a386Sopenharmony_ci        case GL_DEBUG_TYPE_ERROR:
55cb93a386Sopenharmony_ci            return "error";
56cb93a386Sopenharmony_ci        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
57cb93a386Sopenharmony_ci            return "deprecated behavior";
58cb93a386Sopenharmony_ci        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
59cb93a386Sopenharmony_ci            return "undefined behavior";
60cb93a386Sopenharmony_ci        case GL_DEBUG_TYPE_PORTABILITY:
61cb93a386Sopenharmony_ci            return "portability";
62cb93a386Sopenharmony_ci        case GL_DEBUG_TYPE_PERFORMANCE:
63cb93a386Sopenharmony_ci            return "performance";
64cb93a386Sopenharmony_ci        case GL_DEBUG_TYPE_MARKER:
65cb93a386Sopenharmony_ci            return "marker";
66cb93a386Sopenharmony_ci        case GL_DEBUG_TYPE_PUSH_GROUP:
67cb93a386Sopenharmony_ci            return "start of group";
68cb93a386Sopenharmony_ci        case GL_DEBUG_TYPE_POP_GROUP:
69cb93a386Sopenharmony_ci            return "end of group";
70cb93a386Sopenharmony_ci        case GL_DEBUG_TYPE_OTHER:
71cb93a386Sopenharmony_ci        default:
72cb93a386Sopenharmony_ci            return "other message";
73cb93a386Sopenharmony_ci    }
74cb93a386Sopenharmony_ci}
75cb93a386Sopenharmony_ci}  // namespace
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_cinamespace gl
78cb93a386Sopenharmony_ci{
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ciDebug::Control::Control() {}
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_ciDebug::Control::~Control() {}
83cb93a386Sopenharmony_ci
84cb93a386Sopenharmony_ciDebug::Control::Control(const Control &other) = default;
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ciDebug::Group::Group() {}
87cb93a386Sopenharmony_ci
88cb93a386Sopenharmony_ciDebug::Group::~Group() {}
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_ciDebug::Group::Group(const Group &other) = default;
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ciDebug::Debug(bool initialDebugState)
93cb93a386Sopenharmony_ci    : mOutputEnabled(initialDebugState),
94cb93a386Sopenharmony_ci      mCallbackFunction(nullptr),
95cb93a386Sopenharmony_ci      mCallbackUserParam(nullptr),
96cb93a386Sopenharmony_ci      mMessages(),
97cb93a386Sopenharmony_ci      mMaxLoggedMessages(0),
98cb93a386Sopenharmony_ci      mOutputSynchronous(false),
99cb93a386Sopenharmony_ci      mGroups()
100cb93a386Sopenharmony_ci{
101cb93a386Sopenharmony_ci    pushDefaultGroup();
102cb93a386Sopenharmony_ci}
103cb93a386Sopenharmony_ci
104cb93a386Sopenharmony_ciDebug::~Debug() {}
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_civoid Debug::setMaxLoggedMessages(GLuint maxLoggedMessages)
107cb93a386Sopenharmony_ci{
108cb93a386Sopenharmony_ci    mMaxLoggedMessages = maxLoggedMessages;
109cb93a386Sopenharmony_ci}
110cb93a386Sopenharmony_ci
111cb93a386Sopenharmony_civoid Debug::setOutputEnabled(bool enabled)
112cb93a386Sopenharmony_ci{
113cb93a386Sopenharmony_ci    mOutputEnabled = enabled;
114cb93a386Sopenharmony_ci}
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_cibool Debug::isOutputEnabled() const
117cb93a386Sopenharmony_ci{
118cb93a386Sopenharmony_ci    return mOutputEnabled;
119cb93a386Sopenharmony_ci}
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_civoid Debug::setOutputSynchronous(bool synchronous)
122cb93a386Sopenharmony_ci{
123cb93a386Sopenharmony_ci    mOutputSynchronous = synchronous;
124cb93a386Sopenharmony_ci}
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_cibool Debug::isOutputSynchronous() const
127cb93a386Sopenharmony_ci{
128cb93a386Sopenharmony_ci    return mOutputSynchronous;
129cb93a386Sopenharmony_ci}
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_civoid Debug::setCallback(GLDEBUGPROCKHR callback, const void *userParam)
132cb93a386Sopenharmony_ci{
133cb93a386Sopenharmony_ci    mCallbackFunction  = callback;
134cb93a386Sopenharmony_ci    mCallbackUserParam = userParam;
135cb93a386Sopenharmony_ci}
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ciGLDEBUGPROCKHR Debug::getCallback() const
138cb93a386Sopenharmony_ci{
139cb93a386Sopenharmony_ci    return mCallbackFunction;
140cb93a386Sopenharmony_ci}
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ciconst void *Debug::getUserParam() const
143cb93a386Sopenharmony_ci{
144cb93a386Sopenharmony_ci    return mCallbackUserParam;
145cb93a386Sopenharmony_ci}
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_civoid Debug::insertMessage(GLenum source,
148cb93a386Sopenharmony_ci                          GLenum type,
149cb93a386Sopenharmony_ci                          GLuint id,
150cb93a386Sopenharmony_ci                          GLenum severity,
151cb93a386Sopenharmony_ci                          const std::string &message,
152cb93a386Sopenharmony_ci                          gl::LogSeverity logSeverity,
153cb93a386Sopenharmony_ci                          angle::EntryPoint entryPoint) const
154cb93a386Sopenharmony_ci{
155cb93a386Sopenharmony_ci    std::string messageCopy(message);
156cb93a386Sopenharmony_ci    insertMessage(source, type, id, severity, std::move(messageCopy), logSeverity, entryPoint);
157cb93a386Sopenharmony_ci}
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_civoid Debug::insertMessage(GLenum source,
160cb93a386Sopenharmony_ci                          GLenum type,
161cb93a386Sopenharmony_ci                          GLuint id,
162cb93a386Sopenharmony_ci                          GLenum severity,
163cb93a386Sopenharmony_ci                          std::string &&message,
164cb93a386Sopenharmony_ci                          gl::LogSeverity logSeverity,
165cb93a386Sopenharmony_ci                          angle::EntryPoint entryPoint) const
166cb93a386Sopenharmony_ci{
167cb93a386Sopenharmony_ci    {
168cb93a386Sopenharmony_ci        // output all messages to the debug log
169cb93a386Sopenharmony_ci        const char *messageTypeString = GLMessageTypeToString(type);
170cb93a386Sopenharmony_ci        const char *severityString    = GLSeverityToString(severity);
171cb93a386Sopenharmony_ci        std::ostringstream messageStream;
172cb93a386Sopenharmony_ci        if (entryPoint != angle::EntryPoint::GLInvalid)
173cb93a386Sopenharmony_ci        {
174cb93a386Sopenharmony_ci            messageStream << GetEntryPointName(entryPoint) << ": ";
175cb93a386Sopenharmony_ci        }
176cb93a386Sopenharmony_ci        messageStream << "GL " << messageTypeString << ": " << severityString << ": " << message;
177cb93a386Sopenharmony_ci        switch (logSeverity)
178cb93a386Sopenharmony_ci        {
179cb93a386Sopenharmony_ci            case gl::LOG_FATAL:
180cb93a386Sopenharmony_ci                FATAL() << messageStream.str();
181cb93a386Sopenharmony_ci                break;
182cb93a386Sopenharmony_ci            case gl::LOG_ERR:
183cb93a386Sopenharmony_ci                ERR() << messageStream.str();
184cb93a386Sopenharmony_ci                break;
185cb93a386Sopenharmony_ci            case gl::LOG_WARN:
186cb93a386Sopenharmony_ci                WARN() << messageStream.str();
187cb93a386Sopenharmony_ci                break;
188cb93a386Sopenharmony_ci            case gl::LOG_INFO:
189cb93a386Sopenharmony_ci                INFO() << messageStream.str();
190cb93a386Sopenharmony_ci                break;
191cb93a386Sopenharmony_ci            case gl::LOG_EVENT:
192cb93a386Sopenharmony_ci                ANGLE_LOG(EVENT) << messageStream.str();
193cb93a386Sopenharmony_ci                break;
194cb93a386Sopenharmony_ci        }
195cb93a386Sopenharmony_ci    }
196cb93a386Sopenharmony_ci
197cb93a386Sopenharmony_ci    if (!isMessageEnabled(source, type, id, severity))
198cb93a386Sopenharmony_ci    {
199cb93a386Sopenharmony_ci        return;
200cb93a386Sopenharmony_ci    }
201cb93a386Sopenharmony_ci
202cb93a386Sopenharmony_ci    if (mCallbackFunction != nullptr)
203cb93a386Sopenharmony_ci    {
204cb93a386Sopenharmony_ci        // TODO(geofflang) Check the synchronous flag and potentially flush messages from another
205cb93a386Sopenharmony_ci        // thread.
206cb93a386Sopenharmony_ci        mCallbackFunction(source, type, id, severity, static_cast<GLsizei>(message.length()),
207cb93a386Sopenharmony_ci                          message.c_str(), mCallbackUserParam);
208cb93a386Sopenharmony_ci    }
209cb93a386Sopenharmony_ci    else
210cb93a386Sopenharmony_ci    {
211cb93a386Sopenharmony_ci        if (mMessages.size() >= mMaxLoggedMessages)
212cb93a386Sopenharmony_ci        {
213cb93a386Sopenharmony_ci            // Drop messages over the limit
214cb93a386Sopenharmony_ci            return;
215cb93a386Sopenharmony_ci        }
216cb93a386Sopenharmony_ci
217cb93a386Sopenharmony_ci        Message m;
218cb93a386Sopenharmony_ci        m.source   = source;
219cb93a386Sopenharmony_ci        m.type     = type;
220cb93a386Sopenharmony_ci        m.id       = id;
221cb93a386Sopenharmony_ci        m.severity = severity;
222cb93a386Sopenharmony_ci        m.message  = std::move(message);
223cb93a386Sopenharmony_ci
224cb93a386Sopenharmony_ci        mMessages.push_back(std::move(m));
225cb93a386Sopenharmony_ci    }
226cb93a386Sopenharmony_ci}
227cb93a386Sopenharmony_ci
228cb93a386Sopenharmony_cisize_t Debug::getMessages(GLuint count,
229cb93a386Sopenharmony_ci                          GLsizei bufSize,
230cb93a386Sopenharmony_ci                          GLenum *sources,
231cb93a386Sopenharmony_ci                          GLenum *types,
232cb93a386Sopenharmony_ci                          GLuint *ids,
233cb93a386Sopenharmony_ci                          GLenum *severities,
234cb93a386Sopenharmony_ci                          GLsizei *lengths,
235cb93a386Sopenharmony_ci                          GLchar *messageLog)
236cb93a386Sopenharmony_ci{
237cb93a386Sopenharmony_ci    size_t messageCount       = 0;
238cb93a386Sopenharmony_ci    size_t messageStringIndex = 0;
239cb93a386Sopenharmony_ci    while (messageCount <= count && !mMessages.empty())
240cb93a386Sopenharmony_ci    {
241cb93a386Sopenharmony_ci        const Message &m = mMessages.front();
242cb93a386Sopenharmony_ci
243cb93a386Sopenharmony_ci        if (messageLog != nullptr)
244cb93a386Sopenharmony_ci        {
245cb93a386Sopenharmony_ci            // Check that this message can fit in the message buffer
246cb93a386Sopenharmony_ci            if (messageStringIndex + m.message.length() + 1 > static_cast<size_t>(bufSize))
247cb93a386Sopenharmony_ci            {
248cb93a386Sopenharmony_ci                break;
249cb93a386Sopenharmony_ci            }
250cb93a386Sopenharmony_ci
251cb93a386Sopenharmony_ci            std::copy(m.message.begin(), m.message.end(), messageLog + messageStringIndex);
252cb93a386Sopenharmony_ci            messageStringIndex += m.message.length();
253cb93a386Sopenharmony_ci
254cb93a386Sopenharmony_ci            messageLog[messageStringIndex] = '\0';
255cb93a386Sopenharmony_ci            messageStringIndex += 1;
256cb93a386Sopenharmony_ci        }
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_ci        if (sources != nullptr)
259cb93a386Sopenharmony_ci        {
260cb93a386Sopenharmony_ci            sources[messageCount] = m.source;
261cb93a386Sopenharmony_ci        }
262cb93a386Sopenharmony_ci
263cb93a386Sopenharmony_ci        if (types != nullptr)
264cb93a386Sopenharmony_ci        {
265cb93a386Sopenharmony_ci            types[messageCount] = m.type;
266cb93a386Sopenharmony_ci        }
267cb93a386Sopenharmony_ci
268cb93a386Sopenharmony_ci        if (ids != nullptr)
269cb93a386Sopenharmony_ci        {
270cb93a386Sopenharmony_ci            ids[messageCount] = m.id;
271cb93a386Sopenharmony_ci        }
272cb93a386Sopenharmony_ci
273cb93a386Sopenharmony_ci        if (severities != nullptr)
274cb93a386Sopenharmony_ci        {
275cb93a386Sopenharmony_ci            severities[messageCount] = m.severity;
276cb93a386Sopenharmony_ci        }
277cb93a386Sopenharmony_ci
278cb93a386Sopenharmony_ci        if (lengths != nullptr)
279cb93a386Sopenharmony_ci        {
280cb93a386Sopenharmony_ci            lengths[messageCount] = static_cast<GLsizei>(m.message.length()) + 1;
281cb93a386Sopenharmony_ci        }
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_ci        mMessages.pop_front();
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_ci        messageCount++;
286cb93a386Sopenharmony_ci    }
287cb93a386Sopenharmony_ci
288cb93a386Sopenharmony_ci    return messageCount;
289cb93a386Sopenharmony_ci}
290cb93a386Sopenharmony_ci
291cb93a386Sopenharmony_cisize_t Debug::getNextMessageLength() const
292cb93a386Sopenharmony_ci{
293cb93a386Sopenharmony_ci    return mMessages.empty() ? 0 : mMessages.front().message.length() + 1;
294cb93a386Sopenharmony_ci}
295cb93a386Sopenharmony_ci
296cb93a386Sopenharmony_cisize_t Debug::getMessageCount() const
297cb93a386Sopenharmony_ci{
298cb93a386Sopenharmony_ci    return mMessages.size();
299cb93a386Sopenharmony_ci}
300cb93a386Sopenharmony_ci
301cb93a386Sopenharmony_civoid Debug::setMessageControl(GLenum source,
302cb93a386Sopenharmony_ci                              GLenum type,
303cb93a386Sopenharmony_ci                              GLenum severity,
304cb93a386Sopenharmony_ci                              std::vector<GLuint> &&ids,
305cb93a386Sopenharmony_ci                              bool enabled)
306cb93a386Sopenharmony_ci{
307cb93a386Sopenharmony_ci    Control c;
308cb93a386Sopenharmony_ci    c.source   = source;
309cb93a386Sopenharmony_ci    c.type     = type;
310cb93a386Sopenharmony_ci    c.severity = severity;
311cb93a386Sopenharmony_ci    c.ids      = std::move(ids);
312cb93a386Sopenharmony_ci    c.enabled  = enabled;
313cb93a386Sopenharmony_ci
314cb93a386Sopenharmony_ci    auto &controls = mGroups.back().controls;
315cb93a386Sopenharmony_ci    controls.push_back(std::move(c));
316cb93a386Sopenharmony_ci}
317cb93a386Sopenharmony_ci
318cb93a386Sopenharmony_civoid Debug::pushGroup(GLenum source, GLuint id, std::string &&message)
319cb93a386Sopenharmony_ci{
320cb93a386Sopenharmony_ci    insertMessage(source, GL_DEBUG_TYPE_PUSH_GROUP, id, GL_DEBUG_SEVERITY_NOTIFICATION,
321cb93a386Sopenharmony_ci                  std::string(message), gl::LOG_INFO, angle::EntryPoint::GLPushDebugGroup);
322cb93a386Sopenharmony_ci
323cb93a386Sopenharmony_ci    Group g;
324cb93a386Sopenharmony_ci    g.source  = source;
325cb93a386Sopenharmony_ci    g.id      = id;
326cb93a386Sopenharmony_ci    g.message = std::move(message);
327cb93a386Sopenharmony_ci    mGroups.push_back(std::move(g));
328cb93a386Sopenharmony_ci}
329cb93a386Sopenharmony_ci
330cb93a386Sopenharmony_civoid Debug::popGroup()
331cb93a386Sopenharmony_ci{
332cb93a386Sopenharmony_ci    // Make sure the default group is not about to be popped
333cb93a386Sopenharmony_ci    ASSERT(mGroups.size() > 1);
334cb93a386Sopenharmony_ci
335cb93a386Sopenharmony_ci    Group g = mGroups.back();
336cb93a386Sopenharmony_ci    mGroups.pop_back();
337cb93a386Sopenharmony_ci
338cb93a386Sopenharmony_ci    insertMessage(g.source, GL_DEBUG_TYPE_POP_GROUP, g.id, GL_DEBUG_SEVERITY_NOTIFICATION,
339cb93a386Sopenharmony_ci                  g.message, gl::LOG_INFO, angle::EntryPoint::GLPopDebugGroup);
340cb93a386Sopenharmony_ci}
341cb93a386Sopenharmony_ci
342cb93a386Sopenharmony_cisize_t Debug::getGroupStackDepth() const
343cb93a386Sopenharmony_ci{
344cb93a386Sopenharmony_ci    return mGroups.size();
345cb93a386Sopenharmony_ci}
346cb93a386Sopenharmony_ci
347cb93a386Sopenharmony_civoid Debug::insertPerfWarning(GLenum severity, const char *message, uint32_t *repeatCount) const
348cb93a386Sopenharmony_ci{
349cb93a386Sopenharmony_ci    bool repeatLast;
350cb93a386Sopenharmony_ci
351cb93a386Sopenharmony_ci    {
352cb93a386Sopenharmony_ci        constexpr uint32_t kMaxRepeat = 4;
353cb93a386Sopenharmony_ci        std::lock_guard<std::mutex> lock(GetDebugMutex());
354cb93a386Sopenharmony_ci
355cb93a386Sopenharmony_ci        if (*repeatCount >= kMaxRepeat)
356cb93a386Sopenharmony_ci        {
357cb93a386Sopenharmony_ci            return;
358cb93a386Sopenharmony_ci        }
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_ci        ++*repeatCount;
361cb93a386Sopenharmony_ci        repeatLast = (*repeatCount == kMaxRepeat);
362cb93a386Sopenharmony_ci    }
363cb93a386Sopenharmony_ci
364cb93a386Sopenharmony_ci    std::string msg = message;
365cb93a386Sopenharmony_ci    if (repeatLast)
366cb93a386Sopenharmony_ci    {
367cb93a386Sopenharmony_ci        msg += " (this message will no longer repeat)";
368cb93a386Sopenharmony_ci    }
369cb93a386Sopenharmony_ci
370cb93a386Sopenharmony_ci    // Release the lock before we call insertMessage. It will re-acquire the lock.
371cb93a386Sopenharmony_ci    insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_PERFORMANCE, 0, severity, std::move(msg),
372cb93a386Sopenharmony_ci                  gl::LOG_INFO, angle::EntryPoint::GLInvalid);
373cb93a386Sopenharmony_ci}
374cb93a386Sopenharmony_ci
375cb93a386Sopenharmony_cibool Debug::isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const
376cb93a386Sopenharmony_ci{
377cb93a386Sopenharmony_ci    if (!mOutputEnabled)
378cb93a386Sopenharmony_ci    {
379cb93a386Sopenharmony_ci        return false;
380cb93a386Sopenharmony_ci    }
381cb93a386Sopenharmony_ci
382cb93a386Sopenharmony_ci    for (auto groupIter = mGroups.rbegin(); groupIter != mGroups.rend(); groupIter++)
383cb93a386Sopenharmony_ci    {
384cb93a386Sopenharmony_ci        const auto &controls = groupIter->controls;
385cb93a386Sopenharmony_ci        for (auto controlIter = controls.rbegin(); controlIter != controls.rend(); controlIter++)
386cb93a386Sopenharmony_ci        {
387cb93a386Sopenharmony_ci            const auto &control = *controlIter;
388cb93a386Sopenharmony_ci
389cb93a386Sopenharmony_ci            if (control.source != GL_DONT_CARE && control.source != source)
390cb93a386Sopenharmony_ci            {
391cb93a386Sopenharmony_ci                continue;
392cb93a386Sopenharmony_ci            }
393cb93a386Sopenharmony_ci
394cb93a386Sopenharmony_ci            if (control.type != GL_DONT_CARE && control.type != type)
395cb93a386Sopenharmony_ci            {
396cb93a386Sopenharmony_ci                continue;
397cb93a386Sopenharmony_ci            }
398cb93a386Sopenharmony_ci
399cb93a386Sopenharmony_ci            if (control.severity != GL_DONT_CARE && control.severity != severity)
400cb93a386Sopenharmony_ci            {
401cb93a386Sopenharmony_ci                continue;
402cb93a386Sopenharmony_ci            }
403cb93a386Sopenharmony_ci
404cb93a386Sopenharmony_ci            if (!control.ids.empty() &&
405cb93a386Sopenharmony_ci                std::find(control.ids.begin(), control.ids.end(), id) == control.ids.end())
406cb93a386Sopenharmony_ci            {
407cb93a386Sopenharmony_ci                continue;
408cb93a386Sopenharmony_ci            }
409cb93a386Sopenharmony_ci
410cb93a386Sopenharmony_ci            return control.enabled;
411cb93a386Sopenharmony_ci        }
412cb93a386Sopenharmony_ci    }
413cb93a386Sopenharmony_ci
414cb93a386Sopenharmony_ci    return true;
415cb93a386Sopenharmony_ci}
416cb93a386Sopenharmony_ci
417cb93a386Sopenharmony_civoid Debug::pushDefaultGroup()
418cb93a386Sopenharmony_ci{
419cb93a386Sopenharmony_ci    Group g;
420cb93a386Sopenharmony_ci    g.source  = GL_NONE;
421cb93a386Sopenharmony_ci    g.id      = 0;
422cb93a386Sopenharmony_ci    g.message = "";
423cb93a386Sopenharmony_ci
424cb93a386Sopenharmony_ci    Control c0;
425cb93a386Sopenharmony_ci    c0.source   = GL_DONT_CARE;
426cb93a386Sopenharmony_ci    c0.type     = GL_DONT_CARE;
427cb93a386Sopenharmony_ci    c0.severity = GL_DONT_CARE;
428cb93a386Sopenharmony_ci    c0.enabled  = true;
429cb93a386Sopenharmony_ci    g.controls.push_back(std::move(c0));
430cb93a386Sopenharmony_ci
431cb93a386Sopenharmony_ci    Control c1;
432cb93a386Sopenharmony_ci    c1.source   = GL_DONT_CARE;
433cb93a386Sopenharmony_ci    c1.type     = GL_DONT_CARE;
434cb93a386Sopenharmony_ci    c1.severity = GL_DEBUG_SEVERITY_LOW;
435cb93a386Sopenharmony_ci    c1.enabled  = false;
436cb93a386Sopenharmony_ci    g.controls.push_back(std::move(c1));
437cb93a386Sopenharmony_ci
438cb93a386Sopenharmony_ci    mGroups.push_back(std::move(g));
439cb93a386Sopenharmony_ci}
440cb93a386Sopenharmony_ci}  // namespace gl
441cb93a386Sopenharmony_ci
442cb93a386Sopenharmony_cinamespace egl
443cb93a386Sopenharmony_ci{
444cb93a386Sopenharmony_ci
445cb93a386Sopenharmony_cinamespace
446cb93a386Sopenharmony_ci{
447cb93a386Sopenharmony_ciangle::PackedEnumBitSet<MessageType> GetDefaultMessageTypeBits()
448cb93a386Sopenharmony_ci{
449cb93a386Sopenharmony_ci    angle::PackedEnumBitSet<MessageType> result;
450cb93a386Sopenharmony_ci    result.set(MessageType::Critical);
451cb93a386Sopenharmony_ci    result.set(MessageType::Error);
452cb93a386Sopenharmony_ci    return result;
453cb93a386Sopenharmony_ci}
454cb93a386Sopenharmony_ci}  // anonymous namespace
455cb93a386Sopenharmony_ci
456cb93a386Sopenharmony_ciDebug::Debug() : mCallback(nullptr), mEnabledMessageTypes(GetDefaultMessageTypeBits()) {}
457cb93a386Sopenharmony_ci
458cb93a386Sopenharmony_civoid Debug::setCallback(EGLDEBUGPROCKHR callback, const AttributeMap &attribs)
459cb93a386Sopenharmony_ci{
460cb93a386Sopenharmony_ci    mCallback = callback;
461cb93a386Sopenharmony_ci
462cb93a386Sopenharmony_ci    const angle::PackedEnumBitSet<MessageType> defaultMessageTypes = GetDefaultMessageTypeBits();
463cb93a386Sopenharmony_ci    if (mCallback != nullptr)
464cb93a386Sopenharmony_ci    {
465cb93a386Sopenharmony_ci        for (MessageType messageType : angle::AllEnums<MessageType>())
466cb93a386Sopenharmony_ci        {
467cb93a386Sopenharmony_ci            mEnabledMessageTypes[messageType] =
468cb93a386Sopenharmony_ci                (attribs.getAsInt(egl::ToEGLenum(messageType), defaultMessageTypes[messageType]) ==
469cb93a386Sopenharmony_ci                 EGL_TRUE);
470cb93a386Sopenharmony_ci        }
471cb93a386Sopenharmony_ci    }
472cb93a386Sopenharmony_ci}
473cb93a386Sopenharmony_ci
474cb93a386Sopenharmony_ciEGLDEBUGPROCKHR Debug::getCallback() const
475cb93a386Sopenharmony_ci{
476cb93a386Sopenharmony_ci    return mCallback;
477cb93a386Sopenharmony_ci}
478cb93a386Sopenharmony_ci
479cb93a386Sopenharmony_cibool Debug::isMessageTypeEnabled(MessageType type) const
480cb93a386Sopenharmony_ci{
481cb93a386Sopenharmony_ci    return mEnabledMessageTypes[type];
482cb93a386Sopenharmony_ci}
483cb93a386Sopenharmony_ci
484cb93a386Sopenharmony_civoid Debug::insertMessage(EGLenum error,
485cb93a386Sopenharmony_ci                          const char *command,
486cb93a386Sopenharmony_ci                          MessageType messageType,
487cb93a386Sopenharmony_ci                          EGLLabelKHR threadLabel,
488cb93a386Sopenharmony_ci                          EGLLabelKHR objectLabel,
489cb93a386Sopenharmony_ci                          const std::string &message) const
490cb93a386Sopenharmony_ci{
491cb93a386Sopenharmony_ci    {
492cb93a386Sopenharmony_ci        // output all messages to the debug log
493cb93a386Sopenharmony_ci        const char *messageTypeString = EGLMessageTypeToString(messageType);
494cb93a386Sopenharmony_ci        std::ostringstream messageStream;
495cb93a386Sopenharmony_ci        messageStream << "EGL " << messageTypeString << ": " << command << ": " << message;
496cb93a386Sopenharmony_ci        INFO() << messageStream.str();
497cb93a386Sopenharmony_ci    }
498cb93a386Sopenharmony_ci
499cb93a386Sopenharmony_ci    // TODO(geofflang): Lock before checking the callback. http://anglebug.com/2464
500cb93a386Sopenharmony_ci    if (mCallback && isMessageTypeEnabled(messageType))
501cb93a386Sopenharmony_ci    {
502cb93a386Sopenharmony_ci        mCallback(error, command, egl::ToEGLenum(messageType), threadLabel, objectLabel,
503cb93a386Sopenharmony_ci                  message.c_str());
504cb93a386Sopenharmony_ci    }
505cb93a386Sopenharmony_ci}
506cb93a386Sopenharmony_ci
507cb93a386Sopenharmony_ci}  // namespace egl
508