00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "pipe/p_config.h"
00030
00031 #include <stdarg.h>
00032
00033
00034 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
00035
00036 #include <windows.h>
00037 #include <winddi.h>
00038
00039 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
00040
00041 #ifndef WIN32_LEAN_AND_MEAN
00042 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
00043 #endif
00044 #include <windows.h>
00045 #include <stdio.h>
00046
00047 #else
00048
00049 #include <stdio.h>
00050 #include <stdlib.h>
00051
00052 #endif
00053
00054
00055 #include "pipe/p_compiler.h"
00056 #include "pipe/p_debug.h"
00057 #include "pipe/p_format.h"
00058 #include "pipe/p_state.h"
00059 #include "pipe/p_inlines.h"
00060 #include "util/u_memory.h"
00061 #include "util/u_string.h"
00062 #include "util/u_stream.h"
00063 #include "util/u_math.h"
00064 #include "util/u_tile.h"
00065
00066
00067 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
00068 static INLINE void
00069 _EngDebugPrint(const char *format, ...)
00070 {
00071 va_list ap;
00072 va_start(ap, format);
00073 EngDebugPrint("", (PCHAR)format, ap);
00074 va_end(ap);
00075 }
00076 #endif
00077
00078
00079 void _debug_vprintf(const char *format, va_list ap)
00080 {
00081 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
00082
00083
00084
00085 static char buf[512] = {'\0'};
00086 size_t len = strlen(buf);
00087 int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
00088 if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
00089 _EngDebugPrint("%s", buf);
00090 buf[0] = '\0';
00091 }
00092 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
00093
00094
00095
00096 static char buf[512 + 1] = {'\0'};
00097 size_t len = strlen(buf);
00098 int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
00099 if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
00100 OutputDebugStringA(buf);
00101 buf[0] = '\0';
00102 }
00103
00104
00105 if(GetConsoleWindow() && !IsDebuggerPresent()) {
00106 fflush(stdout);
00107 vfprintf(stderr, format, ap);
00108 fflush(stderr);
00109 }
00110
00111
00112 #elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
00113
00114 #else
00115 #ifdef DEBUG
00116 vfprintf(stderr, format, ap);
00117 #endif
00118 #endif
00119 }
00120
00121
00122 #ifdef DEBUG
00123 void debug_print_blob( const char *name,
00124 const void *blob,
00125 unsigned size )
00126 {
00127 const unsigned *ublob = (const unsigned *)blob;
00128 unsigned i;
00129
00130 debug_printf("%s (%d dwords%s)\n", name, size/4,
00131 size%4 ? "... plus a few bytes" : "");
00132
00133 for (i = 0; i < size/4; i++) {
00134 debug_printf("%d:\t%08x\n", i, ublob[i]);
00135 }
00136 }
00137 #endif
00138
00139
00140 void _debug_break(void)
00141 {
00142 #if defined(PIPE_ARCH_X86) && defined(PIPE_CC_GCC)
00143 __asm("int3");
00144 #elif defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)
00145 _asm {int 3};
00146 #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
00147 EngDebugBreak();
00148 #else
00149 abort();
00150 #endif
00151 }
00152
00153
00154 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
00155 static const char *
00156 find(const char *start, const char *end, char c)
00157 {
00158 const char *p;
00159 for(p = start; !end || p != end; ++p) {
00160 if(*p == c)
00161 return p;
00162 if(*p < 32)
00163 break;
00164 }
00165 return NULL;
00166 }
00167
00168 static int
00169 compare(const char *start, const char *end, const char *s)
00170 {
00171 const char *p, *q;
00172 for(p = start, q = s; p != end && *q != '\0'; ++p, ++q) {
00173 if(*p != *q)
00174 return 0;
00175 }
00176 return p == end && *q == '\0';
00177 }
00178
00179 static void
00180 copy(char *dst, const char *start, const char *end, size_t n)
00181 {
00182 const char *p;
00183 char *q;
00184 for(p = start, q = dst, n = n - 1; p != end && n; ++p, ++q, --n)
00185 *q = *p;
00186 *q = '\0';
00187 }
00188 #endif
00189
00190
00191 static INLINE const char *
00192 _debug_get_option(const char *name)
00193 {
00194 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
00195
00196
00197 #ifdef DEBUG
00198 const char *result = NULL;
00199 ULONG_PTR iFile = 0;
00200 const void *pMap = NULL;
00201 const char *sol, *eol, *sep;
00202 static char output[1024];
00203
00204 pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile);
00205 if(pMap) {
00206 sol = (const char *)pMap;
00207 while(1) {
00208
00209 eol = find(sol, NULL, '\r');
00210 if(!eol || eol == sol)
00211 break;
00212 sep = find(sol, eol, '=');
00213 if(!sep)
00214 break;
00215 if(compare(sol, sep, name)) {
00216 copy(output, sep + 1, eol, sizeof(output));
00217 result = output;
00218 break;
00219 }
00220 sol = eol + 2;
00221 }
00222 EngUnmapFile(iFile);
00223 }
00224 return result;
00225 #else
00226 return NULL;
00227 #endif
00228 #elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
00229
00230 return NULL;
00231 #else
00232 return getenv(name);
00233 #endif
00234 }
00235
00236 const char *
00237 debug_get_option(const char *name, const char *dfault)
00238 {
00239 const char *result;
00240
00241 result = _debug_get_option(name);
00242 if(!result)
00243 result = dfault;
00244
00245 debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
00246
00247 return result;
00248 }
00249
00250 boolean
00251 debug_get_bool_option(const char *name, boolean dfault)
00252 {
00253 const char *str = _debug_get_option(name);
00254 boolean result;
00255
00256 if(str == NULL)
00257 result = dfault;
00258 else if(!util_strcmp(str, "n"))
00259 result = FALSE;
00260 else if(!util_strcmp(str, "no"))
00261 result = FALSE;
00262 else if(!util_strcmp(str, "0"))
00263 result = FALSE;
00264 else if(!util_strcmp(str, "f"))
00265 result = FALSE;
00266 else if(!util_strcmp(str, "false"))
00267 result = FALSE;
00268 else
00269 result = TRUE;
00270
00271 debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
00272
00273 return result;
00274 }
00275
00276
00277 long
00278 debug_get_num_option(const char *name, long dfault)
00279 {
00280 long result;
00281 const char *str;
00282
00283 str = _debug_get_option(name);
00284 if(!str)
00285 result = dfault;
00286 else {
00287 long sign;
00288 char c;
00289 c = *str++;
00290 if(c == '-') {
00291 sign = -1;
00292 c = *str++;
00293 }
00294 else {
00295 sign = 1;
00296 }
00297 result = 0;
00298 while('0' <= c && c <= '9') {
00299 result = result*10 + (c - '0');
00300 c = *str++;
00301 }
00302 result *= sign;
00303 }
00304
00305 debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
00306
00307 return result;
00308 }
00309
00310
00311 unsigned long
00312 debug_get_flags_option(const char *name,
00313 const struct debug_named_value *flags,
00314 unsigned long dfault)
00315 {
00316 unsigned long result;
00317 const char *str;
00318
00319 str = _debug_get_option(name);
00320 if(!str)
00321 result = dfault;
00322 else {
00323 result = 0;
00324 while( flags->name ) {
00325 if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
00326 result |= flags->value;
00327 ++flags;
00328 }
00329 }
00330
00331 debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
00332
00333 return result;
00334 }
00335
00336
00337 void _debug_assert_fail(const char *expr,
00338 const char *file,
00339 unsigned line,
00340 const char *function)
00341 {
00342 _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
00343 #if defined(PIPE_OS_WINDOWS) && !defined(PIPE_SUBSYSTEM_WINDOWS_USER)
00344 if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", FALSE))
00345 #else
00346 if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
00347 #endif
00348 debug_break();
00349 else
00350 _debug_printf("continuing...\n");
00351 }
00352
00353
00354 const char *
00355 debug_dump_enum(const struct debug_named_value *names,
00356 unsigned long value)
00357 {
00358 static char rest[64];
00359
00360 while(names->name) {
00361 if(names->value == value)
00362 return names->name;
00363 ++names;
00364 }
00365
00366 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
00367 return rest;
00368 }
00369
00370
00371 const char *
00372 debug_dump_flags(const struct debug_named_value *names,
00373 unsigned long value)
00374 {
00375 static char output[4096];
00376 static char rest[256];
00377 int first = 1;
00378
00379 output[0] = '\0';
00380
00381 while(names->name) {
00382 if((names->value & value) == names->value) {
00383 if (!first)
00384 util_strncat(output, "|", sizeof(output));
00385 else
00386 first = 0;
00387 util_strncat(output, names->name, sizeof(output));
00388 value &= ~names->value;
00389 }
00390 ++names;
00391 }
00392
00393 if (value) {
00394 if (!first)
00395 util_strncat(output, "|", sizeof(output));
00396 else
00397 first = 0;
00398
00399 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
00400 util_strncat(output, rest, sizeof(output));
00401 }
00402
00403 if(first)
00404 return "0";
00405
00406 return output;
00407 }
00408
00409
00410 static const struct debug_named_value pipe_format_names[] = {
00411 #ifdef DEBUG
00412 DEBUG_NAMED_VALUE(PIPE_FORMAT_NONE),
00413 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_UNORM),
00414 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_UNORM),
00415 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_UNORM),
00416 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_UNORM),
00417 DEBUG_NAMED_VALUE(PIPE_FORMAT_A1R5G5B5_UNORM),
00418 DEBUG_NAMED_VALUE(PIPE_FORMAT_A4R4G4B4_UNORM),
00419 DEBUG_NAMED_VALUE(PIPE_FORMAT_R5G6B5_UNORM),
00420 DEBUG_NAMED_VALUE(PIPE_FORMAT_A2B10G10R10_UNORM),
00421 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_UNORM),
00422 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_UNORM),
00423 DEBUG_NAMED_VALUE(PIPE_FORMAT_I8_UNORM),
00424 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_UNORM),
00425 DEBUG_NAMED_VALUE(PIPE_FORMAT_L16_UNORM),
00426 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR),
00427 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR_REV),
00428 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z16_UNORM),
00429 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_UNORM),
00430 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_FLOAT),
00431 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8Z24_UNORM),
00432 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24S8_UNORM),
00433 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8Z24_UNORM),
00434 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24X8_UNORM),
00435 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8_UNORM),
00436 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64_FLOAT),
00437 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64_FLOAT),
00438 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64_FLOAT),
00439 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64A64_FLOAT),
00440 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_FLOAT),
00441 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_FLOAT),
00442 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_FLOAT),
00443 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_FLOAT),
00444 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_UNORM),
00445 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_UNORM),
00446 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_UNORM),
00447 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_UNORM),
00448 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_USCALED),
00449 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_USCALED),
00450 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_USCALED),
00451 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_USCALED),
00452 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SNORM),
00453 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SNORM),
00454 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SNORM),
00455 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SNORM),
00456 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SSCALED),
00457 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SSCALED),
00458 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SSCALED),
00459 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SSCALED),
00460 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_UNORM),
00461 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_UNORM),
00462 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_UNORM),
00463 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_UNORM),
00464 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_USCALED),
00465 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_USCALED),
00466 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_USCALED),
00467 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_USCALED),
00468 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SNORM),
00469 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SNORM),
00470 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SNORM),
00471 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SNORM),
00472 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SSCALED),
00473 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SSCALED),
00474 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SSCALED),
00475 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SSCALED),
00476 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_UNORM),
00477 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_UNORM),
00478 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_UNORM),
00479 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_UNORM),
00480 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_UNORM),
00481 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_USCALED),
00482 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_USCALED),
00483 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_USCALED),
00484 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_USCALED),
00485 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_USCALED),
00486 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SNORM),
00487 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SNORM),
00488 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SNORM),
00489 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SNORM),
00490 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SNORM),
00491 DEBUG_NAMED_VALUE(PIPE_FORMAT_B6G5R5_SNORM),
00492 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8B8G8R8_SNORM),
00493 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8B8G8R8_SNORM),
00494 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SSCALED),
00495 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SSCALED),
00496 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SSCALED),
00497 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SSCALED),
00498 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SSCALED),
00499 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_SRGB),
00500 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_L8_SRGB),
00501 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SRGB),
00502 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SRGB),
00503 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SRGB),
00504 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8UB8UG8SR8S_NORM),
00505 DEBUG_NAMED_VALUE(PIPE_FORMAT_B6UG5SR5S_NORM),
00506 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGB),
00507 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGBA),
00508 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_RGBA),
00509 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_RGBA),
00510 #endif
00511 DEBUG_NAMED_VALUE_END
00512 };
00513
00514 #ifdef DEBUG
00515 void debug_print_format(const char *msg, unsigned fmt )
00516 {
00517 debug_printf("%s: %s\n", msg, debug_dump_enum(pipe_format_names, fmt));
00518 }
00519 #endif
00520
00521 const char *pf_name( enum pipe_format format )
00522 {
00523 return debug_dump_enum(pipe_format_names, format);
00524 }
00525
00526
00527 #ifdef DEBUG
00528 void debug_dump_image(const char *prefix,
00529 unsigned format, unsigned cpp,
00530 unsigned width, unsigned height,
00531 unsigned stride,
00532 const void *data)
00533 {
00534 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
00535 static unsigned no = 0;
00536 char filename[256];
00537 WCHAR wfilename[sizeof(filename)];
00538 ULONG_PTR iFile = 0;
00539 struct {
00540 unsigned format;
00541 unsigned cpp;
00542 unsigned width;
00543 unsigned height;
00544 } header;
00545 unsigned char *pMap = NULL;
00546 unsigned i;
00547
00548 util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix);
00549 for(i = 0; i < sizeof(filename); ++i)
00550 wfilename[i] = (WCHAR)filename[i];
00551
00552 pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + height*width*cpp, &iFile);
00553 if(!pMap)
00554 return;
00555
00556 header.format = format;
00557 header.cpp = cpp;
00558 header.width = width;
00559 header.height = height;
00560 memcpy(pMap, &header, sizeof(header));
00561 pMap += sizeof(header);
00562
00563 for(i = 0; i < height; ++i) {
00564 memcpy(pMap, (unsigned char *)data + stride*i, cpp*width);
00565 pMap += cpp*width;
00566 }
00567
00568 EngUnmapFile(iFile);
00569 #endif
00570 }
00571
00572 void debug_dump_surface(const char *prefix,
00573 struct pipe_surface *surface)
00574 {
00575 unsigned surface_usage;
00576 void *data;
00577
00578 if (!surface)
00579 goto error1;
00580
00581
00582 surface_usage = surface->usage;
00583 surface->usage |= PIPE_BUFFER_USAGE_CPU_READ;
00584
00585 data = pipe_surface_map(surface,
00586 PIPE_BUFFER_USAGE_CPU_READ);
00587 if(!data)
00588 goto error2;
00589
00590 debug_dump_image(prefix,
00591 surface->format,
00592 surface->block.size,
00593 surface->nblocksx,
00594 surface->nblocksy,
00595 surface->stride,
00596 data);
00597
00598 pipe_surface_unmap(surface);
00599 error2:
00600 surface->usage = surface_usage;
00601 error1:
00602 ;
00603 }
00604
00605
00606 #pragma pack(push,2)
00607 struct bmp_file_header {
00608 uint16_t bfType;
00609 uint32_t bfSize;
00610 uint16_t bfReserved1;
00611 uint16_t bfReserved2;
00612 uint32_t bfOffBits;
00613 };
00614 #pragma pack(pop)
00615
00616 struct bmp_info_header {
00617 uint32_t biSize;
00618 int32_t biWidth;
00619 int32_t biHeight;
00620 uint16_t biPlanes;
00621 uint16_t biBitCount;
00622 uint32_t biCompression;
00623 uint32_t biSizeImage;
00624 int32_t biXPelsPerMeter;
00625 int32_t biYPelsPerMeter;
00626 uint32_t biClrUsed;
00627 uint32_t biClrImportant;
00628 };
00629
00630 struct bmp_rgb_quad {
00631 uint8_t rgbBlue;
00632 uint8_t rgbGreen;
00633 uint8_t rgbRed;
00634 uint8_t rgbAlpha;
00635 };
00636
00637 void
00638 debug_dump_surface_bmp(const char *filename,
00639 struct pipe_surface *surface)
00640 {
00641 struct util_stream *stream;
00642 unsigned surface_usage;
00643 struct bmp_file_header bmfh;
00644 struct bmp_info_header bmih;
00645 float *rgba;
00646 unsigned x, y;
00647
00648 if (!surface)
00649 goto error1;
00650
00651 rgba = MALLOC(surface->width*4*sizeof(float));
00652 if(!rgba)
00653 goto error1;
00654
00655 bmfh.bfType = 0x4d42;
00656 bmfh.bfSize = 14 + 40 + surface->height*surface->width*4;
00657 bmfh.bfReserved1 = 0;
00658 bmfh.bfReserved2 = 0;
00659 bmfh.bfOffBits = 14 + 40;
00660
00661 bmih.biSize = 40;
00662 bmih.biWidth = surface->width;
00663 bmih.biHeight = surface->height;
00664 bmih.biPlanes = 1;
00665 bmih.biBitCount = 32;
00666 bmih.biCompression = 0;
00667 bmih.biSizeImage = surface->height*surface->width*4;
00668 bmih.biXPelsPerMeter = 0;
00669 bmih.biYPelsPerMeter = 0;
00670 bmih.biClrUsed = 0;
00671 bmih.biClrImportant = 0;
00672
00673 stream = util_stream_create(filename, bmfh.bfSize);
00674 if(!stream)
00675 goto error2;
00676
00677 util_stream_write(stream, &bmfh, 14);
00678 util_stream_write(stream, &bmih, 40);
00679
00680
00681 surface_usage = surface->usage;
00682 surface->usage |= PIPE_BUFFER_USAGE_CPU_READ;
00683
00684 y = surface->height;
00685 while(y--) {
00686 pipe_get_tile_rgba(surface,
00687 0, y, surface->width, 1,
00688 rgba);
00689 for(x = 0; x < surface->width; ++x)
00690 {
00691 struct bmp_rgb_quad pixel;
00692 pixel.rgbRed = float_to_ubyte(rgba[x*4 + 0]);
00693 pixel.rgbGreen = float_to_ubyte(rgba[x*4 + 1]);
00694 pixel.rgbBlue = float_to_ubyte(rgba[x*4 + 2]);
00695 pixel.rgbAlpha = float_to_ubyte(rgba[x*4 + 3]);
00696 util_stream_write(stream, &pixel, 4);
00697 }
00698 }
00699
00700 surface->usage = surface_usage;
00701
00702 util_stream_close(stream);
00703 error2:
00704 FREE(rgba);
00705 error1:
00706 ;
00707 }
00708
00709 #endif