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(©->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