• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2016  Brian Paul, et al   All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include "context.h"
29 #include "debug_output.h"
30 #include "enums.h"
31 
32 #include "hash.h"
33 #include "mtypes.h"
34 #include "version.h"
35 #include "util/hash_table.h"
36 #include "util/list.h"
37 #include "util/u_memory.h"
38 #include "api_exec_decl.h"
39 
40 #include "pipe/p_context.h"
41 
42 static GLuint PrevDynamicID = 0;
43 
44 
45 /**
46  * A namespace element.
47  */
48 struct gl_debug_element
49 {
50    struct list_head link;
51 
52    GLuint ID;
53    /* at which severity levels (mesa_debug_severity) is the message enabled */
54    GLbitfield State;
55 };
56 
57 
58 struct gl_debug_namespace
59 {
60    struct list_head Elements;
61    GLbitfield DefaultState;
62 };
63 
64 
65 struct gl_debug_group {
66    struct gl_debug_namespace Namespaces[MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
67 };
68 
69 
70 /**
71  * An error, warning, or other piece of debug information for an application
72  * to consume via GL_ARB_debug_output/GL_KHR_debug.
73  */
74 struct gl_debug_message
75 {
76    enum mesa_debug_source source;
77    enum mesa_debug_type type;
78    GLuint id;
79    enum mesa_debug_severity severity;
80    /* length as given by the user - if message was explicitly null terminated,
81     * length can be negative */
82    GLsizei length;
83    GLcharARB *message;
84 };
85 
86 
87 /**
88  * Debug message log.  It works like a ring buffer.
89  */
90 struct gl_debug_log {
91    struct gl_debug_message Messages[MAX_DEBUG_LOGGED_MESSAGES];
92    GLint NextMessage;
93    GLint NumMessages;
94 };
95 
96 
97 struct gl_debug_state
98 {
99    GLDEBUGPROC Callback;
100    const void *CallbackData;
101    GLboolean SyncOutput;
102    GLboolean DebugOutput;
103    GLboolean LogToStderr;
104 
105    struct gl_debug_group *Groups[MAX_DEBUG_GROUP_STACK_DEPTH];
106    struct gl_debug_message GroupMessages[MAX_DEBUG_GROUP_STACK_DEPTH];
107    GLint CurrentGroup; // GroupStackDepth - 1
108 
109    struct gl_debug_log Log;
110 };
111 
112 
113 static char out_of_memory[] = "Debugging error: out of memory";
114 
115 static const GLenum debug_source_enums[] = {
116    GL_DEBUG_SOURCE_API,
117    GL_DEBUG_SOURCE_WINDOW_SYSTEM,
118    GL_DEBUG_SOURCE_SHADER_COMPILER,
119    GL_DEBUG_SOURCE_THIRD_PARTY,
120    GL_DEBUG_SOURCE_APPLICATION,
121    GL_DEBUG_SOURCE_OTHER,
122 };
123 
124 static const GLenum debug_type_enums[] = {
125    GL_DEBUG_TYPE_ERROR,
126    GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR,
127    GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR,
128    GL_DEBUG_TYPE_PORTABILITY,
129    GL_DEBUG_TYPE_PERFORMANCE,
130    GL_DEBUG_TYPE_OTHER,
131    GL_DEBUG_TYPE_MARKER,
132    GL_DEBUG_TYPE_PUSH_GROUP,
133    GL_DEBUG_TYPE_POP_GROUP,
134 };
135 
136 static const GLenum debug_severity_enums[] = {
137    GL_DEBUG_SEVERITY_LOW,
138    GL_DEBUG_SEVERITY_MEDIUM,
139    GL_DEBUG_SEVERITY_HIGH,
140    GL_DEBUG_SEVERITY_NOTIFICATION,
141 };
142 
143 
144 static enum mesa_debug_source
gl_enum_to_debug_source(GLenum e)145 gl_enum_to_debug_source(GLenum e)
146 {
147    unsigned i;
148 
149    for (i = 0; i < ARRAY_SIZE(debug_source_enums); i++) {
150       if (debug_source_enums[i] == e)
151          break;
152    }
153    return i;
154 }
155 
156 static enum mesa_debug_type
gl_enum_to_debug_type(GLenum e)157 gl_enum_to_debug_type(GLenum e)
158 {
159    unsigned i;
160 
161    for (i = 0; i < ARRAY_SIZE(debug_type_enums); i++) {
162       if (debug_type_enums[i] == e)
163          break;
164    }
165    return i;
166 }
167 
168 static enum mesa_debug_severity
gl_enum_to_debug_severity(GLenum e)169 gl_enum_to_debug_severity(GLenum e)
170 {
171    unsigned i;
172 
173    for (i = 0; i < ARRAY_SIZE(debug_severity_enums); i++) {
174       if (debug_severity_enums[i] == e)
175          break;
176    }
177    return i;
178 }
179 
180 
181 /**
182  * Handles generating a GL_ARB_debug_output message ID generated by the GL or
183  * GLSL compiler.
184  *
185  * The GL API has this "ID" mechanism, where the intention is to allow a
186  * client to filter in/out messages based on source, type, and ID.  Of course,
187  * building a giant enum list of all debug output messages that Mesa might
188  * generate is ridiculous, so instead we have our caller pass us a pointer to
189  * static storage where the ID should get stored.  This ID will be shared
190  * across all contexts for that message (which seems like a desirable
191  * property, even if it's not expected by the spec), but note that it won't be
192  * the same between executions if messages aren't generated in the same order.
193  */
194 void
_mesa_debug_get_id(GLuint * id)195 _mesa_debug_get_id(GLuint *id)
196 {
197    if (!(*id)) {
198       /* Don't update *id if we raced with some other thread. */
199       p_atomic_cmpxchg(id, 0, p_atomic_inc_return(&PrevDynamicID));
200    }
201 }
202 
203 static void
debug_message_clear(struct gl_debug_message * msg)204 debug_message_clear(struct gl_debug_message *msg)
205 {
206    if (msg->message != (char*)out_of_memory)
207       free(msg->message);
208    msg->message = NULL;
209    msg->length = 0;
210 }
211 
212 static void
debug_message_store(struct gl_debug_message * msg,enum mesa_debug_source source,enum mesa_debug_type type,GLuint id,enum mesa_debug_severity severity,GLsizei len,const char * buf)213 debug_message_store(struct gl_debug_message *msg,
214                     enum mesa_debug_source source,
215                     enum mesa_debug_type type, GLuint id,
216                     enum mesa_debug_severity severity,
217                     GLsizei len, const char *buf)
218 {
219    GLsizei length = len;
220 
221    assert(!msg->message && !msg->length);
222 
223    if (length < 0)
224       length = strlen(buf);
225 
226    msg->message = malloc(length+1);
227    if (msg->message) {
228       (void) strncpy(msg->message, buf, (size_t)length);
229       msg->message[length] = '\0';
230 
231       msg->length = len;
232       msg->source = source;
233       msg->type = type;
234       msg->id = id;
235       msg->severity = severity;
236    } else {
237       static GLuint oom_msg_id = 0;
238       _mesa_debug_get_id(&oom_msg_id);
239 
240       /* malloc failed! */
241       msg->message = out_of_memory;
242       msg->length = -1;
243       msg->source = MESA_DEBUG_SOURCE_OTHER;
244       msg->type = MESA_DEBUG_TYPE_ERROR;
245       msg->id = oom_msg_id;
246       msg->severity = MESA_DEBUG_SEVERITY_HIGH;
247    }
248 }
249 
250 static void
debug_namespace_init(struct gl_debug_namespace * ns)251 debug_namespace_init(struct gl_debug_namespace *ns)
252 {
253    list_inithead(&ns->Elements);
254 
255    /* Enable all the messages with severity HIGH or MEDIUM by default */
256    ns->DefaultState = (1 << MESA_DEBUG_SEVERITY_MEDIUM ) |
257                       (1 << MESA_DEBUG_SEVERITY_HIGH) |
258                       (1 << MESA_DEBUG_SEVERITY_NOTIFICATION);
259 }
260 
261 static void
debug_namespace_clear(struct gl_debug_namespace * ns)262 debug_namespace_clear(struct gl_debug_namespace *ns)
263 {
264    list_for_each_entry_safe(struct gl_debug_element, elem, &ns->Elements, link)
265       free(elem);
266 }
267 
268 static bool
debug_namespace_copy(struct gl_debug_namespace * dst,const struct gl_debug_namespace * src)269 debug_namespace_copy(struct gl_debug_namespace *dst,
270                      const struct gl_debug_namespace *src)
271 {
272    dst->DefaultState = src->DefaultState;
273 
274    list_inithead(&dst->Elements);
275    list_for_each_entry(struct gl_debug_element, elem, &src->Elements, link) {
276       struct gl_debug_element *copy;
277 
278       copy = malloc(sizeof(*copy));
279       if (!copy) {
280          debug_namespace_clear(dst);
281          return false;
282       }
283 
284       copy->ID = elem->ID;
285       copy->State = elem->State;
286       list_addtail(&copy->link, &dst->Elements);
287    }
288 
289    return true;
290 }
291 
292 /**
293  * Set the state of \p id in the namespace.
294  */
295 static bool
debug_namespace_set(struct gl_debug_namespace * ns,GLuint id,bool enabled)296 debug_namespace_set(struct gl_debug_namespace *ns,
297                     GLuint id, bool enabled)
298 {
299    const uint32_t state = (enabled) ?
300       ((1 << MESA_DEBUG_SEVERITY_COUNT) - 1) : 0;
301    struct gl_debug_element *elem = NULL;
302 
303    /* find the element */
304    list_for_each_entry(struct gl_debug_element, tmp, &ns->Elements, link) {
305       if (tmp->ID == id) {
306          elem = tmp;
307          break;
308       }
309    }
310 
311    /* we do not need the element if it has the default state */
312    if (ns->DefaultState == state) {
313       if (elem) {
314          list_del(&elem->link);
315          free(elem);
316       }
317       return true;
318    }
319 
320    if (!elem) {
321       elem = malloc(sizeof(*elem));
322       if (!elem)
323          return false;
324 
325       elem->ID = id;
326       list_addtail(&elem->link, &ns->Elements);
327    }
328 
329    elem->State = state;
330 
331    return true;
332 }
333 
334 /**
335  * Set the default state of the namespace for \p severity.  When \p severity
336  * is MESA_DEBUG_SEVERITY_COUNT, the default values for all severities are
337  * updated.
338  */
339 static void
debug_namespace_set_all(struct gl_debug_namespace * ns,enum mesa_debug_severity severity,bool enabled)340 debug_namespace_set_all(struct gl_debug_namespace *ns,
341                         enum mesa_debug_severity severity,
342                         bool enabled)
343 {
344    uint32_t mask, val;
345 
346    /* set all elements to the same state */
347    if (severity == MESA_DEBUG_SEVERITY_COUNT) {
348       ns->DefaultState = (enabled) ? ((1 << severity) - 1) : 0;
349       debug_namespace_clear(ns);
350       list_inithead(&ns->Elements);
351       return;
352    }
353 
354    mask = 1 << severity;
355    val = (enabled) ? mask : 0;
356 
357    ns->DefaultState = (ns->DefaultState & ~mask) | val;
358 
359    list_for_each_entry_safe(struct gl_debug_element, elem, &ns->Elements,
360                             link) {
361       elem->State = (elem->State & ~mask) | val;
362       if (elem->State == ns->DefaultState) {
363          list_del(&elem->link);
364          free(elem);
365       }
366    }
367 }
368 
369 /**
370  * Get the state of \p id in the namespace.
371  */
372 static bool
debug_namespace_get(const struct gl_debug_namespace * ns,GLuint id,enum mesa_debug_severity severity)373 debug_namespace_get(const struct gl_debug_namespace *ns, GLuint id,
374                     enum mesa_debug_severity severity)
375 {
376    uint32_t state;
377 
378    state = ns->DefaultState;
379    list_for_each_entry(struct gl_debug_element, elem, &ns->Elements, link) {
380       if (elem->ID == id) {
381          state = elem->State;
382          break;
383       }
384    }
385 
386    return (state & (1 << severity));
387 }
388 
389 /**
390  * Allocate and initialize context debug state.
391  */
392 static struct gl_debug_state *
debug_create(void)393 debug_create(void)
394 {
395    struct gl_debug_state *debug;
396    int s, t;
397 
398    debug = CALLOC_STRUCT(gl_debug_state);
399    if (!debug)
400       return NULL;
401 
402    debug->Groups[0] = malloc(sizeof(*debug->Groups[0]));
403    if (!debug->Groups[0]) {
404       free(debug);
405       return NULL;
406    }
407 
408    /* Initialize state for filtering known debug messages. */
409    for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
410       for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
411          debug_namespace_init(&debug->Groups[0]->Namespaces[s][t]);
412    }
413 
414    return debug;
415 }
416 
417 /**
418  * Return true if the top debug group points to the group below it.
419  */
420 static bool
debug_is_group_read_only(const struct gl_debug_state * debug)421 debug_is_group_read_only(const struct gl_debug_state *debug)
422 {
423    const GLint gstack = debug->CurrentGroup;
424    return (gstack > 0 && debug->Groups[gstack] == debug->Groups[gstack - 1]);
425 }
426 
427 /**
428  * Make the top debug group writable.
429  */
430 static bool
debug_make_group_writable(struct gl_debug_state * debug)431 debug_make_group_writable(struct gl_debug_state *debug)
432 {
433    const GLint gstack = debug->CurrentGroup;
434    const struct gl_debug_group *src = debug->Groups[gstack];
435    struct gl_debug_group *dst;
436    int s, t;
437 
438    if (!debug_is_group_read_only(debug))
439       return true;
440 
441    dst = malloc(sizeof(*dst));
442    if (!dst)
443       return false;
444 
445    for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
446       for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
447          if (!debug_namespace_copy(&dst->Namespaces[s][t],
448                                    &src->Namespaces[s][t])) {
449             /* error path! */
450             for (t = t - 1; t >= 0; t--)
451                debug_namespace_clear(&dst->Namespaces[s][t]);
452             for (s = s - 1; s >= 0; s--) {
453                for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
454                   debug_namespace_clear(&dst->Namespaces[s][t]);
455             }
456             free(dst);
457             return false;
458          }
459       }
460    }
461 
462    debug->Groups[gstack] = dst;
463 
464    return true;
465 }
466 
467 /**
468  * Free the top debug group.
469  */
470 static void
debug_clear_group(struct gl_debug_state * debug)471 debug_clear_group(struct gl_debug_state *debug)
472 {
473    const GLint gstack = debug->CurrentGroup;
474 
475    if (!debug_is_group_read_only(debug)) {
476       struct gl_debug_group *grp = debug->Groups[gstack];
477       int s, t;
478 
479       for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
480          for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
481             debug_namespace_clear(&grp->Namespaces[s][t]);
482       }
483 
484       free(grp);
485    }
486 
487    debug->Groups[gstack] = NULL;
488 }
489 
490 /**
491  * Delete the oldest debug messages out of the log.
492  */
493 static void
debug_delete_messages(struct gl_debug_state * debug,int count)494 debug_delete_messages(struct gl_debug_state *debug, int count)
495 {
496    struct gl_debug_log *log = &debug->Log;
497 
498    if (count > log->NumMessages)
499       count = log->NumMessages;
500 
501    while (count--) {
502       struct gl_debug_message *msg = &log->Messages[log->NextMessage];
503 
504       debug_message_clear(msg);
505 
506       log->NumMessages--;
507       log->NextMessage++;
508       log->NextMessage %= MAX_DEBUG_LOGGED_MESSAGES;
509    }
510 }
511 
512 /**
513  * Loop through debug group stack tearing down states for
514  * filtering debug messages.  Then free debug output state.
515  */
516 static void
debug_destroy(struct gl_debug_state * debug)517 debug_destroy(struct gl_debug_state *debug)
518 {
519    while (debug->CurrentGroup > 0) {
520       debug_clear_group(debug);
521       debug->CurrentGroup--;
522    }
523 
524    debug_clear_group(debug);
525    debug_delete_messages(debug, debug->Log.NumMessages);
526    free(debug);
527 }
528 
529 /**
530  * Sets the state of the given message source/type/ID tuple.
531  */
532 static void
debug_set_message_enable(struct gl_debug_state * debug,enum mesa_debug_source source,enum mesa_debug_type type,GLuint id,GLboolean enabled)533 debug_set_message_enable(struct gl_debug_state *debug,
534                          enum mesa_debug_source source,
535                          enum mesa_debug_type type,
536                          GLuint id, GLboolean enabled)
537 {
538    const GLint gstack = debug->CurrentGroup;
539    struct gl_debug_namespace *ns;
540 
541    debug_make_group_writable(debug);
542    ns = &debug->Groups[gstack]->Namespaces[source][type];
543 
544    debug_namespace_set(ns, id, enabled);
545 }
546 
547 /*
548  * Set the state of all message IDs found in the given intersection of
549  * 'source', 'type', and 'severity'.  The _COUNT enum can be used for
550  * GL_DONT_CARE (include all messages in the class).
551  *
552  * This requires both setting the state of all previously seen message
553  * IDs in the hash table, and setting the default state for all
554  * applicable combinations of source/type/severity, so that all the
555  * yet-unknown message IDs that may be used in the future will be
556  * impacted as if they were already known.
557  */
558 static void
debug_set_message_enable_all(struct gl_debug_state * debug,enum mesa_debug_source source,enum mesa_debug_type type,enum mesa_debug_severity severity,GLboolean enabled)559 debug_set_message_enable_all(struct gl_debug_state *debug,
560                              enum mesa_debug_source source,
561                              enum mesa_debug_type type,
562                              enum mesa_debug_severity severity,
563                              GLboolean enabled)
564 {
565    const GLint gstack = debug->CurrentGroup;
566    int s, t, smax, tmax;
567 
568    if (source == MESA_DEBUG_SOURCE_COUNT) {
569       source = 0;
570       smax = MESA_DEBUG_SOURCE_COUNT;
571    } else {
572       smax = source+1;
573    }
574 
575    if (type == MESA_DEBUG_TYPE_COUNT) {
576       type = 0;
577       tmax = MESA_DEBUG_TYPE_COUNT;
578    } else {
579       tmax = type+1;
580    }
581 
582    debug_make_group_writable(debug);
583 
584    for (s = source; s < smax; s++) {
585       for (t = type; t < tmax; t++) {
586          struct gl_debug_namespace *nspace =
587             &debug->Groups[gstack]->Namespaces[s][t];
588          debug_namespace_set_all(nspace, severity, enabled);
589       }
590    }
591 }
592 
593 /**
594  * Returns if the given message source/type/ID tuple is enabled.
595  */
596 bool
_mesa_debug_is_message_enabled(const struct gl_debug_state * debug,enum mesa_debug_source source,enum mesa_debug_type type,GLuint id,enum mesa_debug_severity severity)597 _mesa_debug_is_message_enabled(const struct gl_debug_state *debug,
598                                enum mesa_debug_source source,
599                                enum mesa_debug_type type,
600                                GLuint id,
601                                enum mesa_debug_severity severity)
602 {
603    const GLint gstack = debug->CurrentGroup;
604    struct gl_debug_group *grp = debug->Groups[gstack];
605    struct gl_debug_namespace *nspace = &grp->Namespaces[source][type];
606 
607    if (!debug->DebugOutput)
608       return false;
609 
610    return debug_namespace_get(nspace, id, severity);
611 }
612 
613 /**
614  * 'buf' is not necessarily a null-terminated string. When logging, copy
615  * 'len' characters from it, store them in a new, null-terminated string,
616  * and remember the number of bytes used by that string, *including*
617  * the null terminator this time.
618  */
619 static void
debug_log_message(struct gl_debug_state * debug,enum mesa_debug_source source,enum mesa_debug_type type,GLuint id,enum mesa_debug_severity severity,GLsizei len,const char * buf)620 debug_log_message(struct gl_debug_state *debug,
621                   enum mesa_debug_source source,
622                   enum mesa_debug_type type, GLuint id,
623                   enum mesa_debug_severity severity,
624                   GLsizei len, const char *buf)
625 {
626    struct gl_debug_log *log = &debug->Log;
627    GLint nextEmpty;
628    struct gl_debug_message *emptySlot;
629 
630    if (debug->LogToStderr) {
631       _mesa_log("Mesa debug output: %.*s\n", len, buf);
632    }
633 
634    assert(len < MAX_DEBUG_MESSAGE_LENGTH);
635 
636    if (log->NumMessages == MAX_DEBUG_LOGGED_MESSAGES)
637       return;
638 
639    nextEmpty = (log->NextMessage + log->NumMessages)
640       % MAX_DEBUG_LOGGED_MESSAGES;
641    emptySlot = &log->Messages[nextEmpty];
642 
643    debug_message_store(emptySlot, source, type,
644                        id, severity, len, buf);
645 
646    log->NumMessages++;
647 }
648 
649 /**
650  * Return the oldest debug message out of the log.
651  */
652 static const struct gl_debug_message *
debug_fetch_message(const struct gl_debug_state * debug)653 debug_fetch_message(const struct gl_debug_state *debug)
654 {
655    const struct gl_debug_log *log = &debug->Log;
656 
657    return (log->NumMessages) ? &log->Messages[log->NextMessage] : NULL;
658 }
659 
660 static struct gl_debug_message *
debug_get_group_message(struct gl_debug_state * debug)661 debug_get_group_message(struct gl_debug_state *debug)
662 {
663    return &debug->GroupMessages[debug->CurrentGroup];
664 }
665 
666 static void
debug_push_group(struct gl_debug_state * debug)667 debug_push_group(struct gl_debug_state *debug)
668 {
669    const GLint gstack = debug->CurrentGroup;
670 
671    /* just point to the previous stack */
672    debug->Groups[gstack + 1] = debug->Groups[gstack];
673    debug->CurrentGroup++;
674 }
675 
676 static void
debug_pop_group(struct gl_debug_state * debug)677 debug_pop_group(struct gl_debug_state *debug)
678 {
679    debug_clear_group(debug);
680    debug->CurrentGroup--;
681 }
682 
683 
684 /**
685  * Installed as util_debug_callback when GL_DEBUG_OUTPUT is enabled.
686  */
687 static void
_debug_message(void * data,unsigned * id,enum util_debug_type ptype,const char * fmt,va_list args)688 _debug_message(void *data,
689                unsigned *id,
690                enum util_debug_type ptype,
691                const char *fmt,
692                va_list args)
693 {
694    struct gl_context *ctx = data;
695    enum mesa_debug_source source;
696    enum mesa_debug_type type;
697    enum mesa_debug_severity severity;
698 
699    switch (ptype) {
700    case UTIL_DEBUG_TYPE_OUT_OF_MEMORY:
701       source = MESA_DEBUG_SOURCE_API;
702       type = MESA_DEBUG_TYPE_ERROR;
703       severity = MESA_DEBUG_SEVERITY_MEDIUM;
704       break;
705    case UTIL_DEBUG_TYPE_ERROR:
706       source = MESA_DEBUG_SOURCE_API;
707       type = MESA_DEBUG_TYPE_ERROR;
708       severity = MESA_DEBUG_SEVERITY_MEDIUM;
709       break;
710    case UTIL_DEBUG_TYPE_SHADER_INFO:
711       source = MESA_DEBUG_SOURCE_SHADER_COMPILER;
712       type = MESA_DEBUG_TYPE_OTHER;
713       severity = MESA_DEBUG_SEVERITY_NOTIFICATION;
714       break;
715    case UTIL_DEBUG_TYPE_PERF_INFO:
716       source = MESA_DEBUG_SOURCE_API;
717       type = MESA_DEBUG_TYPE_PERFORMANCE;
718       severity = MESA_DEBUG_SEVERITY_NOTIFICATION;
719       break;
720    case UTIL_DEBUG_TYPE_INFO:
721       source = MESA_DEBUG_SOURCE_API;
722       type = MESA_DEBUG_TYPE_OTHER;
723       severity = MESA_DEBUG_SEVERITY_NOTIFICATION;
724       break;
725    case UTIL_DEBUG_TYPE_FALLBACK:
726       source = MESA_DEBUG_SOURCE_API;
727       type = MESA_DEBUG_TYPE_PERFORMANCE;
728       severity = MESA_DEBUG_SEVERITY_NOTIFICATION;
729       break;
730    case UTIL_DEBUG_TYPE_CONFORMANCE:
731       source = MESA_DEBUG_SOURCE_API;
732       type = MESA_DEBUG_TYPE_OTHER;
733       severity = MESA_DEBUG_SEVERITY_NOTIFICATION;
734       break;
735    default:
736       unreachable("invalid debug type");
737    }
738    _mesa_gl_vdebugf(ctx, id, source, type, severity, fmt, args);
739 }
740 
741 void
_mesa_update_debug_callback(struct gl_context * ctx)742 _mesa_update_debug_callback(struct gl_context *ctx)
743 {
744    struct pipe_context *pipe = ctx->pipe;
745 
746    if (!pipe->set_debug_callback)
747       return;
748 
749    if (_mesa_get_debug_state_int(ctx, GL_DEBUG_OUTPUT)) {
750       struct util_debug_callback cb;
751       memset(&cb, 0, sizeof(cb));
752       cb.async = !_mesa_get_debug_state_int(ctx, GL_DEBUG_OUTPUT_SYNCHRONOUS);
753       cb.debug_message = _debug_message;
754       cb.data = ctx;
755       pipe->set_debug_callback(pipe, &cb);
756    } else {
757       pipe->set_debug_callback(pipe, NULL);
758    }
759 }
760 
761 /**
762  * Lock and return debug state for the context.  The debug state will be
763  * allocated and initialized upon the first call.  When NULL is returned, the
764  * debug state is not locked.
765  */
766 static struct gl_debug_state *
_mesa_lock_debug_state(struct gl_context * ctx)767 _mesa_lock_debug_state(struct gl_context *ctx)
768 {
769    simple_mtx_lock(&ctx->DebugMutex);
770 
771    if (!ctx->Debug) {
772       ctx->Debug = debug_create();
773       if (!ctx->Debug) {
774          GET_CURRENT_CONTEXT(cur);
775          simple_mtx_unlock(&ctx->DebugMutex);
776 
777          /*
778           * This function may be called from other threads.  When that is the
779           * case, we cannot record this OOM error.
780           */
781          if (ctx == cur)
782             _mesa_error(ctx, GL_OUT_OF_MEMORY, "allocating debug state");
783 
784          return NULL;
785       }
786    }
787 
788    return ctx->Debug;
789 }
790 
791 static void
_mesa_unlock_debug_state(struct gl_context * ctx)792 _mesa_unlock_debug_state(struct gl_context *ctx)
793 {
794    simple_mtx_unlock(&ctx->DebugMutex);
795 }
796 
797 /**
798  * Set the integer debug state specified by \p pname.  This can be called from
799  * _mesa_set_enable for example.
800  */
801 bool
_mesa_set_debug_state_int(struct gl_context * ctx,GLenum pname,GLint val)802 _mesa_set_debug_state_int(struct gl_context *ctx, GLenum pname, GLint val)
803 {
804    struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
805 
806    if (!debug)
807       return false;
808 
809    switch (pname) {
810    case GL_DEBUG_OUTPUT:
811       debug->DebugOutput = (val != 0);
812       break;
813    case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
814       debug->SyncOutput = (val != 0);
815       break;
816    default:
817       assert(!"unknown debug output param");
818       break;
819    }
820 
821    _mesa_unlock_debug_state(ctx);
822 
823    return true;
824 }
825 
826 /**
827  * Query the integer debug state specified by \p pname.  This can be called
828  * _mesa_GetIntegerv for example.
829  */
830 GLint
_mesa_get_debug_state_int(struct gl_context * ctx,GLenum pname)831 _mesa_get_debug_state_int(struct gl_context *ctx, GLenum pname)
832 {
833    GLint val;
834 
835    struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
836    if (!debug)
837       return 0;
838 
839    switch (pname) {
840    case GL_DEBUG_OUTPUT:
841       val = debug->DebugOutput;
842       break;
843    case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
844       val = debug->SyncOutput;
845       break;
846    case GL_DEBUG_LOGGED_MESSAGES:
847       val = debug->Log.NumMessages;
848       break;
849    case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
850       val = (debug->Log.NumMessages) ?
851          debug->Log.Messages[debug->Log.NextMessage].length + 1 : 0;
852       break;
853    case GL_DEBUG_GROUP_STACK_DEPTH:
854       val = debug->CurrentGroup + 1;
855       break;
856    default:
857       assert(!"unknown debug output param");
858       val = 0;
859       break;
860    }
861 
862    _mesa_unlock_debug_state(ctx);
863 
864    return val;
865 }
866 
867 /**
868  * Query the pointer debug state specified by \p pname.  This can be called
869  * _mesa_GetPointerv for example.
870  */
871 void *
_mesa_get_debug_state_ptr(struct gl_context * ctx,GLenum pname)872 _mesa_get_debug_state_ptr(struct gl_context *ctx, GLenum pname)
873 {
874    void *val;
875    struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
876 
877    if (!debug)
878       return NULL;
879 
880    switch (pname) {
881    case GL_DEBUG_CALLBACK_FUNCTION_ARB:
882       val = (void *) debug->Callback;
883       break;
884    case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
885       val = (void *) debug->CallbackData;
886       break;
887    default:
888       assert(!"unknown debug output param");
889       val = NULL;
890       break;
891    }
892 
893    _mesa_unlock_debug_state(ctx);
894 
895    return val;
896 }
897 
898 /**
899  * Insert a debug message.  The mutex is assumed to be locked, and will be
900  * unlocked by this call.
901  */
902 static void
log_msg_locked_and_unlock(struct gl_context * ctx,enum mesa_debug_source source,enum mesa_debug_type type,GLuint id,enum mesa_debug_severity severity,GLint len,const char * buf)903 log_msg_locked_and_unlock(struct gl_context *ctx,
904                           enum mesa_debug_source source,
905                           enum mesa_debug_type type, GLuint id,
906                           enum mesa_debug_severity severity,
907                           GLint len, const char *buf)
908 {
909    struct gl_debug_state *debug = ctx->Debug;
910 
911    if (!_mesa_debug_is_message_enabled(debug, source, type, id, severity)) {
912       _mesa_unlock_debug_state(ctx);
913       return;
914    }
915 
916    if (ctx->Debug->Callback) {
917       /* Call the user's callback function */
918       GLenum gl_source = debug_source_enums[source];
919       GLenum gl_type = debug_type_enums[type];
920       GLenum gl_severity = debug_severity_enums[severity];
921       GLDEBUGPROC callback = ctx->Debug->Callback;
922       const void *data = ctx->Debug->CallbackData;
923 
924       /*
925        * When ctx->Debug->SyncOutput is GL_FALSE, the client is prepared for
926        * unsynchronous calls.  When it is GL_TRUE, we will not spawn threads.
927        * In either case, we can call the callback unlocked.
928        */
929       _mesa_unlock_debug_state(ctx);
930       callback(gl_source, gl_type, id, gl_severity, len, buf, data);
931    }
932    else {
933       /* add debug message to queue */
934       debug_log_message(ctx->Debug, source, type, id, severity, len, buf);
935       _mesa_unlock_debug_state(ctx);
936    }
937 }
938 
939 /**
940  * Log a client or driver debug message.
941  */
942 void
_mesa_log_msg(struct gl_context * ctx,enum mesa_debug_source source,enum mesa_debug_type type,GLuint id,enum mesa_debug_severity severity,GLint len,const char * buf)943 _mesa_log_msg(struct gl_context *ctx, enum mesa_debug_source source,
944               enum mesa_debug_type type, GLuint id,
945               enum mesa_debug_severity severity, GLint len, const char *buf)
946 {
947    struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
948 
949    if (!debug)
950       return;
951 
952    log_msg_locked_and_unlock(ctx, source, type, id, severity, len, buf);
953 }
954 
955 
956 /**
957  * Verify that source, type, and severity are valid enums.
958  *
959  * The 'caller' param is used for handling values available
960  * only in glDebugMessageInsert or glDebugMessageControl
961  */
962 static GLboolean
validate_params(struct gl_context * ctx,unsigned caller,const char * callerstr,GLenum source,GLenum type,GLenum severity)963 validate_params(struct gl_context *ctx, unsigned caller,
964                 const char *callerstr, GLenum source, GLenum type,
965                 GLenum severity)
966 {
967 #define INSERT 1
968 #define CONTROL 2
969    switch(source) {
970    case GL_DEBUG_SOURCE_APPLICATION_ARB:
971    case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
972       break;
973    case GL_DEBUG_SOURCE_API_ARB:
974    case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
975    case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
976    case GL_DEBUG_SOURCE_OTHER_ARB:
977       if (caller != INSERT)
978          break;
979       else
980          goto error;
981    case GL_DONT_CARE:
982       if (caller == CONTROL)
983          break;
984       else
985          goto error;
986    default:
987       goto error;
988    }
989 
990    switch(type) {
991    case GL_DEBUG_TYPE_ERROR_ARB:
992    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
993    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
994    case GL_DEBUG_TYPE_PERFORMANCE_ARB:
995    case GL_DEBUG_TYPE_PORTABILITY_ARB:
996    case GL_DEBUG_TYPE_OTHER_ARB:
997    case GL_DEBUG_TYPE_MARKER:
998    case GL_DEBUG_TYPE_PUSH_GROUP:
999    case GL_DEBUG_TYPE_POP_GROUP:
1000       break;
1001    case GL_DONT_CARE:
1002       if (caller == CONTROL)
1003          break;
1004       else
1005          goto error;
1006    default:
1007       goto error;
1008    }
1009 
1010    switch(severity) {
1011    case GL_DEBUG_SEVERITY_HIGH_ARB:
1012    case GL_DEBUG_SEVERITY_MEDIUM_ARB:
1013    case GL_DEBUG_SEVERITY_LOW_ARB:
1014    case GL_DEBUG_SEVERITY_NOTIFICATION:
1015       break;
1016    case GL_DONT_CARE:
1017       if (caller == CONTROL)
1018          break;
1019       else
1020          goto error;
1021    default:
1022       goto error;
1023    }
1024    return GL_TRUE;
1025 
1026 error:
1027    _mesa_error(ctx, GL_INVALID_ENUM, "bad values passed to %s"
1028                "(source=0x%x, type=0x%x, severity=0x%x)", callerstr,
1029                source, type, severity);
1030 
1031    return GL_FALSE;
1032 }
1033 
1034 
1035 static GLboolean
validate_length(struct gl_context * ctx,const char * callerstr,GLsizei length,const GLchar * buf)1036 validate_length(struct gl_context *ctx, const char *callerstr, GLsizei length,
1037                 const GLchar *buf)
1038 {
1039 
1040    if (length < 0) {
1041       GLsizei len = strlen(buf);
1042 
1043       if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
1044          _mesa_error(ctx, GL_INVALID_VALUE,
1045                     "%s(null terminated string length=%d, is not less than "
1046                     "GL_MAX_DEBUG_MESSAGE_LENGTH=%d)", callerstr, len,
1047                     MAX_DEBUG_MESSAGE_LENGTH);
1048          return GL_FALSE;
1049       }
1050    }
1051 
1052    if (length >= MAX_DEBUG_MESSAGE_LENGTH) {
1053       _mesa_error(ctx, GL_INVALID_VALUE,
1054                  "%s(length=%d, which is not less than "
1055                  "GL_MAX_DEBUG_MESSAGE_LENGTH=%d)", callerstr, length,
1056                  MAX_DEBUG_MESSAGE_LENGTH);
1057       return GL_FALSE;
1058    }
1059 
1060    return GL_TRUE;
1061 }
1062 
1063 
1064 void GLAPIENTRY
_mesa_DebugMessageInsert(GLenum source,GLenum type,GLuint id,GLenum severity,GLint length,const GLchar * buf)1065 _mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id,
1066                          GLenum severity, GLint length,
1067                          const GLchar *buf)
1068 {
1069    GET_CURRENT_CONTEXT(ctx);
1070    const char *callerstr;
1071 
1072    if (_mesa_is_desktop_gl(ctx))
1073       callerstr = "glDebugMessageInsert";
1074    else
1075       callerstr = "glDebugMessageInsertKHR";
1076 
1077    if (!validate_params(ctx, INSERT, callerstr, source, type, severity))
1078       return; /* GL_INVALID_ENUM */
1079 
1080    if (!validate_length(ctx, callerstr, length, buf))
1081       return; /* GL_INVALID_VALUE */
1082 
1083    /* if length not specified, string will be null terminated: */
1084    if (length < 0)
1085       length = strlen(buf);
1086 
1087    _mesa_log_msg(ctx, gl_enum_to_debug_source(source),
1088                  gl_enum_to_debug_type(type), id,
1089                  gl_enum_to_debug_severity(severity),
1090                  length, buf);
1091 
1092    if (type == GL_DEBUG_TYPE_MARKER && ctx->has_string_marker) {
1093       ctx->pipe->emit_string_marker(ctx->pipe, buf, length);
1094    }
1095 }
1096 
1097 
1098 GLuint GLAPIENTRY
_mesa_GetDebugMessageLog(GLuint count,GLsizei logSize,GLenum * sources,GLenum * types,GLenum * ids,GLenum * severities,GLsizei * lengths,GLchar * messageLog)1099 _mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum *sources,
1100                          GLenum *types, GLenum *ids, GLenum *severities,
1101                          GLsizei *lengths, GLchar *messageLog)
1102 {
1103    GET_CURRENT_CONTEXT(ctx);
1104    struct gl_debug_state *debug;
1105    const char *callerstr;
1106    GLuint ret;
1107 
1108    if (_mesa_is_desktop_gl(ctx))
1109       callerstr = "glGetDebugMessageLog";
1110    else
1111       callerstr = "glGetDebugMessageLogKHR";
1112 
1113    if (!messageLog)
1114       logSize = 0;
1115 
1116    if (logSize < 0) {
1117       _mesa_error(ctx, GL_INVALID_VALUE,
1118                   "%s(logSize=%d : logSize must not be negative)",
1119                   callerstr, logSize);
1120       return 0;
1121    }
1122 
1123    debug = _mesa_lock_debug_state(ctx);
1124    if (!debug)
1125       return 0;
1126 
1127    for (ret = 0; ret < count; ret++) {
1128       const struct gl_debug_message *msg = debug_fetch_message(debug);
1129       GLsizei len;
1130 
1131       if (!msg)
1132          break;
1133 
1134       len = msg->length;
1135       if (len < 0)
1136          len = strlen(msg->message);
1137 
1138       if (logSize < len+1 && messageLog != NULL)
1139          break;
1140 
1141       if (messageLog) {
1142          assert(msg->message[len] == '\0');
1143          (void) strncpy(messageLog, msg->message, (size_t)len+1);
1144 
1145          messageLog += len+1;
1146          logSize -= len+1;
1147       }
1148 
1149       if (lengths)
1150          *lengths++ = len+1;
1151       if (severities)
1152          *severities++ = debug_severity_enums[msg->severity];
1153       if (sources)
1154          *sources++ = debug_source_enums[msg->source];
1155       if (types)
1156          *types++ = debug_type_enums[msg->type];
1157       if (ids)
1158          *ids++ = msg->id;
1159 
1160       debug_delete_messages(debug, 1);
1161    }
1162 
1163    _mesa_unlock_debug_state(ctx);
1164 
1165    return ret;
1166 }
1167 
1168 
1169 void GLAPIENTRY
_mesa_DebugMessageControl(GLenum gl_source,GLenum gl_type,GLenum gl_severity,GLsizei count,const GLuint * ids,GLboolean enabled)1170 _mesa_DebugMessageControl(GLenum gl_source, GLenum gl_type,
1171                           GLenum gl_severity, GLsizei count,
1172                           const GLuint *ids, GLboolean enabled)
1173 {
1174    GET_CURRENT_CONTEXT(ctx);
1175    enum mesa_debug_source source = gl_enum_to_debug_source(gl_source);
1176    enum mesa_debug_type type = gl_enum_to_debug_type(gl_type);
1177    enum mesa_debug_severity severity = gl_enum_to_debug_severity(gl_severity);
1178    const char *callerstr;
1179    struct gl_debug_state *debug;
1180 
1181    if (_mesa_is_desktop_gl(ctx))
1182       callerstr = "glDebugMessageControl";
1183    else
1184       callerstr = "glDebugMessageControlKHR";
1185 
1186    if (count < 0) {
1187       _mesa_error(ctx, GL_INVALID_VALUE,
1188                   "%s(count=%d : count must not be negative)", callerstr,
1189                   count);
1190       return;
1191    }
1192 
1193    if (!validate_params(ctx, CONTROL, callerstr, gl_source, gl_type,
1194                         gl_severity))
1195       return; /* GL_INVALID_ENUM */
1196 
1197    if (count && (gl_severity != GL_DONT_CARE || gl_type == GL_DONT_CARE
1198                  || gl_source == GL_DONT_CARE)) {
1199       _mesa_error(ctx, GL_INVALID_OPERATION,
1200                   "%s(When passing an array of ids, severity must be"
1201          " GL_DONT_CARE, and source and type must not be GL_DONT_CARE.",
1202                   callerstr);
1203       return;
1204    }
1205 
1206    debug = _mesa_lock_debug_state(ctx);
1207    if (!debug)
1208       return;
1209 
1210    if (count) {
1211       GLsizei i;
1212       for (i = 0; i < count; i++)
1213          debug_set_message_enable(debug, source, type, ids[i], enabled);
1214    }
1215    else {
1216       debug_set_message_enable_all(debug, source, type, severity, enabled);
1217    }
1218 
1219    _mesa_unlock_debug_state(ctx);
1220 }
1221 
1222 
1223 void GLAPIENTRY
_mesa_DebugMessageCallback(GLDEBUGPROC callback,const void * userParam)1224 _mesa_DebugMessageCallback(GLDEBUGPROC callback, const void *userParam)
1225 {
1226    GET_CURRENT_CONTEXT(ctx);
1227    struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
1228    if (debug) {
1229       debug->Callback = callback;
1230       debug->CallbackData = userParam;
1231       _mesa_unlock_debug_state(ctx);
1232    }
1233 }
1234 
1235 
1236 void GLAPIENTRY
_mesa_PushDebugGroup(GLenum source,GLuint id,GLsizei length,const GLchar * message)1237 _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
1238                      const GLchar *message)
1239 {
1240    GET_CURRENT_CONTEXT(ctx);
1241    const char *callerstr;
1242    struct gl_debug_state *debug;
1243    struct gl_debug_message *emptySlot;
1244 
1245    if (_mesa_is_desktop_gl(ctx))
1246       callerstr = "glPushDebugGroup";
1247    else
1248       callerstr = "glPushDebugGroupKHR";
1249 
1250    switch(source) {
1251    case GL_DEBUG_SOURCE_APPLICATION:
1252    case GL_DEBUG_SOURCE_THIRD_PARTY:
1253       break;
1254    default:
1255       _mesa_error(ctx, GL_INVALID_ENUM, "bad value passed to %s"
1256                   "(source=0x%x)", callerstr, source);
1257       return;
1258    }
1259 
1260    if (!validate_length(ctx, callerstr, length, message))
1261       return; /* GL_INVALID_VALUE */
1262 
1263    if (length < 0)
1264       length = strlen(message);
1265 
1266    debug = _mesa_lock_debug_state(ctx);
1267    if (!debug)
1268       return;
1269 
1270    if (debug->CurrentGroup >= MAX_DEBUG_GROUP_STACK_DEPTH-1) {
1271       _mesa_unlock_debug_state(ctx);
1272       _mesa_error(ctx, GL_STACK_OVERFLOW, "%s", callerstr);
1273       return;
1274    }
1275 
1276    /* pop reuses the message details from push so we store this */
1277    emptySlot = debug_get_group_message(debug);
1278    debug_message_store(emptySlot,
1279                        gl_enum_to_debug_source(source),
1280                        gl_enum_to_debug_type(GL_DEBUG_TYPE_PUSH_GROUP),
1281                        id,
1282                        gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
1283                        length, message);
1284 
1285    debug_push_group(debug);
1286 
1287    log_msg_locked_and_unlock(ctx,
1288          gl_enum_to_debug_source(source),
1289          MESA_DEBUG_TYPE_PUSH_GROUP, id,
1290          MESA_DEBUG_SEVERITY_NOTIFICATION, length,
1291          message);
1292 }
1293 
1294 
1295 void GLAPIENTRY
_mesa_PopDebugGroup(void)1296 _mesa_PopDebugGroup(void)
1297 {
1298    GET_CURRENT_CONTEXT(ctx);
1299    const char *callerstr;
1300    struct gl_debug_state *debug;
1301    struct gl_debug_message *gdmessage, msg;
1302 
1303    if (_mesa_is_desktop_gl(ctx))
1304       callerstr = "glPopDebugGroup";
1305    else
1306       callerstr = "glPopDebugGroupKHR";
1307 
1308    debug = _mesa_lock_debug_state(ctx);
1309    if (!debug)
1310       return;
1311 
1312    if (debug->CurrentGroup <= 0) {
1313       _mesa_unlock_debug_state(ctx);
1314       _mesa_error(ctx, GL_STACK_UNDERFLOW, "%s", callerstr);
1315       return;
1316    }
1317 
1318    debug_pop_group(debug);
1319 
1320    /* make a shallow copy */
1321    gdmessage = debug_get_group_message(debug);
1322    msg = *gdmessage;
1323    gdmessage->message = NULL;
1324    gdmessage->length = 0;
1325 
1326    log_msg_locked_and_unlock(ctx,
1327          msg.source,
1328          gl_enum_to_debug_type(GL_DEBUG_TYPE_POP_GROUP),
1329          msg.id,
1330          gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
1331          msg.length, msg.message);
1332 
1333    debug_message_clear(&msg);
1334 }
1335 
1336 
1337 void
_mesa_init_debug_output(struct gl_context * ctx)1338 _mesa_init_debug_output(struct gl_context *ctx)
1339 {
1340    simple_mtx_init(&ctx->DebugMutex, mtx_plain);
1341 
1342    if (MESA_DEBUG_FLAGS & DEBUG_CONTEXT) {
1343       /* If the MESA_DEBUG env is set to "context", we'll turn on the
1344        * GL_CONTEXT_FLAG_DEBUG_BIT context flag and log debug output
1345        * messages to stderr (or whatever MESA_LOG_FILE points at).
1346        */
1347       struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
1348       if (!debug) {
1349          return;
1350       }
1351       debug->DebugOutput = GL_TRUE;
1352       debug->LogToStderr = GL_TRUE;
1353       ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
1354       _mesa_unlock_debug_state(ctx);
1355    }
1356 }
1357 
1358 
1359 void
_mesa_destroy_debug_output(struct gl_context * ctx)1360 _mesa_destroy_debug_output(struct gl_context *ctx)
1361 {
1362    if (ctx->Debug) {
1363       debug_destroy(ctx->Debug);
1364       /* set to NULL just in case it is used before context is completely gone. */
1365       ctx->Debug = NULL;
1366    }
1367 
1368    simple_mtx_destroy(&ctx->DebugMutex);
1369 }
1370 
1371 void GLAPIENTRY
_mesa_StringMarkerGREMEDY(GLsizei len,const GLvoid * string)1372 _mesa_StringMarkerGREMEDY(GLsizei len, const GLvoid *string)
1373 {
1374    GET_CURRENT_CONTEXT(ctx);
1375    if (ctx->Extensions.GREMEDY_string_marker) {
1376       /* if length not specified, string will be null terminated: */
1377       if (len <= 0)
1378          len = strlen(string);
1379       ctx->pipe->emit_string_marker(ctx->pipe, string, len);
1380    } else {
1381       _mesa_error(ctx, GL_INVALID_OPERATION, "StringMarkerGREMEDY");
1382    }
1383 }
1384