Merge master and fix conflicts
[mesa.git] / src / gallium / auxiliary / util / u_debug.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 <stdarg.h>
33
34
35 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
36
37 #include <windows.h>
38 #include <winddi.h>
39
40 #elif defined(PIPE_SUBSYSTEM_WINDOWS_CE)
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <windows.h>
45 #include <types.h>
46
47 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
48
49 #ifndef WIN32_LEAN_AND_MEAN
50 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
51 #endif
52 #include <windows.h>
53 #include <stdio.h>
54
55 #else
56
57 #include <stdio.h>
58 #include <stdlib.h>
59
60 #endif
61
62 #include "pipe/p_compiler.h"
63 #include "util/u_debug.h"
64 #include "pipe/p_format.h"
65 #include "pipe/p_state.h"
66 #include "pipe/p_inlines.h"
67 #include "util/u_memory.h"
68 #include "util/u_string.h"
69 #include "util/u_stream.h"
70 #include "util/u_math.h"
71 #include "util/u_tile.h"
72
73
74 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
75 static INLINE void
76 _EngDebugPrint(const char *format, ...)
77 {
78 va_list ap;
79 va_start(ap, format);
80 EngDebugPrint("", (PCHAR)format, ap);
81 va_end(ap);
82 }
83 #endif
84
85
86 void _debug_vprintf(const char *format, va_list ap)
87 {
88 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
89 /* EngDebugPrint does not handle float point arguments, so we need to use
90 * our own vsnprintf implementation. It is also very slow, so buffer until
91 * we find a newline. */
92 static char buf[512] = {'\0'};
93 size_t len = strlen(buf);
94 int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
95 if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
96 _EngDebugPrint("%s", buf);
97 buf[0] = '\0';
98 }
99 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
100 /* EngDebugPrint does not handle float point arguments, so we need to use
101 * our own vsnprintf implementation. It is also very slow, so buffer until
102 * we find a newline. */
103 static char buf[512 + 1] = {'\0'};
104 size_t len = strlen(buf);
105 int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
106 if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
107 OutputDebugStringA(buf);
108 buf[0] = '\0';
109 }
110
111 if(GetConsoleWindow() && !IsDebuggerPresent()) {
112 fflush(stdout);
113 vfprintf(stderr, format, ap);
114 fflush(stderr);
115 }
116
117 #elif defined(PIPE_SUBSYSTEM_WINDOWS_CE)
118 wchar_t *wide_format;
119 long wide_str_len;
120 char buf[512];
121 int ret;
122 #if (_WIN32_WCE < 600)
123 ret = vsprintf(buf, format, ap);
124 if(ret < 0){
125 sprintf(buf, "Cant handle debug print!");
126 ret = 25;
127 }
128 #else
129 ret = vsprintf_s(buf, 512, format, ap);
130 if(ret < 0){
131 sprintf_s(buf, 512, "Cant handle debug print!");
132 ret = 25;
133 }
134 #endif
135 buf[ret] = '\0';
136 /* Format is ascii - needs to be converted to wchar_t for printing */
137 wide_str_len = MultiByteToWideChar(CP_ACP, 0, (const char *) buf, -1, NULL, 0);
138 wide_format = (wchar_t *) malloc((wide_str_len+1) * sizeof(wchar_t));
139 if (wide_format) {
140 MultiByteToWideChar(CP_ACP, 0, (const char *) buf, -1,
141 wide_format, wide_str_len);
142 NKDbgPrintfW(wide_format, wide_format);
143 free(wide_format);
144 }
145 #elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
146 /* TODO */
147 #else /* !PIPE_SUBSYSTEM_WINDOWS */
148 #ifdef DEBUG
149 fflush(stdout);
150 vfprintf(stderr, format, ap);
151 #endif
152 #endif
153 }
154
155
156 #ifdef DEBUG
157 void debug_print_blob( const char *name,
158 const void *blob,
159 unsigned size )
160 {
161 const unsigned *ublob = (const unsigned *)blob;
162 unsigned i;
163
164 debug_printf("%s (%d dwords%s)\n", name, size/4,
165 size%4 ? "... plus a few bytes" : "");
166
167 for (i = 0; i < size/4; i++) {
168 debug_printf("%d:\t%08x\n", i, ublob[i]);
169 }
170 }
171 #endif
172
173
174 #ifndef debug_break
175 void debug_break(void)
176 {
177 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
178 DebugBreak();
179 #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
180 EngDebugBreak();
181 #else
182 abort();
183 #endif
184 }
185 #endif
186
187
188 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
189 static const char *
190 find(const char *start, const char *end, char c)
191 {
192 const char *p;
193 for(p = start; !end || p != end; ++p) {
194 if(*p == c)
195 return p;
196 if(*p < 32)
197 break;
198 }
199 return NULL;
200 }
201
202 static int
203 compare(const char *start, const char *end, const char *s)
204 {
205 const char *p, *q;
206 for(p = start, q = s; p != end && *q != '\0'; ++p, ++q) {
207 if(*p != *q)
208 return 0;
209 }
210 return p == end && *q == '\0';
211 }
212
213 static void
214 copy(char *dst, const char *start, const char *end, size_t n)
215 {
216 const char *p;
217 char *q;
218 for(p = start, q = dst, n = n - 1; p != end && n; ++p, ++q, --n)
219 *q = *p;
220 *q = '\0';
221 }
222 #endif
223
224
225 static INLINE const char *
226 _debug_get_option(const char *name)
227 {
228 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
229 /* EngMapFile creates the file if it does not exists, so it must either be
230 * disabled on release versions (or put in a less conspicuous place). */
231 #ifdef DEBUG
232 const char *result = NULL;
233 ULONG_PTR iFile = 0;
234 const void *pMap = NULL;
235 const char *sol, *eol, *sep;
236 static char output[1024];
237
238 pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile);
239 if(pMap) {
240 sol = (const char *)pMap;
241 while(1) {
242 /* TODO: handle LF line endings */
243 eol = find(sol, NULL, '\r');
244 if(!eol || eol == sol)
245 break;
246 sep = find(sol, eol, '=');
247 if(!sep)
248 break;
249 if(compare(sol, sep, name)) {
250 copy(output, sep + 1, eol, sizeof(output));
251 result = output;
252 break;
253 }
254 sol = eol + 2;
255 }
256 EngUnmapFile(iFile);
257 }
258 return result;
259 #else
260 return NULL;
261 #endif
262 #elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
263 /* TODO: implement */
264 return NULL;
265 #else
266 return getenv(name);
267 #endif
268 }
269
270 const char *
271 debug_get_option(const char *name, const char *dfault)
272 {
273 const char *result;
274
275 result = _debug_get_option(name);
276 if(!result)
277 result = dfault;
278
279 debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
280
281 return result;
282 }
283
284 boolean
285 debug_get_bool_option(const char *name, boolean dfault)
286 {
287 const char *str = _debug_get_option(name);
288 boolean result;
289
290 if(str == NULL)
291 result = dfault;
292 else if(!util_strcmp(str, "n"))
293 result = FALSE;
294 else if(!util_strcmp(str, "no"))
295 result = FALSE;
296 else if(!util_strcmp(str, "0"))
297 result = FALSE;
298 else if(!util_strcmp(str, "f"))
299 result = FALSE;
300 else if(!util_strcmp(str, "false"))
301 result = FALSE;
302 else
303 result = TRUE;
304
305 debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
306
307 return result;
308 }
309
310
311 long
312 debug_get_num_option(const char *name, long dfault)
313 {
314 long result;
315 const char *str;
316
317 str = _debug_get_option(name);
318 if(!str)
319 result = dfault;
320 else {
321 long sign;
322 char c;
323 c = *str++;
324 if(c == '-') {
325 sign = -1;
326 c = *str++;
327 }
328 else {
329 sign = 1;
330 }
331 result = 0;
332 while('0' <= c && c <= '9') {
333 result = result*10 + (c - '0');
334 c = *str++;
335 }
336 result *= sign;
337 }
338
339 debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
340
341 return result;
342 }
343
344
345 unsigned long
346 debug_get_flags_option(const char *name,
347 const struct debug_named_value *flags,
348 unsigned long dfault)
349 {
350 unsigned long result;
351 const char *str;
352
353 str = _debug_get_option(name);
354 if(!str)
355 result = dfault;
356 else if (!util_strcmp(str, "help")) {
357 result = dfault;
358 while (flags->name) {
359 debug_printf("%s: help for %s: %s [0x%lx]\n", __FUNCTION__, name, flags->name, flags->value);
360 flags++;
361 }
362 }
363 else {
364 result = 0;
365 while( flags->name ) {
366 if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
367 result |= flags->value;
368 ++flags;
369 }
370 }
371
372 if (str) {
373 debug_printf("%s: %s = 0x%lx (%s)\n", __FUNCTION__, name, result, str);
374 }
375 else {
376 debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
377 }
378
379 return result;
380 }
381
382
383 void _debug_assert_fail(const char *expr,
384 const char *file,
385 unsigned line,
386 const char *function)
387 {
388 _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
389 #if defined(PIPE_OS_WINDOWS) && !defined(PIPE_SUBSYSTEM_WINDOWS_USER)
390 if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", FALSE))
391 #else
392 if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
393 #endif
394 debug_break();
395 else
396 _debug_printf("continuing...\n");
397 }
398
399
400 const char *
401 debug_dump_enum(const struct debug_named_value *names,
402 unsigned long value)
403 {
404 static char rest[64];
405
406 while(names->name) {
407 if(names->value == value)
408 return names->name;
409 ++names;
410 }
411
412 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
413 return rest;
414 }
415
416
417 const char *
418 debug_dump_enum_noprefix(const struct debug_named_value *names,
419 const char *prefix,
420 unsigned long value)
421 {
422 static char rest[64];
423
424 while(names->name) {
425 if(names->value == value) {
426 const char *name = names->name;
427 while (*name == *prefix) {
428 name++;
429 prefix++;
430 }
431 return name;
432 }
433 ++names;
434 }
435
436
437
438 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
439 return rest;
440 }
441
442
443 const char *
444 debug_dump_flags(const struct debug_named_value *names,
445 unsigned long value)
446 {
447 static char output[4096];
448 static char rest[256];
449 int first = 1;
450
451 output[0] = '\0';
452
453 while(names->name) {
454 if((names->value & value) == names->value) {
455 if (!first)
456 util_strncat(output, "|", sizeof(output));
457 else
458 first = 0;
459 util_strncat(output, names->name, sizeof(output));
460 value &= ~names->value;
461 }
462 ++names;
463 }
464
465 if (value) {
466 if (!first)
467 util_strncat(output, "|", sizeof(output));
468 else
469 first = 0;
470
471 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
472 util_strncat(output, rest, sizeof(output));
473 }
474
475 if(first)
476 return "0";
477
478 return output;
479 }
480
481
482 static const struct debug_named_value pipe_format_names[] = {
483 #ifdef DEBUG
484 DEBUG_NAMED_VALUE(PIPE_FORMAT_NONE),
485 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_UNORM),
486 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_UNORM),
487 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_UNORM),
488 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_UNORM),
489 DEBUG_NAMED_VALUE(PIPE_FORMAT_A1R5G5B5_UNORM),
490 DEBUG_NAMED_VALUE(PIPE_FORMAT_A4R4G4B4_UNORM),
491 DEBUG_NAMED_VALUE(PIPE_FORMAT_R5G6B5_UNORM),
492 DEBUG_NAMED_VALUE(PIPE_FORMAT_A2B10G10R10_UNORM),
493 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_UNORM),
494 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_UNORM),
495 DEBUG_NAMED_VALUE(PIPE_FORMAT_I8_UNORM),
496 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_UNORM),
497 DEBUG_NAMED_VALUE(PIPE_FORMAT_L16_UNORM),
498 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR),
499 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR_REV),
500 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z16_UNORM),
501 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_UNORM),
502 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_FLOAT),
503 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8Z24_UNORM),
504 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24S8_UNORM),
505 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8Z24_UNORM),
506 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24X8_UNORM),
507 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8_UNORM),
508 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64_FLOAT),
509 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64_FLOAT),
510 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64_FLOAT),
511 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64A64_FLOAT),
512 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_FLOAT),
513 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_FLOAT),
514 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_FLOAT),
515 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_FLOAT),
516 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_UNORM),
517 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_UNORM),
518 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_UNORM),
519 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_UNORM),
520 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_USCALED),
521 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_USCALED),
522 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_USCALED),
523 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_USCALED),
524 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SNORM),
525 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SNORM),
526 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SNORM),
527 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SNORM),
528 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SSCALED),
529 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SSCALED),
530 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SSCALED),
531 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SSCALED),
532 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_UNORM),
533 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_UNORM),
534 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_UNORM),
535 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_UNORM),
536 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_USCALED),
537 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_USCALED),
538 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_USCALED),
539 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_USCALED),
540 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SNORM),
541 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SNORM),
542 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SNORM),
543 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SNORM),
544 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SSCALED),
545 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SSCALED),
546 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SSCALED),
547 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SSCALED),
548 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_UNORM),
549 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_UNORM),
550 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_UNORM),
551 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_UNORM),
552 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_UNORM),
553 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_USCALED),
554 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_USCALED),
555 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_USCALED),
556 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_USCALED),
557 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_USCALED),
558 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SNORM),
559 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SNORM),
560 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SNORM),
561 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SNORM),
562 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SNORM),
563 DEBUG_NAMED_VALUE(PIPE_FORMAT_B6G5R5_SNORM),
564 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8B8G8R8_SNORM),
565 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8B8G8R8_SNORM),
566 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SSCALED),
567 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SSCALED),
568 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SSCALED),
569 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SSCALED),
570 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SSCALED),
571 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_SRGB),
572 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_SRGB),
573 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SRGB),
574 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SRGB),
575 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SRGB),
576 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_SRGB),
577 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_SRGB),
578 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_SRGB),
579 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_SRGB),
580 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8UB8UG8SR8S_NORM),
581 DEBUG_NAMED_VALUE(PIPE_FORMAT_B6UG5SR5S_NORM),
582 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGB),
583 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGBA),
584 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_RGBA),
585 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_RGBA),
586 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_SRGB),
587 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_SRGBA),
588 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_SRGBA),
589 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_SRGBA),
590 #endif
591 DEBUG_NAMED_VALUE_END
592 };
593
594 #ifdef DEBUG
595 void debug_print_format(const char *msg, unsigned fmt )
596 {
597 debug_printf("%s: %s\n", msg, debug_dump_enum(pipe_format_names, fmt));
598 }
599 #endif
600
601 const char *pf_name( enum pipe_format format )
602 {
603 return debug_dump_enum(pipe_format_names, format);
604 }
605
606
607 #ifdef DEBUG
608 void debug_dump_image(const char *prefix,
609 unsigned format, unsigned cpp,
610 unsigned width, unsigned height,
611 unsigned stride,
612 const void *data)
613 {
614 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
615 static unsigned no = 0;
616 char filename[256];
617 WCHAR wfilename[sizeof(filename)];
618 ULONG_PTR iFile = 0;
619 struct {
620 unsigned format;
621 unsigned cpp;
622 unsigned width;
623 unsigned height;
624 } header;
625 unsigned char *pMap = NULL;
626 unsigned i;
627
628 util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix);
629 for(i = 0; i < sizeof(filename); ++i)
630 wfilename[i] = (WCHAR)filename[i];
631
632 pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + height*width*cpp, &iFile);
633 if(!pMap)
634 return;
635
636 header.format = format;
637 header.cpp = cpp;
638 header.width = width;
639 header.height = height;
640 memcpy(pMap, &header, sizeof(header));
641 pMap += sizeof(header);
642
643 for(i = 0; i < height; ++i) {
644 memcpy(pMap, (unsigned char *)data + stride*i, cpp*width);
645 pMap += cpp*width;
646 }
647
648 EngUnmapFile(iFile);
649 #endif
650 }
651
652 void debug_dump_surface(const char *prefix,
653 struct pipe_surface *surface)
654 {
655 struct pipe_texture *texture;
656 struct pipe_screen *screen;
657 struct pipe_transfer *transfer;
658 void *data;
659
660 if (!surface)
661 return;
662
663 texture = surface->texture;
664 screen = texture->screen;
665
666 transfer = screen->get_tex_transfer(screen, texture, surface->face,
667 surface->level, surface->zslice,
668 PIPE_TRANSFER_READ, 0, 0, surface->width,
669 surface->height);
670
671 data = screen->transfer_map(screen, transfer);
672 if(!data)
673 goto error;
674
675 debug_dump_image(prefix,
676 transfer->format,
677 transfer->block.size,
678 transfer->nblocksx,
679 transfer->nblocksy,
680 transfer->stride,
681 data);
682
683 screen->transfer_unmap(screen, transfer);
684 error:
685 screen->tex_transfer_destroy(transfer);
686 }
687
688
689 #pragma pack(push,2)
690 struct bmp_file_header {
691 uint16_t bfType;
692 uint32_t bfSize;
693 uint16_t bfReserved1;
694 uint16_t bfReserved2;
695 uint32_t bfOffBits;
696 };
697 #pragma pack(pop)
698
699 struct bmp_info_header {
700 uint32_t biSize;
701 int32_t biWidth;
702 int32_t biHeight;
703 uint16_t biPlanes;
704 uint16_t biBitCount;
705 uint32_t biCompression;
706 uint32_t biSizeImage;
707 int32_t biXPelsPerMeter;
708 int32_t biYPelsPerMeter;
709 uint32_t biClrUsed;
710 uint32_t biClrImportant;
711 };
712
713 struct bmp_rgb_quad {
714 uint8_t rgbBlue;
715 uint8_t rgbGreen;
716 uint8_t rgbRed;
717 uint8_t rgbAlpha;
718 };
719
720 void
721 debug_dump_surface_bmp(const char *filename,
722 struct pipe_surface *surface)
723 {
724 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
725 struct pipe_transfer *transfer;
726 struct pipe_texture *texture = surface->texture;
727 struct pipe_screen *screen = texture->screen;
728
729 transfer = screen->get_tex_transfer(screen, texture, surface->face,
730 surface->level, surface->zslice,
731 PIPE_TRANSFER_READ, 0, 0, surface->width,
732 surface->height);
733
734 debug_dump_transfer_bmp(filename, transfer);
735
736 screen->tex_transfer_destroy(transfer);
737 #endif
738 }
739
740 void
741 debug_dump_transfer_bmp(const char *filename,
742 struct pipe_transfer *transfer)
743 {
744 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
745 float *rgba;
746
747 if (!transfer)
748 goto error1;
749
750 rgba = MALLOC(transfer->width*transfer->height*4*sizeof(float));
751 if(!rgba)
752 goto error1;
753
754 pipe_get_tile_rgba(transfer, 0, 0,
755 transfer->width, transfer->height,
756 rgba);
757
758 debug_dump_float_rgba_bmp(filename,
759 transfer->width, transfer->height,
760 rgba, transfer->width);
761
762 FREE(rgba);
763 error1:
764 ;
765 #endif
766 }
767
768 void
769 debug_dump_float_rgba_bmp(const char *filename,
770 unsigned width, unsigned height,
771 float *rgba, unsigned stride)
772 {
773 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
774 struct util_stream *stream;
775 struct bmp_file_header bmfh;
776 struct bmp_info_header bmih;
777 unsigned x, y;
778
779 if(!rgba)
780 goto error1;
781
782 bmfh.bfType = 0x4d42;
783 bmfh.bfSize = 14 + 40 + height*width*4;
784 bmfh.bfReserved1 = 0;
785 bmfh.bfReserved2 = 0;
786 bmfh.bfOffBits = 14 + 40;
787
788 bmih.biSize = 40;
789 bmih.biWidth = width;
790 bmih.biHeight = height;
791 bmih.biPlanes = 1;
792 bmih.biBitCount = 32;
793 bmih.biCompression = 0;
794 bmih.biSizeImage = height*width*4;
795 bmih.biXPelsPerMeter = 0;
796 bmih.biYPelsPerMeter = 0;
797 bmih.biClrUsed = 0;
798 bmih.biClrImportant = 0;
799
800 stream = util_stream_create(filename, bmfh.bfSize);
801 if(!stream)
802 goto error1;
803
804 util_stream_write(stream, &bmfh, 14);
805 util_stream_write(stream, &bmih, 40);
806
807 y = height;
808 while(y--) {
809 float *ptr = rgba + (stride * y * 4);
810 for(x = 0; x < width; ++x)
811 {
812 struct bmp_rgb_quad pixel;
813 pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);
814 pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
815 pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
816 pixel.rgbAlpha = 255;
817 util_stream_write(stream, &pixel, 4);
818 }
819 }
820
821 util_stream_close(stream);
822 error1:
823 ;
824 #endif
825 }
826
827 #endif