util: Reimplement all utility functions in terms of the new OS abstraction.
[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 "pipe/p_compiler.h"
33 #include "util/u_debug.h"
34 #include "pipe/p_format.h"
35 #include "pipe/p_state.h"
36 #include "util/u_inlines.h"
37 #include "util/u_format.h"
38 #include "util/u_memory.h"
39 #include "util/u_string.h"
40 #include "util/u_stream.h"
41 #include "util/u_math.h"
42 #include "util/u_tile.h"
43 #include "util/u_prim.h"
44
45
46 void _debug_vprintf(const char *format, va_list ap)
47 {
48 /* We buffer until we find a newline. */
49 static char buf[4096] = {'\0'};
50 size_t len = strlen(buf);
51 int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
52 if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
53 os_log_message(buf);
54 buf[0] = '\0';
55 }
56 }
57
58
59 #ifdef DEBUG
60 void debug_print_blob( const char *name,
61 const void *blob,
62 unsigned size )
63 {
64 const unsigned *ublob = (const unsigned *)blob;
65 unsigned i;
66
67 debug_printf("%s (%d dwords%s)\n", name, size/4,
68 size%4 ? "... plus a few bytes" : "");
69
70 for (i = 0; i < size/4; i++) {
71 debug_printf("%d:\t%08x\n", i, ublob[i]);
72 }
73 }
74 #endif
75
76
77 const char *
78 debug_get_option(const char *name, const char *dfault)
79 {
80 const char *result;
81
82 result = os_get_option(name);
83 if(!result)
84 result = dfault;
85
86 debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
87
88 return result;
89 }
90
91 boolean
92 debug_get_bool_option(const char *name, boolean dfault)
93 {
94 const char *str = os_get_option(name);
95 boolean result;
96
97 if(str == NULL)
98 result = dfault;
99 else if(!util_strcmp(str, "n"))
100 result = FALSE;
101 else if(!util_strcmp(str, "no"))
102 result = FALSE;
103 else if(!util_strcmp(str, "0"))
104 result = FALSE;
105 else if(!util_strcmp(str, "f"))
106 result = FALSE;
107 else if(!util_strcmp(str, "false"))
108 result = FALSE;
109 else
110 result = TRUE;
111
112 debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
113
114 return result;
115 }
116
117
118 long
119 debug_get_num_option(const char *name, long dfault)
120 {
121 long result;
122 const char *str;
123
124 str = os_get_option(name);
125 if(!str)
126 result = dfault;
127 else {
128 long sign;
129 char c;
130 c = *str++;
131 if(c == '-') {
132 sign = -1;
133 c = *str++;
134 }
135 else {
136 sign = 1;
137 }
138 result = 0;
139 while('0' <= c && c <= '9') {
140 result = result*10 + (c - '0');
141 c = *str++;
142 }
143 result *= sign;
144 }
145
146 debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
147
148 return result;
149 }
150
151
152 unsigned long
153 debug_get_flags_option(const char *name,
154 const struct debug_named_value *flags,
155 unsigned long dfault)
156 {
157 unsigned long result;
158 const char *str;
159
160 str = os_get_option(name);
161 if(!str)
162 result = dfault;
163 else if (!util_strcmp(str, "help")) {
164 result = dfault;
165 while (flags->name) {
166 debug_printf("%s: help for %s: %s [0x%lx]\n", __FUNCTION__, name, flags->name, flags->value);
167 flags++;
168 }
169 }
170 else {
171 result = 0;
172 while( flags->name ) {
173 if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
174 result |= flags->value;
175 ++flags;
176 }
177 }
178
179 if (str) {
180 debug_printf("%s: %s = 0x%lx (%s)\n", __FUNCTION__, name, result, str);
181 }
182 else {
183 debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
184 }
185
186 return result;
187 }
188
189
190 void _debug_assert_fail(const char *expr,
191 const char *file,
192 unsigned line,
193 const char *function)
194 {
195 _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
196 #if defined(PIPE_OS_WINDOWS) && !defined(PIPE_SUBSYSTEM_WINDOWS_USER)
197 if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", FALSE))
198 #else
199 if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
200 #endif
201 os_abort();
202 else
203 _debug_printf("continuing...\n");
204 }
205
206
207 const char *
208 debug_dump_enum(const struct debug_named_value *names,
209 unsigned long value)
210 {
211 static char rest[64];
212
213 while(names->name) {
214 if(names->value == value)
215 return names->name;
216 ++names;
217 }
218
219 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
220 return rest;
221 }
222
223
224 const char *
225 debug_dump_enum_noprefix(const struct debug_named_value *names,
226 const char *prefix,
227 unsigned long value)
228 {
229 static char rest[64];
230
231 while(names->name) {
232 if(names->value == value) {
233 const char *name = names->name;
234 while (*name == *prefix) {
235 name++;
236 prefix++;
237 }
238 return name;
239 }
240 ++names;
241 }
242
243
244
245 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
246 return rest;
247 }
248
249
250 const char *
251 debug_dump_flags(const struct debug_named_value *names,
252 unsigned long value)
253 {
254 static char output[4096];
255 static char rest[256];
256 int first = 1;
257
258 output[0] = '\0';
259
260 while(names->name) {
261 if((names->value & value) == names->value) {
262 if (!first)
263 util_strncat(output, "|", sizeof(output));
264 else
265 first = 0;
266 util_strncat(output, names->name, sizeof(output) - 1);
267 output[sizeof(output) - 1] = '\0';
268 value &= ~names->value;
269 }
270 ++names;
271 }
272
273 if (value) {
274 if (!first)
275 util_strncat(output, "|", sizeof(output));
276 else
277 first = 0;
278
279 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
280 util_strncat(output, rest, sizeof(output) - 1);
281 output[sizeof(output) - 1] = '\0';
282 }
283
284 if(first)
285 return "0";
286
287 return output;
288 }
289
290
291 static const struct debug_named_value pipe_format_names[] = {
292 #ifdef DEBUG
293 DEBUG_NAMED_VALUE(PIPE_FORMAT_NONE),
294 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_UNORM),
295 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_UNORM),
296 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_UNORM),
297 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_UNORM),
298 DEBUG_NAMED_VALUE(PIPE_FORMAT_A1R5G5B5_UNORM),
299 DEBUG_NAMED_VALUE(PIPE_FORMAT_A4R4G4B4_UNORM),
300 DEBUG_NAMED_VALUE(PIPE_FORMAT_R5G6B5_UNORM),
301 DEBUG_NAMED_VALUE(PIPE_FORMAT_A2B10G10R10_UNORM),
302 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_UNORM),
303 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_UNORM),
304 DEBUG_NAMED_VALUE(PIPE_FORMAT_I8_UNORM),
305 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_UNORM),
306 DEBUG_NAMED_VALUE(PIPE_FORMAT_L16_UNORM),
307 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR),
308 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR_REV),
309 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z16_UNORM),
310 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_UNORM),
311 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_FLOAT),
312 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8Z24_UNORM),
313 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24S8_UNORM),
314 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8Z24_UNORM),
315 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24X8_UNORM),
316 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8_UNORM),
317 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64_FLOAT),
318 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64_FLOAT),
319 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64_FLOAT),
320 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64A64_FLOAT),
321 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_FLOAT),
322 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_FLOAT),
323 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_FLOAT),
324 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_FLOAT),
325 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_UNORM),
326 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_UNORM),
327 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_UNORM),
328 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_UNORM),
329 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_USCALED),
330 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_USCALED),
331 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_USCALED),
332 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_USCALED),
333 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SNORM),
334 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SNORM),
335 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SNORM),
336 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SNORM),
337 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SSCALED),
338 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SSCALED),
339 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SSCALED),
340 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SSCALED),
341 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_UNORM),
342 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_UNORM),
343 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_UNORM),
344 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_UNORM),
345 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_USCALED),
346 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_USCALED),
347 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_USCALED),
348 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_USCALED),
349 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SNORM),
350 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SNORM),
351 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SNORM),
352 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SNORM),
353 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SSCALED),
354 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SSCALED),
355 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SSCALED),
356 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SSCALED),
357 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_UNORM),
358 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_UNORM),
359 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_UNORM),
360 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_UNORM),
361 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_UNORM),
362 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_USCALED),
363 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_USCALED),
364 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_USCALED),
365 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_USCALED),
366 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_USCALED),
367 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SNORM),
368 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SNORM),
369 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SNORM),
370 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SNORM),
371 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SNORM),
372 DEBUG_NAMED_VALUE(PIPE_FORMAT_B6G5R5_SNORM),
373 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8B8G8R8_SNORM),
374 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8B8G8R8_SNORM),
375 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SSCALED),
376 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SSCALED),
377 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SSCALED),
378 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SSCALED),
379 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SSCALED),
380 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_SRGB),
381 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_SRGB),
382 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SRGB),
383 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SRGB),
384 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SRGB),
385 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_SRGB),
386 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_SRGB),
387 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_SRGB),
388 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_SRGB),
389 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8UB8UG8SR8S_NORM),
390 DEBUG_NAMED_VALUE(PIPE_FORMAT_B6UG5SR5S_NORM),
391 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGB),
392 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGBA),
393 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_RGBA),
394 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_RGBA),
395 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_SRGB),
396 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_SRGBA),
397 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_SRGBA),
398 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_SRGBA),
399 #endif
400 DEBUG_NAMED_VALUE_END
401 };
402
403 #ifdef DEBUG
404 void debug_print_format(const char *msg, unsigned fmt )
405 {
406 debug_printf("%s: %s\n", msg, debug_dump_enum(pipe_format_names, fmt));
407 }
408 #endif
409
410 const char *pf_name( enum pipe_format format )
411 {
412 return debug_dump_enum(pipe_format_names, format);
413 }
414
415
416
417 static const struct debug_named_value pipe_prim_names[] = {
418 #ifdef DEBUG
419 DEBUG_NAMED_VALUE(PIPE_PRIM_POINTS),
420 DEBUG_NAMED_VALUE(PIPE_PRIM_LINES),
421 DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_LOOP),
422 DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP),
423 DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES),
424 DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP),
425 DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_FAN),
426 DEBUG_NAMED_VALUE(PIPE_PRIM_QUADS),
427 DEBUG_NAMED_VALUE(PIPE_PRIM_QUAD_STRIP),
428 DEBUG_NAMED_VALUE(PIPE_PRIM_POLYGON),
429 #endif
430 DEBUG_NAMED_VALUE_END
431 };
432
433
434 const char *u_prim_name( unsigned prim )
435 {
436 return debug_dump_enum(pipe_prim_names, prim);
437 }
438
439
440
441
442 #ifdef DEBUG
443 void debug_dump_image(const char *prefix,
444 unsigned format, unsigned cpp,
445 unsigned width, unsigned height,
446 unsigned stride,
447 const void *data)
448 {
449 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
450 static unsigned no = 0;
451 char filename[256];
452 WCHAR wfilename[sizeof(filename)];
453 ULONG_PTR iFile = 0;
454 struct {
455 unsigned format;
456 unsigned cpp;
457 unsigned width;
458 unsigned height;
459 } header;
460 unsigned char *pMap = NULL;
461 unsigned i;
462
463 util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix);
464 for(i = 0; i < sizeof(filename); ++i)
465 wfilename[i] = (WCHAR)filename[i];
466
467 pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + height*width*cpp, &iFile);
468 if(!pMap)
469 return;
470
471 header.format = format;
472 header.cpp = cpp;
473 header.width = width;
474 header.height = height;
475 memcpy(pMap, &header, sizeof(header));
476 pMap += sizeof(header);
477
478 for(i = 0; i < height; ++i) {
479 memcpy(pMap, (unsigned char *)data + stride*i, cpp*width);
480 pMap += cpp*width;
481 }
482
483 EngUnmapFile(iFile);
484 #endif
485 }
486
487 void debug_dump_surface(const char *prefix,
488 struct pipe_surface *surface)
489 {
490 struct pipe_texture *texture;
491 struct pipe_screen *screen;
492 struct pipe_transfer *transfer;
493 void *data;
494
495 if (!surface)
496 return;
497
498 texture = surface->texture;
499 screen = texture->screen;
500
501 transfer = screen->get_tex_transfer(screen, texture, surface->face,
502 surface->level, surface->zslice,
503 PIPE_TRANSFER_READ, 0, 0, surface->width,
504 surface->height);
505
506 data = screen->transfer_map(screen, transfer);
507 if(!data)
508 goto error;
509
510 debug_dump_image(prefix,
511 texture->format,
512 util_format_get_blocksize(texture->format),
513 util_format_get_nblocksx(texture->format, transfer->width),
514 util_format_get_nblocksy(texture->format, transfer->height),
515 transfer->stride,
516 data);
517
518 screen->transfer_unmap(screen, transfer);
519 error:
520 screen->tex_transfer_destroy(transfer);
521 }
522
523
524 #pragma pack(push,2)
525 struct bmp_file_header {
526 uint16_t bfType;
527 uint32_t bfSize;
528 uint16_t bfReserved1;
529 uint16_t bfReserved2;
530 uint32_t bfOffBits;
531 };
532 #pragma pack(pop)
533
534 struct bmp_info_header {
535 uint32_t biSize;
536 int32_t biWidth;
537 int32_t biHeight;
538 uint16_t biPlanes;
539 uint16_t biBitCount;
540 uint32_t biCompression;
541 uint32_t biSizeImage;
542 int32_t biXPelsPerMeter;
543 int32_t biYPelsPerMeter;
544 uint32_t biClrUsed;
545 uint32_t biClrImportant;
546 };
547
548 struct bmp_rgb_quad {
549 uint8_t rgbBlue;
550 uint8_t rgbGreen;
551 uint8_t rgbRed;
552 uint8_t rgbAlpha;
553 };
554
555 void
556 debug_dump_surface_bmp(const char *filename,
557 struct pipe_surface *surface)
558 {
559 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
560 struct pipe_transfer *transfer;
561 struct pipe_texture *texture = surface->texture;
562 struct pipe_screen *screen = texture->screen;
563
564 transfer = screen->get_tex_transfer(screen, texture, surface->face,
565 surface->level, surface->zslice,
566 PIPE_TRANSFER_READ, 0, 0, surface->width,
567 surface->height);
568
569 debug_dump_transfer_bmp(filename, transfer);
570
571 screen->tex_transfer_destroy(transfer);
572 #endif
573 }
574
575 void
576 debug_dump_transfer_bmp(const char *filename,
577 struct pipe_transfer *transfer)
578 {
579 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
580 float *rgba;
581
582 if (!transfer)
583 goto error1;
584
585 rgba = MALLOC(transfer->width*transfer->height*4*sizeof(float));
586 if(!rgba)
587 goto error1;
588
589 pipe_get_tile_rgba(transfer, 0, 0,
590 transfer->width, transfer->height,
591 rgba);
592
593 debug_dump_float_rgba_bmp(filename,
594 transfer->width, transfer->height,
595 rgba, transfer->width);
596
597 FREE(rgba);
598 error1:
599 ;
600 #endif
601 }
602
603 void
604 debug_dump_float_rgba_bmp(const char *filename,
605 unsigned width, unsigned height,
606 float *rgba, unsigned stride)
607 {
608 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
609 struct util_stream *stream;
610 struct bmp_file_header bmfh;
611 struct bmp_info_header bmih;
612 unsigned x, y;
613
614 if(!rgba)
615 goto error1;
616
617 bmfh.bfType = 0x4d42;
618 bmfh.bfSize = 14 + 40 + height*width*4;
619 bmfh.bfReserved1 = 0;
620 bmfh.bfReserved2 = 0;
621 bmfh.bfOffBits = 14 + 40;
622
623 bmih.biSize = 40;
624 bmih.biWidth = width;
625 bmih.biHeight = height;
626 bmih.biPlanes = 1;
627 bmih.biBitCount = 32;
628 bmih.biCompression = 0;
629 bmih.biSizeImage = height*width*4;
630 bmih.biXPelsPerMeter = 0;
631 bmih.biYPelsPerMeter = 0;
632 bmih.biClrUsed = 0;
633 bmih.biClrImportant = 0;
634
635 stream = util_stream_create(filename, bmfh.bfSize);
636 if(!stream)
637 goto error1;
638
639 util_stream_write(stream, &bmfh, 14);
640 util_stream_write(stream, &bmih, 40);
641
642 y = height;
643 while(y--) {
644 float *ptr = rgba + (stride * y * 4);
645 for(x = 0; x < width; ++x)
646 {
647 struct bmp_rgb_quad pixel;
648 pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);
649 pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
650 pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
651 pixel.rgbAlpha = 255;
652 util_stream_write(stream, &pixel, 4);
653 }
654 }
655
656 util_stream_close(stream);
657 error1:
658 ;
659 #endif
660 }
661
662 #endif