Merge remote branch 'origin/master' into radeon-rewrite
[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 struct pipe_transfer *transfer;
725 struct pipe_texture *texture = surface->texture;
726 struct pipe_screen *screen = texture->screen;
727
728 transfer = screen->get_tex_transfer(screen, texture, surface->face,
729 surface->level, surface->zslice,
730 PIPE_TRANSFER_READ, 0, 0, surface->width,
731 surface->height);
732
733 debug_dump_transfer_bmp(filename, transfer);
734
735 screen->tex_transfer_destroy(transfer);
736 }
737
738 void
739 debug_dump_transfer_bmp(const char *filename,
740 struct pipe_transfer *transfer)
741 {
742 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
743 struct util_stream *stream;
744 struct bmp_file_header bmfh;
745 struct bmp_info_header bmih;
746 float *rgba;
747 unsigned x, y;
748
749 if (!transfer)
750 goto error1;
751
752 rgba = MALLOC(transfer->width*transfer->height*4*sizeof(float));
753 if(!rgba)
754 goto error1;
755
756 bmfh.bfType = 0x4d42;
757 bmfh.bfSize = 14 + 40 + transfer->height*transfer->width*4;
758 bmfh.bfReserved1 = 0;
759 bmfh.bfReserved2 = 0;
760 bmfh.bfOffBits = 14 + 40;
761
762 bmih.biSize = 40;
763 bmih.biWidth = transfer->width;
764 bmih.biHeight = transfer->height;
765 bmih.biPlanes = 1;
766 bmih.biBitCount = 32;
767 bmih.biCompression = 0;
768 bmih.biSizeImage = transfer->height*transfer->width*4;
769 bmih.biXPelsPerMeter = 0;
770 bmih.biYPelsPerMeter = 0;
771 bmih.biClrUsed = 0;
772 bmih.biClrImportant = 0;
773
774 stream = util_stream_create(filename, bmfh.bfSize);
775 if(!stream)
776 goto error2;
777
778 util_stream_write(stream, &bmfh, 14);
779 util_stream_write(stream, &bmih, 40);
780
781 pipe_get_tile_rgba(transfer, 0, 0,
782 transfer->width, transfer->height,
783 rgba);
784
785 y = transfer->height;
786 while(y--) {
787 float *ptr = rgba + (transfer->width * y * 4);
788 for(x = 0; x < transfer->width; ++x)
789 {
790 struct bmp_rgb_quad pixel;
791 pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);
792 pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
793 pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
794 pixel.rgbAlpha = 255;
795 util_stream_write(stream, &pixel, 4);
796 }
797 }
798
799 util_stream_close(stream);
800 error2:
801 FREE(rgba);
802 error1:
803 ;
804 #endif
805 }
806
807 #endif