7a3d51f12c100594472cf5436896e38b8bb9df3d
[mesa.git] / src / gallium / auxiliary / util / u_debug.c
1 /**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * Copyright (c) 2008 VMware, Inc.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29
30 #include "pipe/p_config.h"
31
32 #include "pipe/p_compiler.h"
33 #include "util/u_debug.h"
34 #include "pipe/p_format.h"
35 #include "pipe/p_state.h"
36 #include "util/u_inlines.h"
37 #include "util/u_format.h"
38 #include "util/u_memory.h"
39 #include "util/u_string.h"
40 #include "util/u_math.h"
41 #include "util/u_tile.h"
42 #include "util/u_prim.h"
43 #include "util/u_surface.h"
44 #include <inttypes.h>
45
46 #include <stdio.h>
47 #include <limits.h> /* CHAR_BIT */
48 #include <ctype.h> /* isalnum */
49
50 #ifdef _WIN32
51 #include <windows.h>
52 #include <stdlib.h>
53 #endif
54
55
56 void
57 _debug_vprintf(const char *format, va_list ap)
58 {
59 static char buf[4096] = {'\0'};
60 #if defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_EMBEDDED)
61 /* We buffer until we find a newline. */
62 size_t len = strlen(buf);
63 int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
64 if (ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
65 os_log_message(buf);
66 buf[0] = '\0';
67 }
68 #else
69 util_vsnprintf(buf, sizeof(buf), format, ap);
70 os_log_message(buf);
71 #endif
72 }
73
74
75 void
76 _pipe_debug_message(struct pipe_debug_callback *cb,
77 unsigned *id,
78 enum pipe_debug_type type,
79 const char *fmt, ...)
80 {
81 va_list args;
82 va_start(args, fmt);
83 if (cb && cb->debug_message)
84 cb->debug_message(cb->data, id, type, fmt, args);
85 va_end(args);
86 }
87
88
89 void
90 debug_disable_error_message_boxes(void)
91 {
92 #ifdef _WIN32
93 /* When Windows' error message boxes are disabled for this process (as is
94 * typically the case when running tests in an automated fashion) we disable
95 * CRT message boxes too.
96 */
97 UINT uMode = SetErrorMode(0);
98 SetErrorMode(uMode);
99 if (uMode & SEM_FAILCRITICALERRORS) {
100 /* Disable assertion failure message box.
101 * http://msdn.microsoft.com/en-us/library/sas1dkb2.aspx
102 */
103 _set_error_mode(_OUT_TO_STDERR);
104 #ifdef _MSC_VER
105 /* Disable abort message box.
106 * http://msdn.microsoft.com/en-us/library/e631wekh.aspx
107 */
108 _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
109 #endif
110 }
111 #endif /* _WIN32 */
112 }
113
114
115 #ifdef DEBUG
116 void
117 debug_print_blob(const char *name, const void *blob, unsigned size)
118 {
119 const unsigned *ublob = (const unsigned *)blob;
120 unsigned i;
121
122 debug_printf("%s (%d dwords%s)\n", name, size/4,
123 size%4 ? "... plus a few bytes" : "");
124
125 for (i = 0; i < size/4; i++) {
126 debug_printf("%d:\t%08x\n", i, ublob[i]);
127 }
128 }
129 #endif
130
131
132 static boolean
133 debug_get_option_should_print(void)
134 {
135 static boolean first = TRUE;
136 static boolean value = FALSE;
137
138 if (!first)
139 return value;
140
141 /* Oh hey this will call into this function,
142 * but its cool since we set first to false
143 */
144 first = FALSE;
145 value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", FALSE);
146 /* XXX should we print this option? Currently it wont */
147 return value;
148 }
149
150
151 const char *
152 debug_get_option(const char *name, const char *dfault)
153 {
154 const char *result;
155
156 result = os_get_option(name);
157 if (!result)
158 result = dfault;
159
160 if (debug_get_option_should_print())
161 debug_printf("%s: %s = %s\n", __FUNCTION__, name,
162 result ? result : "(null)");
163
164 return result;
165 }
166
167
168 boolean
169 debug_get_bool_option(const char *name, boolean dfault)
170 {
171 const char *str = os_get_option(name);
172 boolean result;
173
174 if (str == NULL)
175 result = dfault;
176 else if (!util_strcmp(str, "n"))
177 result = FALSE;
178 else if (!util_strcmp(str, "no"))
179 result = FALSE;
180 else if (!util_strcmp(str, "0"))
181 result = FALSE;
182 else if (!util_strcmp(str, "f"))
183 result = FALSE;
184 else if (!util_strcmp(str, "F"))
185 result = FALSE;
186 else if (!util_strcmp(str, "false"))
187 result = FALSE;
188 else if (!util_strcmp(str, "FALSE"))
189 result = FALSE;
190 else
191 result = TRUE;
192
193 if (debug_get_option_should_print())
194 debug_printf("%s: %s = %s\n", __FUNCTION__, name,
195 result ? "TRUE" : "FALSE");
196
197 return result;
198 }
199
200
201 long
202 debug_get_num_option(const char *name, long dfault)
203 {
204 long result;
205 const char *str;
206
207 str = os_get_option(name);
208 if (!str)
209 result = dfault;
210 else {
211 long sign;
212 char c;
213 c = *str++;
214 if (c == '-') {
215 sign = -1;
216 c = *str++;
217 }
218 else {
219 sign = 1;
220 }
221 result = 0;
222 while ('0' <= c && c <= '9') {
223 result = result*10 + (c - '0');
224 c = *str++;
225 }
226 result *= sign;
227 }
228
229 if (debug_get_option_should_print())
230 debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
231
232 return result;
233 }
234
235
236 static boolean
237 str_has_option(const char *str, const char *name)
238 {
239 /* Empty string. */
240 if (!*str) {
241 return FALSE;
242 }
243
244 /* OPTION=all */
245 if (!util_strcmp(str, "all")) {
246 return TRUE;
247 }
248
249 /* Find 'name' in 'str' surrounded by non-alphanumeric characters. */
250 {
251 const char *start = str;
252 unsigned name_len = strlen(name);
253
254 /* 'start' is the beginning of the currently-parsed word,
255 * we increment 'str' each iteration.
256 * if we find either the end of string or a non-alphanumeric character,
257 * we compare 'start' up to 'str-1' with 'name'. */
258
259 while (1) {
260 if (!*str || !(isalnum(*str) || *str == '_')) {
261 if (str-start == name_len &&
262 !memcmp(start, name, name_len)) {
263 return TRUE;
264 }
265
266 if (!*str) {
267 return FALSE;
268 }
269
270 start = str+1;
271 }
272
273 str++;
274 }
275 }
276
277 return FALSE;
278 }
279
280
281 uint64_t
282 debug_get_flags_option(const char *name,
283 const struct debug_named_value *flags,
284 uint64_t dfault)
285 {
286 uint64_t result;
287 const char *str;
288 const struct debug_named_value *orig = flags;
289 unsigned namealign = 0;
290
291 str = os_get_option(name);
292 if (!str)
293 result = dfault;
294 else if (!util_strcmp(str, "help")) {
295 result = dfault;
296 _debug_printf("%s: help for %s:\n", __FUNCTION__, name);
297 for (; flags->name; ++flags)
298 namealign = MAX2(namealign, strlen(flags->name));
299 for (flags = orig; flags->name; ++flags)
300 _debug_printf("| %*s [0x%0*"PRIx64"]%s%s\n", namealign, flags->name,
301 (int)sizeof(uint64_t)*CHAR_BIT/4, flags->value,
302 flags->desc ? " " : "", flags->desc ? flags->desc : "");
303 }
304 else {
305 result = 0;
306 while (flags->name) {
307 if (str_has_option(str, flags->name))
308 result |= flags->value;
309 ++flags;
310 }
311 }
312
313 if (debug_get_option_should_print()) {
314 if (str) {
315 debug_printf("%s: %s = 0x%"PRIx64" (%s)\n",
316 __FUNCTION__, name, result, str);
317 } else {
318 debug_printf("%s: %s = 0x%"PRIx64"\n", __FUNCTION__, name, result);
319 }
320 }
321
322 return result;
323 }
324
325
326 void
327 _debug_assert_fail(const char *expr, const char *file, unsigned line,
328 const char *function)
329 {
330 _debug_printf("%s:%u:%s: Assertion `%s' failed.\n",
331 file, line, function, expr);
332 os_abort();
333 }
334
335
336 const char *
337 debug_dump_enum(const struct debug_named_value *names,
338 unsigned long value)
339 {
340 static char rest[64];
341
342 while (names->name) {
343 if (names->value == value)
344 return names->name;
345 ++names;
346 }
347
348 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
349 return rest;
350 }
351
352
353 const char *
354 debug_dump_enum_noprefix(const struct debug_named_value *names,
355 const char *prefix,
356 unsigned long value)
357 {
358 static char rest[64];
359
360 while (names->name) {
361 if (names->value == value) {
362 const char *name = names->name;
363 while (*name == *prefix) {
364 name++;
365 prefix++;
366 }
367 return name;
368 }
369 ++names;
370 }
371
372 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
373 return rest;
374 }
375
376
377 const char *
378 debug_dump_flags(const struct debug_named_value *names, unsigned long value)
379 {
380 static char output[4096];
381 static char rest[256];
382 int first = 1;
383
384 output[0] = '\0';
385
386 while (names->name) {
387 if ((names->value & value) == names->value) {
388 if (!first)
389 util_strncat(output, "|", sizeof(output) - strlen(output) - 1);
390 else
391 first = 0;
392 util_strncat(output, names->name, sizeof(output) - strlen(output) - 1);
393 output[sizeof(output) - 1] = '\0';
394 value &= ~names->value;
395 }
396 ++names;
397 }
398
399 if (value) {
400 if (!first)
401 util_strncat(output, "|", sizeof(output) - strlen(output) - 1);
402 else
403 first = 0;
404
405 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
406 util_strncat(output, rest, sizeof(output) - strlen(output) - 1);
407 output[sizeof(output) - 1] = '\0';
408 }
409
410 if (first)
411 return "0";
412
413 return output;
414 }
415
416
417 #ifdef DEBUG
418 void
419 debug_print_format(const char *msg, unsigned fmt )
420 {
421 debug_printf("%s: %s\n", msg, util_format_name(fmt));
422 }
423 #endif
424
425
426 /** Return string name of given primitive type */
427 const char *
428 u_prim_name(unsigned prim)
429 {
430 static const struct debug_named_value names[] = {
431 DEBUG_NAMED_VALUE(PIPE_PRIM_POINTS),
432 DEBUG_NAMED_VALUE(PIPE_PRIM_LINES),
433 DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_LOOP),
434 DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP),
435 DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES),
436 DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP),
437 DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_FAN),
438 DEBUG_NAMED_VALUE(PIPE_PRIM_QUADS),
439 DEBUG_NAMED_VALUE(PIPE_PRIM_QUAD_STRIP),
440 DEBUG_NAMED_VALUE(PIPE_PRIM_POLYGON),
441 DEBUG_NAMED_VALUE(PIPE_PRIM_LINES_ADJACENCY),
442 DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP_ADJACENCY),
443 DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES_ADJACENCY),
444 DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY),
445 DEBUG_NAMED_VALUE_END
446 };
447 return debug_dump_enum(names, prim);
448 }
449
450
451
452 #ifdef DEBUG
453 int fl_indent = 0;
454 const char* fl_function[1024];
455
456 int
457 debug_funclog_enter(const char* f, const int line, const char* file)
458 {
459 int i;
460
461 for (i = 0; i < fl_indent; i++)
462 debug_printf(" ");
463 debug_printf("%s\n", f);
464
465 assert(fl_indent < 1023);
466 fl_function[fl_indent++] = f;
467
468 return 0;
469 }
470
471 void
472 debug_funclog_exit(const char* f, const int line, const char* file)
473 {
474 --fl_indent;
475 assert(fl_indent >= 0);
476 assert(fl_function[fl_indent] == f);
477 }
478
479 void
480 debug_funclog_enter_exit(const char* f, const int line, const char* file)
481 {
482 int i;
483 for (i = 0; i < fl_indent; i++)
484 debug_printf(" ");
485 debug_printf("%s\n", f);
486 }
487 #endif
488
489
490
491 #ifdef DEBUG
492 /**
493 * Dump an image to .ppm file.
494 * \param format PIPE_FORMAT_x
495 * \param cpp bytes per pixel
496 * \param width width in pixels
497 * \param height height in pixels
498 * \param stride row stride in bytes
499 */
500 void
501 debug_dump_image(const char *prefix,
502 enum pipe_format format, unsigned cpp,
503 unsigned width, unsigned height,
504 unsigned stride,
505 const void *data)
506 {
507 /* write a ppm file */
508 char filename[256];
509 unsigned char *rgb8;
510 FILE *f;
511
512 util_snprintf(filename, sizeof(filename), "%s.ppm", prefix);
513
514 rgb8 = MALLOC(height * width * 3);
515 if (!rgb8) {
516 return;
517 }
518
519 util_format_translate(
520 PIPE_FORMAT_R8G8B8_UNORM,
521 rgb8, width * 3,
522 0, 0,
523 format,
524 data, stride,
525 0, 0, width, height);
526
527 /* Must be opened in binary mode or DOS line ending causes data
528 * to be read with one byte offset.
529 */
530 f = fopen(filename, "wb");
531 if (f) {
532 fprintf(f, "P6\n");
533 fprintf(f, "# ppm-file created by gallium\n");
534 fprintf(f, "%i %i\n", width, height);
535 fprintf(f, "255\n");
536 fwrite(rgb8, 1, height * width * 3, f);
537 fclose(f);
538 }
539 else {
540 fprintf(stderr, "Can't open %s for writing\n", filename);
541 }
542
543 FREE(rgb8);
544 }
545
546
547 /* FIXME: dump resources, not surfaces... */
548 void
549 debug_dump_surface(struct pipe_context *pipe,
550 const char *prefix,
551 struct pipe_surface *surface)
552 {
553 struct pipe_resource *texture;
554 struct pipe_transfer *transfer;
555 void *data;
556
557 if (!surface)
558 return;
559
560 /* XXX: this doesn't necessarily work, as the driver may be using
561 * temporary storage for the surface which hasn't been propagated
562 * back into the texture. Need to nail down the semantics of views
563 * and transfers a bit better before we can say if extra work needs
564 * to be done here:
565 */
566 texture = surface->texture;
567
568 data = pipe_transfer_map(pipe, texture, surface->u.tex.level,
569 surface->u.tex.first_layer,
570 PIPE_TRANSFER_READ,
571 0, 0, surface->width, surface->height, &transfer);
572 if (!data)
573 return;
574
575 debug_dump_image(prefix,
576 texture->format,
577 util_format_get_blocksize(texture->format),
578 util_format_get_nblocksx(texture->format, surface->width),
579 util_format_get_nblocksy(texture->format, surface->height),
580 transfer->stride,
581 data);
582
583 pipe->transfer_unmap(pipe, transfer);
584 }
585
586
587 void
588 debug_dump_texture(struct pipe_context *pipe,
589 const char *prefix,
590 struct pipe_resource *texture)
591 {
592 struct pipe_surface *surface, surf_tmpl;
593
594 if (!texture)
595 return;
596
597 /* XXX for now, just dump image for layer=0, level=0 */
598 u_surface_default_template(&surf_tmpl, texture);
599 surface = pipe->create_surface(pipe, texture, &surf_tmpl);
600 if (surface) {
601 debug_dump_surface(pipe, prefix, surface);
602 pipe->surface_destroy(pipe, surface);
603 }
604 }
605
606
607 #pragma pack(push,2)
608 struct bmp_file_header {
609 uint16_t bfType;
610 uint32_t bfSize;
611 uint16_t bfReserved1;
612 uint16_t bfReserved2;
613 uint32_t bfOffBits;
614 };
615 #pragma pack(pop)
616
617 struct bmp_info_header {
618 uint32_t biSize;
619 int32_t biWidth;
620 int32_t biHeight;
621 uint16_t biPlanes;
622 uint16_t biBitCount;
623 uint32_t biCompression;
624 uint32_t biSizeImage;
625 int32_t biXPelsPerMeter;
626 int32_t biYPelsPerMeter;
627 uint32_t biClrUsed;
628 uint32_t biClrImportant;
629 };
630
631 struct bmp_rgb_quad {
632 uint8_t rgbBlue;
633 uint8_t rgbGreen;
634 uint8_t rgbRed;
635 uint8_t rgbAlpha;
636 };
637
638 void
639 debug_dump_surface_bmp(struct pipe_context *pipe,
640 const char *filename,
641 struct pipe_surface *surface)
642 {
643 struct pipe_transfer *transfer;
644 struct pipe_resource *texture = surface->texture;
645 void *ptr;
646
647 ptr = pipe_transfer_map(pipe, texture, surface->u.tex.level,
648 surface->u.tex.first_layer, PIPE_TRANSFER_READ,
649 0, 0, surface->width, surface->height, &transfer);
650
651 debug_dump_transfer_bmp(pipe, filename, transfer, ptr);
652
653 pipe->transfer_unmap(pipe, transfer);
654 }
655
656 void
657 debug_dump_transfer_bmp(struct pipe_context *pipe,
658 const char *filename,
659 struct pipe_transfer *transfer, void *ptr)
660 {
661 float *rgba;
662
663 if (!transfer)
664 goto error1;
665
666 rgba = MALLOC(transfer->box.width *
667 transfer->box.height *
668 transfer->box.depth *
669 4*sizeof(float));
670 if (!rgba)
671 goto error1;
672
673 pipe_get_tile_rgba(transfer, ptr, 0, 0,
674 transfer->box.width, transfer->box.height,
675 rgba);
676
677 debug_dump_float_rgba_bmp(filename,
678 transfer->box.width, transfer->box.height,
679 rgba, transfer->box.width);
680
681 FREE(rgba);
682 error1:
683 ;
684 }
685
686 void
687 debug_dump_float_rgba_bmp(const char *filename,
688 unsigned width, unsigned height,
689 float *rgba, unsigned stride)
690 {
691 FILE *stream;
692 struct bmp_file_header bmfh;
693 struct bmp_info_header bmih;
694 unsigned x, y;
695
696 if (!rgba)
697 goto error1;
698
699 bmfh.bfType = 0x4d42;
700 bmfh.bfSize = 14 + 40 + height*width*4;
701 bmfh.bfReserved1 = 0;
702 bmfh.bfReserved2 = 0;
703 bmfh.bfOffBits = 14 + 40;
704
705 bmih.biSize = 40;
706 bmih.biWidth = width;
707 bmih.biHeight = height;
708 bmih.biPlanes = 1;
709 bmih.biBitCount = 32;
710 bmih.biCompression = 0;
711 bmih.biSizeImage = height*width*4;
712 bmih.biXPelsPerMeter = 0;
713 bmih.biYPelsPerMeter = 0;
714 bmih.biClrUsed = 0;
715 bmih.biClrImportant = 0;
716
717 stream = fopen(filename, "wb");
718 if (!stream)
719 goto error1;
720
721 fwrite(&bmfh, 14, 1, stream);
722 fwrite(&bmih, 40, 1, stream);
723
724 y = height;
725 while (y--) {
726 float *ptr = rgba + (stride * y * 4);
727 for (x = 0; x < width; ++x) {
728 struct bmp_rgb_quad pixel;
729 pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);
730 pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
731 pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
732 pixel.rgbAlpha = float_to_ubyte(ptr[x*4 + 3]);
733 fwrite(&pixel, 1, 4, stream);
734 }
735 }
736
737 fclose(stream);
738 error1:
739 ;
740 }
741
742 void
743 debug_dump_ubyte_rgba_bmp(const char *filename,
744 unsigned width, unsigned height,
745 const ubyte *rgba, unsigned stride)
746 {
747 FILE *stream;
748 struct bmp_file_header bmfh;
749 struct bmp_info_header bmih;
750 unsigned x, y;
751
752 assert(rgba);
753 if (!rgba)
754 goto error1;
755
756 bmfh.bfType = 0x4d42;
757 bmfh.bfSize = 14 + 40 + height*width*4;
758 bmfh.bfReserved1 = 0;
759 bmfh.bfReserved2 = 0;
760 bmfh.bfOffBits = 14 + 40;
761
762 bmih.biSize = 40;
763 bmih.biWidth = width;
764 bmih.biHeight = height;
765 bmih.biPlanes = 1;
766 bmih.biBitCount = 32;
767 bmih.biCompression = 0;
768 bmih.biSizeImage = height*width*4;
769 bmih.biXPelsPerMeter = 0;
770 bmih.biYPelsPerMeter = 0;
771 bmih.biClrUsed = 0;
772 bmih.biClrImportant = 0;
773
774 stream = fopen(filename, "wb");
775 assert(stream);
776 if (!stream)
777 goto error1;
778
779 fwrite(&bmfh, 14, 1, stream);
780 fwrite(&bmih, 40, 1, stream);
781
782 y = height;
783 while (y--) {
784 const ubyte *ptr = rgba + (stride * y * 4);
785 for (x = 0; x < width; ++x) {
786 struct bmp_rgb_quad pixel;
787 pixel.rgbRed = ptr[x*4 + 0];
788 pixel.rgbGreen = ptr[x*4 + 1];
789 pixel.rgbBlue = ptr[x*4 + 2];
790 pixel.rgbAlpha = ptr[x*4 + 3];
791 fwrite(&pixel, 1, 4, stream);
792 }
793 }
794
795 fclose(stream);
796 error1:
797 ;
798 }
799
800
801 /**
802 * Print PIPE_TRANSFER_x flags with a message.
803 */
804 void
805 debug_print_transfer_flags(const char *msg, unsigned usage)
806 {
807 static const struct debug_named_value names[] = {
808 DEBUG_NAMED_VALUE(PIPE_TRANSFER_READ),
809 DEBUG_NAMED_VALUE(PIPE_TRANSFER_WRITE),
810 DEBUG_NAMED_VALUE(PIPE_TRANSFER_MAP_DIRECTLY),
811 DEBUG_NAMED_VALUE(PIPE_TRANSFER_DISCARD_RANGE),
812 DEBUG_NAMED_VALUE(PIPE_TRANSFER_DONTBLOCK),
813 DEBUG_NAMED_VALUE(PIPE_TRANSFER_UNSYNCHRONIZED),
814 DEBUG_NAMED_VALUE(PIPE_TRANSFER_FLUSH_EXPLICIT),
815 DEBUG_NAMED_VALUE(PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE),
816 DEBUG_NAMED_VALUE(PIPE_TRANSFER_PERSISTENT),
817 DEBUG_NAMED_VALUE(PIPE_TRANSFER_COHERENT),
818 DEBUG_NAMED_VALUE_END
819 };
820
821 debug_printf("%s: %s\n", msg, debug_dump_flags(names, usage));
822 }
823
824
825 /**
826 * Print PIPE_BIND_x flags with a message.
827 */
828 void
829 debug_print_bind_flags(const char *msg, unsigned usage)
830 {
831 static const struct debug_named_value names[] = {
832 DEBUG_NAMED_VALUE(PIPE_BIND_DEPTH_STENCIL),
833 DEBUG_NAMED_VALUE(PIPE_BIND_RENDER_TARGET),
834 DEBUG_NAMED_VALUE(PIPE_BIND_BLENDABLE),
835 DEBUG_NAMED_VALUE(PIPE_BIND_SAMPLER_VIEW),
836 DEBUG_NAMED_VALUE(PIPE_BIND_VERTEX_BUFFER),
837 DEBUG_NAMED_VALUE(PIPE_BIND_INDEX_BUFFER),
838 DEBUG_NAMED_VALUE(PIPE_BIND_CONSTANT_BUFFER),
839 DEBUG_NAMED_VALUE(PIPE_BIND_DISPLAY_TARGET),
840 DEBUG_NAMED_VALUE(PIPE_BIND_TRANSFER_WRITE),
841 DEBUG_NAMED_VALUE(PIPE_BIND_TRANSFER_READ),
842 DEBUG_NAMED_VALUE(PIPE_BIND_STREAM_OUTPUT),
843 DEBUG_NAMED_VALUE(PIPE_BIND_CURSOR),
844 DEBUG_NAMED_VALUE(PIPE_BIND_CUSTOM),
845 DEBUG_NAMED_VALUE(PIPE_BIND_GLOBAL),
846 DEBUG_NAMED_VALUE(PIPE_BIND_SHADER_BUFFER),
847 DEBUG_NAMED_VALUE(PIPE_BIND_SHADER_IMAGE),
848 DEBUG_NAMED_VALUE(PIPE_BIND_COMPUTE_RESOURCE),
849 DEBUG_NAMED_VALUE(PIPE_BIND_COMMAND_ARGS_BUFFER),
850 DEBUG_NAMED_VALUE(PIPE_BIND_SCANOUT),
851 DEBUG_NAMED_VALUE(PIPE_BIND_SHARED),
852 DEBUG_NAMED_VALUE(PIPE_BIND_LINEAR),
853 DEBUG_NAMED_VALUE_END
854 };
855
856 debug_printf("%s: %s\n", msg, debug_dump_flags(names, usage));
857 }
858
859
860 /**
861 * Print PIPE_USAGE_x enum values with a message.
862 */
863 void
864 debug_print_usage_enum(const char *msg, unsigned usage)
865 {
866 static const struct debug_named_value names[] = {
867 DEBUG_NAMED_VALUE(PIPE_USAGE_DEFAULT),
868 DEBUG_NAMED_VALUE(PIPE_USAGE_IMMUTABLE),
869 DEBUG_NAMED_VALUE(PIPE_USAGE_DYNAMIC),
870 DEBUG_NAMED_VALUE(PIPE_USAGE_STREAM),
871 DEBUG_NAMED_VALUE(PIPE_USAGE_STAGING),
872 DEBUG_NAMED_VALUE_END
873 };
874
875 debug_printf("%s: %s\n", msg, debug_dump_enum(names, usage));
876 }
877
878
879 #endif