Merge branch 'gallium-nopointsizeminmax'
[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 "os/os_stream.h"
34 #include "util/u_debug.h"
35 #include "pipe/p_format.h"
36 #include "pipe/p_state.h"
37 #include "util/u_inlines.h"
38 #include "util/u_format.h"
39 #include "util/u_memory.h"
40 #include "util/u_string.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 /**
444 * Dump an image to a .raw or .ppm file (depends on OS).
445 * \param format PIPE_FORMAT_x
446 * \param cpp bytes per pixel
447 * \param width width in pixels
448 * \param height height in pixels
449 * \param stride row stride in bytes
450 */
451 void debug_dump_image(const char *prefix,
452 unsigned format, unsigned cpp,
453 unsigned width, unsigned height,
454 unsigned stride,
455 const void *data)
456 {
457 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
458 static unsigned no = 0;
459 char filename[256];
460 WCHAR wfilename[sizeof(filename)];
461 ULONG_PTR iFile = 0;
462 struct {
463 unsigned format;
464 unsigned cpp;
465 unsigned width;
466 unsigned height;
467 } header;
468 unsigned char *pMap = NULL;
469 unsigned i;
470
471 util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix);
472 for(i = 0; i < sizeof(filename); ++i)
473 wfilename[i] = (WCHAR)filename[i];
474
475 pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + height*width*cpp, &iFile);
476 if(!pMap)
477 return;
478
479 header.format = format;
480 header.cpp = cpp;
481 header.width = width;
482 header.height = height;
483 memcpy(pMap, &header, sizeof(header));
484 pMap += sizeof(header);
485
486 for(i = 0; i < height; ++i) {
487 memcpy(pMap, (unsigned char *)data + stride*i, cpp*width);
488 pMap += cpp*width;
489 }
490
491 EngUnmapFile(iFile);
492 #elif defined(PIPE_OS_UNIX)
493 /* write a ppm file */
494 char filename[256];
495 FILE *f;
496
497 util_snprintf(filename, sizeof(filename), "%s.ppm", prefix);
498
499 f = fopen(filename, "w");
500 if (f) {
501 int i, x, y;
502 int r, g, b;
503 const uint8_t *ptr = (uint8_t *) data;
504
505 /* XXX this is a hack */
506 switch (format) {
507 case PIPE_FORMAT_A8R8G8B8_UNORM:
508 r = 2;
509 g = 1;
510 b = 0;
511 break;
512 default:
513 r = 0;
514 g = 1;
515 b = 1;
516 }
517
518 fprintf(f, "P6\n");
519 fprintf(f, "# ppm-file created by osdemo.c\n");
520 fprintf(f, "%i %i\n", width, height);
521 fprintf(f, "255\n");
522 fclose(f);
523
524 f = fopen(filename, "ab"); /* reopen in binary append mode */
525 for (y = 0; y < height; y++) {
526 for (x = 0; x < width; x++) {
527 i = y * stride + x * cpp;
528 fputc(ptr[i + r], f); /* write red */
529 fputc(ptr[i + g], f); /* write green */
530 fputc(ptr[i + b], f); /* write blue */
531 }
532 }
533 fclose(f);
534 }
535 else {
536 fprintf(stderr, "Can't open %s for writing\n", filename);
537 }
538 #endif
539 }
540
541 void debug_dump_surface(const char *prefix,
542 struct pipe_surface *surface)
543 {
544 struct pipe_texture *texture;
545 struct pipe_screen *screen;
546 struct pipe_transfer *transfer;
547 void *data;
548
549 if (!surface)
550 return;
551
552 texture = surface->texture;
553 screen = texture->screen;
554
555 transfer = screen->get_tex_transfer(screen, texture, surface->face,
556 surface->level, surface->zslice,
557 PIPE_TRANSFER_READ, 0, 0, surface->width,
558 surface->height);
559
560 data = screen->transfer_map(screen, transfer);
561 if(!data)
562 goto error;
563
564 debug_dump_image(prefix,
565 texture->format,
566 util_format_get_blocksize(texture->format),
567 util_format_get_nblocksx(texture->format, transfer->width),
568 util_format_get_nblocksy(texture->format, transfer->height),
569 transfer->stride,
570 data);
571
572 screen->transfer_unmap(screen, transfer);
573 error:
574 screen->tex_transfer_destroy(transfer);
575 }
576
577
578 void debug_dump_texture(const char *prefix,
579 struct pipe_texture *texture)
580 {
581 struct pipe_surface *surface;
582 struct pipe_screen *screen;
583
584 if (!texture)
585 return;
586
587 screen = texture->screen;
588
589 /* XXX for now, just dump image for face=0, level=0 */
590 surface = screen->get_tex_surface(screen, texture, 0, 0, 0,
591 PIPE_TEXTURE_USAGE_SAMPLER);
592 if (surface) {
593 debug_dump_surface(prefix, surface);
594 screen->tex_surface_destroy(surface);
595 }
596 }
597
598
599 #pragma pack(push,2)
600 struct bmp_file_header {
601 uint16_t bfType;
602 uint32_t bfSize;
603 uint16_t bfReserved1;
604 uint16_t bfReserved2;
605 uint32_t bfOffBits;
606 };
607 #pragma pack(pop)
608
609 struct bmp_info_header {
610 uint32_t biSize;
611 int32_t biWidth;
612 int32_t biHeight;
613 uint16_t biPlanes;
614 uint16_t biBitCount;
615 uint32_t biCompression;
616 uint32_t biSizeImage;
617 int32_t biXPelsPerMeter;
618 int32_t biYPelsPerMeter;
619 uint32_t biClrUsed;
620 uint32_t biClrImportant;
621 };
622
623 struct bmp_rgb_quad {
624 uint8_t rgbBlue;
625 uint8_t rgbGreen;
626 uint8_t rgbRed;
627 uint8_t rgbAlpha;
628 };
629
630 void
631 debug_dump_surface_bmp(const char *filename,
632 struct pipe_surface *surface)
633 {
634 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
635 struct pipe_transfer *transfer;
636 struct pipe_texture *texture = surface->texture;
637 struct pipe_screen *screen = texture->screen;
638
639 transfer = screen->get_tex_transfer(screen, texture, surface->face,
640 surface->level, surface->zslice,
641 PIPE_TRANSFER_READ, 0, 0, surface->width,
642 surface->height);
643
644 debug_dump_transfer_bmp(filename, transfer);
645
646 screen->tex_transfer_destroy(transfer);
647 #endif
648 }
649
650 void
651 debug_dump_transfer_bmp(const char *filename,
652 struct pipe_transfer *transfer)
653 {
654 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
655 float *rgba;
656
657 if (!transfer)
658 goto error1;
659
660 rgba = MALLOC(transfer->width*transfer->height*4*sizeof(float));
661 if(!rgba)
662 goto error1;
663
664 pipe_get_tile_rgba(transfer, 0, 0,
665 transfer->width, transfer->height,
666 rgba);
667
668 debug_dump_float_rgba_bmp(filename,
669 transfer->width, transfer->height,
670 rgba, transfer->width);
671
672 FREE(rgba);
673 error1:
674 ;
675 #endif
676 }
677
678 void
679 debug_dump_float_rgba_bmp(const char *filename,
680 unsigned width, unsigned height,
681 float *rgba, unsigned stride)
682 {
683 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
684 struct os_stream *stream;
685 struct bmp_file_header bmfh;
686 struct bmp_info_header bmih;
687 unsigned x, y;
688
689 if(!rgba)
690 goto error1;
691
692 bmfh.bfType = 0x4d42;
693 bmfh.bfSize = 14 + 40 + height*width*4;
694 bmfh.bfReserved1 = 0;
695 bmfh.bfReserved2 = 0;
696 bmfh.bfOffBits = 14 + 40;
697
698 bmih.biSize = 40;
699 bmih.biWidth = width;
700 bmih.biHeight = height;
701 bmih.biPlanes = 1;
702 bmih.biBitCount = 32;
703 bmih.biCompression = 0;
704 bmih.biSizeImage = height*width*4;
705 bmih.biXPelsPerMeter = 0;
706 bmih.biYPelsPerMeter = 0;
707 bmih.biClrUsed = 0;
708 bmih.biClrImportant = 0;
709
710 stream = os_stream_create(filename, bmfh.bfSize);
711 if(!stream)
712 goto error1;
713
714 os_stream_write(stream, &bmfh, 14);
715 os_stream_write(stream, &bmih, 40);
716
717 y = height;
718 while(y--) {
719 float *ptr = rgba + (stride * y * 4);
720 for(x = 0; x < width; ++x)
721 {
722 struct bmp_rgb_quad pixel;
723 pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);
724 pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
725 pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
726 pixel.rgbAlpha = 255;
727 os_stream_write(stream, &pixel, 4);
728 }
729 }
730
731 os_stream_close(stream);
732 error1:
733 ;
734 #endif
735 }
736
737 #endif