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