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