1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
29 #include "pipe/p_config.h"
34 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
39 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
41 #ifndef WIN32_LEAN_AND_MEAN
42 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
53 #include "pipe/p_compiler.h"
54 #include "pipe/p_debug.h"
55 #include "pipe/p_format.h"
56 #include "pipe/p_state.h"
57 #include "pipe/p_inlines.h"
58 #include "util/u_memory.h"
59 #include "util/u_string.h"
60 #include "util/u_stream.h"
61 #include "util/u_math.h"
62 #include "util/u_tile.h"
65 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
67 _EngDebugPrint(const char *format
, ...)
71 EngDebugPrint("", (PCHAR
)format
, ap
);
77 void _debug_vprintf(const char *format
, va_list ap
)
79 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
80 /* EngDebugPrint does not handle float point arguments, so we need to use
81 * our own vsnprintf implementation. It is also very slow, so buffer until
82 * we find a newline. */
83 static char buf
[512] = {'\0'};
84 size_t len
= strlen(buf
);
85 int ret
= util_vsnprintf(buf
+ len
, sizeof(buf
) - len
, format
, ap
);
86 if(ret
> (int)(sizeof(buf
) - len
- 1) || util_strchr(buf
+ len
, '\n')) {
87 _EngDebugPrint("%s", buf
);
90 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
91 /* EngDebugPrint does not handle float point arguments, so we need to use
92 * our own vsnprintf implementation. It is also very slow, so buffer until
93 * we find a newline. */
94 static char buf
[512 + 1] = {'\0'};
95 size_t len
= strlen(buf
);
96 int ret
= util_vsnprintf(buf
+ len
, sizeof(buf
) - len
, format
, ap
);
97 if(ret
> (int)(sizeof(buf
) - len
- 1) || util_strchr(buf
+ len
, '\n')) {
98 OutputDebugStringA(buf
);
101 #elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
103 #else /* !PIPE_SUBSYSTEM_WINDOWS */
105 vfprintf(stderr
, format
, ap
);
112 void debug_print_blob( const char *name
,
116 const unsigned *ublob
= (const unsigned *)blob
;
119 debug_printf("%s (%d dwords%s)\n", name
, size
/4,
120 size
%4 ? "... plus a few bytes" : "");
122 for (i
= 0; i
< size
/4; i
++) {
123 debug_printf("%d:\t%08x\n", i
, ublob
[i
]);
129 void _debug_break(void)
131 #if defined(PIPE_ARCH_X86) && defined(PIPE_CC_GCC)
133 #elif defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)
135 #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
143 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
145 find(const char *start
, const char *end
, char c
)
148 for(p
= start
; !end
|| p
!= end
; ++p
) {
158 compare(const char *start
, const char *end
, const char *s
)
161 for(p
= start
, q
= s
; p
!= end
&& *q
!= '\0'; ++p
, ++q
) {
165 return p
== end
&& *q
== '\0';
169 copy(char *dst
, const char *start
, const char *end
, size_t n
)
173 for(p
= start
, q
= dst
, n
= n
- 1; p
!= end
&& n
; ++p
, ++q
, --n
)
180 static INLINE
const char *
181 _debug_get_option(const char *name
)
183 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
184 /* EngMapFile creates the file if it does not exists, so it must either be
185 * disabled on release versions (or put in a less conspicuous place). */
187 const char *result
= NULL
;
189 const void *pMap
= NULL
;
190 const char *sol
, *eol
, *sep
;
191 static char output
[1024];
193 pMap
= EngMapFile(L
"\\??\\c:\\gallium.cfg", 0, &iFile
);
195 sol
= (const char *)pMap
;
197 /* TODO: handle LF line endings */
198 eol
= find(sol
, NULL
, '\r');
199 if(!eol
|| eol
== sol
)
201 sep
= find(sol
, eol
, '=');
204 if(compare(sol
, sep
, name
)) {
205 copy(output
, sep
+ 1, eol
, sizeof(output
));
217 #elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
218 /* TODO: implement */
226 debug_get_option(const char *name
, const char *dfault
)
230 result
= _debug_get_option(name
);
234 debug_printf("%s: %s = %s\n", __FUNCTION__
, name
, result
? result
: "(null)");
240 debug_get_bool_option(const char *name
, boolean dfault
)
242 const char *str
= _debug_get_option(name
);
247 else if(!util_strcmp(str
, "n"))
249 else if(!util_strcmp(str
, "no"))
251 else if(!util_strcmp(str
, "0"))
253 else if(!util_strcmp(str
, "f"))
255 else if(!util_strcmp(str
, "false"))
260 debug_printf("%s: %s = %s\n", __FUNCTION__
, name
, result
? "TRUE" : "FALSE");
267 debug_get_num_option(const char *name
, long dfault
)
272 str
= _debug_get_option(name
);
287 while('0' <= c
&& c
<= '9') {
288 result
= result
*10 + (c
- '0');
294 debug_printf("%s: %s = %li\n", __FUNCTION__
, name
, result
);
301 debug_get_flags_option(const char *name
,
302 const struct debug_named_value
*flags
,
303 unsigned long dfault
)
305 unsigned long result
;
308 str
= _debug_get_option(name
);
313 while( flags
->name
) {
314 if (!util_strcmp(str
, "all") || util_strstr(str
, flags
->name
))
315 result
|= flags
->value
;
320 debug_printf("%s: %s = 0x%lx\n", __FUNCTION__
, name
, result
);
326 void _debug_assert_fail(const char *expr
,
329 const char *function
)
331 _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file
, line
, function
, expr
);
332 #if defined(PIPE_OS_WINDOWS) && !defined(PIPE_SUBSYSTEM_WINDOWS_USER)
333 if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", FALSE
))
335 if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE
))
339 _debug_printf("continuing...\n");
344 debug_dump_enum(const struct debug_named_value
*names
,
347 static char rest
[64];
350 if(names
->value
== value
)
355 util_snprintf(rest
, sizeof(rest
), "0x%08lx", value
);
361 debug_dump_flags(const struct debug_named_value
*names
,
364 static char output
[4096];
365 static char rest
[256];
371 if((names
->value
& value
) == names
->value
) {
373 util_strncat(output
, "|", sizeof(output
));
376 util_strncat(output
, names
->name
, sizeof(output
));
377 value
&= ~names
->value
;
384 util_strncat(output
, "|", sizeof(output
));
388 util_snprintf(rest
, sizeof(rest
), "0x%08lx", value
);
389 util_strncat(output
, rest
, sizeof(output
));
399 static const struct debug_named_value pipe_format_names
[] = {
401 DEBUG_NAMED_VALUE(PIPE_FORMAT_NONE
),
402 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_UNORM
),
403 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_UNORM
),
404 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_UNORM
),
405 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_UNORM
),
406 DEBUG_NAMED_VALUE(PIPE_FORMAT_A1R5G5B5_UNORM
),
407 DEBUG_NAMED_VALUE(PIPE_FORMAT_A4R4G4B4_UNORM
),
408 DEBUG_NAMED_VALUE(PIPE_FORMAT_R5G6B5_UNORM
),
409 DEBUG_NAMED_VALUE(PIPE_FORMAT_A2B10G10R10_UNORM
),
410 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_UNORM
),
411 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_UNORM
),
412 DEBUG_NAMED_VALUE(PIPE_FORMAT_I8_UNORM
),
413 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_UNORM
),
414 DEBUG_NAMED_VALUE(PIPE_FORMAT_L16_UNORM
),
415 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR
),
416 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR_REV
),
417 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z16_UNORM
),
418 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_UNORM
),
419 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_FLOAT
),
420 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8Z24_UNORM
),
421 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24S8_UNORM
),
422 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8Z24_UNORM
),
423 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24X8_UNORM
),
424 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8_UNORM
),
425 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64_FLOAT
),
426 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64_FLOAT
),
427 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64_FLOAT
),
428 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64A64_FLOAT
),
429 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_FLOAT
),
430 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_FLOAT
),
431 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_FLOAT
),
432 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_FLOAT
),
433 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_UNORM
),
434 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_UNORM
),
435 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_UNORM
),
436 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_UNORM
),
437 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_USCALED
),
438 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_USCALED
),
439 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_USCALED
),
440 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_USCALED
),
441 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SNORM
),
442 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SNORM
),
443 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SNORM
),
444 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SNORM
),
445 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SSCALED
),
446 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SSCALED
),
447 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SSCALED
),
448 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SSCALED
),
449 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_UNORM
),
450 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_UNORM
),
451 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_UNORM
),
452 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_UNORM
),
453 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_USCALED
),
454 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_USCALED
),
455 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_USCALED
),
456 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_USCALED
),
457 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SNORM
),
458 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SNORM
),
459 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SNORM
),
460 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SNORM
),
461 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SSCALED
),
462 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SSCALED
),
463 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SSCALED
),
464 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SSCALED
),
465 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_UNORM
),
466 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_UNORM
),
467 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_UNORM
),
468 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_UNORM
),
469 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_UNORM
),
470 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_USCALED
),
471 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_USCALED
),
472 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_USCALED
),
473 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_USCALED
),
474 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_USCALED
),
475 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SNORM
),
476 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SNORM
),
477 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SNORM
),
478 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SNORM
),
479 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SNORM
),
480 DEBUG_NAMED_VALUE(PIPE_FORMAT_B6G5R5_SNORM
),
481 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8B8G8R8_SNORM
),
482 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8B8G8R8_SNORM
),
483 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SSCALED
),
484 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SSCALED
),
485 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SSCALED
),
486 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SSCALED
),
487 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SSCALED
),
488 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_SRGB
),
489 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_L8_SRGB
),
490 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SRGB
),
491 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SRGB
),
492 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SRGB
),
493 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8UB8UG8SR8S_NORM
),
494 DEBUG_NAMED_VALUE(PIPE_FORMAT_B6UG5SR5S_NORM
),
495 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGB
),
496 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGBA
),
497 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_RGBA
),
498 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_RGBA
),
500 DEBUG_NAMED_VALUE_END
504 void debug_print_format(const char *msg
, unsigned fmt
)
506 debug_printf("%s: %s\n", msg
, debug_dump_enum(pipe_format_names
, fmt
));
510 const char *pf_name( enum pipe_format format
)
512 return debug_dump_enum(pipe_format_names
, format
);
517 void debug_dump_image(const char *prefix
,
518 unsigned format
, unsigned cpp
,
519 unsigned width
, unsigned height
,
523 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
524 static unsigned no
= 0;
526 WCHAR wfilename
[sizeof(filename
)];
534 unsigned char *pMap
= NULL
;
537 util_snprintf(filename
, sizeof(filename
), "\\??\\c:\\%03u%s.raw", ++no
, prefix
);
538 for(i
= 0; i
< sizeof(filename
); ++i
)
539 wfilename
[i
] = (WCHAR
)filename
[i
];
541 pMap
= (unsigned char *)EngMapFile(wfilename
, sizeof(header
) + height
*width
*cpp
, &iFile
);
545 header
.format
= format
;
547 header
.width
= width
;
548 header
.height
= height
;
549 memcpy(pMap
, &header
, sizeof(header
));
550 pMap
+= sizeof(header
);
552 for(i
= 0; i
< height
; ++i
) {
553 memcpy(pMap
, (unsigned char *)data
+ stride
*i
, cpp
*width
);
561 void debug_dump_surface(const char *prefix
,
562 struct pipe_surface
*surface
)
564 unsigned surface_usage
;
570 /* XXX: force mappable surface */
571 surface_usage
= surface
->usage
;
572 surface
->usage
|= PIPE_BUFFER_USAGE_CPU_READ
;
574 data
= pipe_surface_map(surface
,
575 PIPE_BUFFER_USAGE_CPU_READ
);
579 debug_dump_image(prefix
,
587 pipe_surface_unmap(surface
);
589 surface
->usage
= surface_usage
;
596 struct bmp_file_header
{
599 uint16_t bfReserved1
;
600 uint16_t bfReserved2
;
605 struct bmp_info_header
{
611 uint32_t biCompression
;
612 uint32_t biSizeImage
;
613 int32_t biXPelsPerMeter
;
614 int32_t biYPelsPerMeter
;
616 uint32_t biClrImportant
;
619 struct bmp_rgb_quad
{
627 debug_dump_surface_bmp(const char *filename
,
628 struct pipe_surface
*surface
)
630 struct util_stream
*stream
;
631 unsigned surface_usage
;
632 struct bmp_file_header bmfh
;
633 struct bmp_info_header bmih
;
640 rgba
= MALLOC(surface
->width
*4*sizeof(float));
644 bmfh
.bfType
= 0x4d42;
645 bmfh
.bfSize
= 14 + 40 + surface
->height
*surface
->width
*4;
646 bmfh
.bfReserved1
= 0;
647 bmfh
.bfReserved2
= 0;
648 bmfh
.bfOffBits
= 14 + 40;
651 bmih
.biWidth
= surface
->width
;
652 bmih
.biHeight
= surface
->height
;
654 bmih
.biBitCount
= 32;
655 bmih
.biCompression
= 0;
656 bmih
.biSizeImage
= surface
->height
*surface
->width
*4;
657 bmih
.biXPelsPerMeter
= 0;
658 bmih
.biYPelsPerMeter
= 0;
660 bmih
.biClrImportant
= 0;
662 stream
= util_stream_create(filename
, bmfh
.bfSize
);
666 util_stream_write(stream
, &bmfh
, 14);
667 util_stream_write(stream
, &bmih
, 40);
669 /* XXX: force mappable surface */
670 surface_usage
= surface
->usage
;
671 surface
->usage
|= PIPE_BUFFER_USAGE_CPU_READ
;
675 pipe_get_tile_rgba(surface
,
676 0, y
, surface
->width
, 1,
678 for(x
= 0; x
< surface
->width
; ++x
)
680 struct bmp_rgb_quad pixel
;
681 pixel
.rgbRed
= float_to_ubyte(rgba
[x
*4 + 0]);
682 pixel
.rgbGreen
= float_to_ubyte(rgba
[x
*4 + 1]);
683 pixel
.rgbBlue
= float_to_ubyte(rgba
[x
*4 + 2]);
684 pixel
.rgbAlpha
= float_to_ubyte(rgba
[x
*4 + 3]);
685 util_stream_write(stream
, &pixel
, 4);
689 surface
->usage
= surface_usage
;
691 util_stream_close(stream
);