mesa: Reject ResumeTransformFeedback if the wrong program is bound.
[mesa.git] / src / mesa / main / debug.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009 VMware, Inc. 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 "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "mtypes.h"
27 #include "attrib.h"
28 #include "colormac.h"
29 #include "enums.h"
30 #include "formats.h"
31 #include "hash.h"
32 #include "imports.h"
33 #include "debug.h"
34 #include "get.h"
35 #include "pixelstore.h"
36 #include "readpix.h"
37 #include "texobj.h"
38
39
40 static const char *
41 tex_target_name(GLenum tgt)
42 {
43 static const struct {
44 GLenum target;
45 const char *name;
46 } tex_targets[] = {
47 { GL_TEXTURE_1D, "GL_TEXTURE_1D" },
48 { GL_TEXTURE_2D, "GL_TEXTURE_2D" },
49 { GL_TEXTURE_3D, "GL_TEXTURE_3D" },
50 { GL_TEXTURE_CUBE_MAP, "GL_TEXTURE_CUBE_MAP" },
51 { GL_TEXTURE_RECTANGLE, "GL_TEXTURE_RECTANGLE" },
52 { GL_TEXTURE_1D_ARRAY_EXT, "GL_TEXTURE_1D_ARRAY" },
53 { GL_TEXTURE_2D_ARRAY_EXT, "GL_TEXTURE_2D_ARRAY" },
54 { GL_TEXTURE_CUBE_MAP_ARRAY, "GL_TEXTURE_CUBE_MAP_ARRAY" },
55 { GL_TEXTURE_BUFFER, "GL_TEXTURE_BUFFER" },
56 { GL_TEXTURE_2D_MULTISAMPLE, "GL_TEXTURE_2D_MULTISAMPLE" },
57 { GL_TEXTURE_2D_MULTISAMPLE_ARRAY, "GL_TEXTURE_2D_MULTISAMPLE_ARRAY" },
58 { GL_TEXTURE_EXTERNAL_OES, "GL_TEXTURE_EXTERNAL_OES" }
59 };
60 GLuint i;
61 STATIC_ASSERT(Elements(tex_targets) == NUM_TEXTURE_TARGETS);
62 for (i = 0; i < Elements(tex_targets); i++) {
63 if (tex_targets[i].target == tgt)
64 return tex_targets[i].name;
65 }
66 return "UNKNOWN TEX TARGET";
67 }
68
69
70 void
71 _mesa_print_state( const char *msg, GLuint state )
72 {
73 _mesa_debug(NULL,
74 "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
75 msg,
76 state,
77 (state & _NEW_MODELVIEW) ? "ctx->ModelView, " : "",
78 (state & _NEW_PROJECTION) ? "ctx->Projection, " : "",
79 (state & _NEW_TEXTURE_MATRIX) ? "ctx->TextureMatrix, " : "",
80 (state & _NEW_COLOR) ? "ctx->Color, " : "",
81 (state & _NEW_DEPTH) ? "ctx->Depth, " : "",
82 (state & _NEW_EVAL) ? "ctx->Eval/EvalMap, " : "",
83 (state & _NEW_FOG) ? "ctx->Fog, " : "",
84 (state & _NEW_HINT) ? "ctx->Hint, " : "",
85 (state & _NEW_LIGHT) ? "ctx->Light, " : "",
86 (state & _NEW_LINE) ? "ctx->Line, " : "",
87 (state & _NEW_PIXEL) ? "ctx->Pixel, " : "",
88 (state & _NEW_POINT) ? "ctx->Point, " : "",
89 (state & _NEW_POLYGON) ? "ctx->Polygon, " : "",
90 (state & _NEW_POLYGONSTIPPLE) ? "ctx->PolygonStipple, " : "",
91 (state & _NEW_SCISSOR) ? "ctx->Scissor, " : "",
92 (state & _NEW_STENCIL) ? "ctx->Stencil, " : "",
93 (state & _NEW_TEXTURE) ? "ctx->Texture, " : "",
94 (state & _NEW_TRANSFORM) ? "ctx->Transform, " : "",
95 (state & _NEW_VIEWPORT) ? "ctx->Viewport, " : "",
96 (state & _NEW_ARRAY) ? "ctx->Array, " : "",
97 (state & _NEW_RENDERMODE) ? "ctx->RenderMode, " : "",
98 (state & _NEW_BUFFERS) ? "ctx->Visual, ctx->DrawBuffer,, " : "");
99 }
100
101
102
103 /**
104 * Print information about this Mesa version and build options.
105 */
106 void _mesa_print_info( void )
107 {
108 _mesa_debug(NULL, "Mesa GL_VERSION = %s\n",
109 (char *) _mesa_GetString(GL_VERSION));
110 _mesa_debug(NULL, "Mesa GL_RENDERER = %s\n",
111 (char *) _mesa_GetString(GL_RENDERER));
112 _mesa_debug(NULL, "Mesa GL_VENDOR = %s\n",
113 (char *) _mesa_GetString(GL_VENDOR));
114 _mesa_debug(NULL, "Mesa GL_EXTENSIONS = %s\n",
115 (char *) _mesa_GetString(GL_EXTENSIONS));
116 #if defined(THREADS)
117 _mesa_debug(NULL, "Mesa thread-safe: YES\n");
118 #else
119 _mesa_debug(NULL, "Mesa thread-safe: NO\n");
120 #endif
121 #if defined(USE_X86_ASM)
122 _mesa_debug(NULL, "Mesa x86-optimized: YES\n");
123 #else
124 _mesa_debug(NULL, "Mesa x86-optimized: NO\n");
125 #endif
126 #if defined(USE_SPARC_ASM)
127 _mesa_debug(NULL, "Mesa sparc-optimized: YES\n");
128 #else
129 _mesa_debug(NULL, "Mesa sparc-optimized: NO\n");
130 #endif
131 }
132
133
134 /**
135 * Set verbose logging flags. When these flags are set, GL API calls
136 * in the various categories will be printed to stderr.
137 * \param str a comma-separated list of keywords
138 */
139 static void
140 set_verbose_flags(const char *str)
141 {
142 #ifdef DEBUG
143 struct option {
144 const char *name;
145 GLbitfield flag;
146 };
147 static const struct option opts[] = {
148 { "varray", VERBOSE_VARRAY },
149 { "tex", VERBOSE_TEXTURE },
150 { "mat", VERBOSE_MATERIAL },
151 { "pipe", VERBOSE_PIPELINE },
152 { "driver", VERBOSE_DRIVER },
153 { "state", VERBOSE_STATE },
154 { "api", VERBOSE_API },
155 { "list", VERBOSE_DISPLAY_LIST },
156 { "lighting", VERBOSE_LIGHTING },
157 { "disassem", VERBOSE_DISASSEM },
158 { "draw", VERBOSE_DRAW },
159 { "swap", VERBOSE_SWAPBUFFERS }
160 };
161 GLuint i;
162
163 if (!str)
164 return;
165
166 MESA_VERBOSE = 0x0;
167 for (i = 0; i < Elements(opts); i++) {
168 if (strstr(str, opts[i].name) || strcmp(str, "all") == 0)
169 MESA_VERBOSE |= opts[i].flag;
170 }
171 #endif
172 }
173
174
175 /**
176 * Set debugging flags. When these flags are set, Mesa will do additional
177 * debug checks or actions.
178 * \param str a comma-separated list of keywords
179 */
180 static void
181 set_debug_flags(const char *str)
182 {
183 #ifdef DEBUG
184 struct option {
185 const char *name;
186 GLbitfield flag;
187 };
188 static const struct option opts[] = {
189 { "silent", DEBUG_SILENT }, /* turn off debug messages */
190 { "flush", DEBUG_ALWAYS_FLUSH }, /* flush after each drawing command */
191 { "incomplete_tex", DEBUG_INCOMPLETE_TEXTURE },
192 { "incomplete_fbo", DEBUG_INCOMPLETE_FBO }
193 };
194 GLuint i;
195
196 if (!str)
197 return;
198
199 MESA_DEBUG_FLAGS = 0x0;
200 for (i = 0; i < Elements(opts); i++) {
201 if (strstr(str, opts[i].name))
202 MESA_DEBUG_FLAGS |= opts[i].flag;
203 }
204 #endif
205 }
206
207
208 /**
209 * Initialize debugging variables from env vars.
210 */
211 void
212 _mesa_init_debug( struct gl_context *ctx )
213 {
214 set_debug_flags(_mesa_getenv("MESA_DEBUG"));
215 set_verbose_flags(_mesa_getenv("MESA_VERBOSE"));
216 }
217
218
219 /*
220 * Write ppm file
221 */
222 static void
223 write_ppm(const char *filename, const GLubyte *buffer, int width, int height,
224 int comps, int rcomp, int gcomp, int bcomp, GLboolean invert)
225 {
226 FILE *f = fopen( filename, "w" );
227 if (f) {
228 int x, y;
229 const GLubyte *ptr = buffer;
230 fprintf(f,"P6\n");
231 fprintf(f,"# ppm-file created by osdemo.c\n");
232 fprintf(f,"%i %i\n", width,height);
233 fprintf(f,"255\n");
234 fclose(f);
235 f = fopen( filename, "ab" ); /* reopen in binary append mode */
236 for (y=0; y < height; y++) {
237 for (x = 0; x < width; x++) {
238 int yy = invert ? (height - 1 - y) : y;
239 int i = (yy * width + x) * comps;
240 fputc(ptr[i+rcomp], f); /* write red */
241 fputc(ptr[i+gcomp], f); /* write green */
242 fputc(ptr[i+bcomp], f); /* write blue */
243 }
244 }
245 fclose(f);
246 }
247 else {
248 fprintf(stderr, "Unable to create %s in write_ppm()\n", filename);
249 }
250 }
251
252
253 /**
254 * Write a texture image to a ppm file.
255 * \param face cube face in [0,5]
256 * \param level mipmap level
257 */
258 static void
259 write_texture_image(struct gl_texture_object *texObj,
260 GLuint face, GLuint level)
261 {
262 struct gl_texture_image *img = texObj->Image[face][level];
263 if (img) {
264 GET_CURRENT_CONTEXT(ctx);
265 struct gl_pixelstore_attrib store;
266 GLubyte *buffer;
267 char s[100];
268
269 buffer = malloc(img->Width * img->Height
270 * img->Depth * 4);
271
272 store = ctx->Pack; /* save */
273 ctx->Pack = ctx->DefaultPacking;
274
275 ctx->Driver.GetTexImage(ctx, GL_RGBA, GL_UNSIGNED_BYTE, buffer, img);
276
277 /* make filename */
278 _mesa_snprintf(s, sizeof(s), "/tmp/tex%u.l%u.f%u.ppm", texObj->Name, level, face);
279
280 printf(" Writing image level %u to %s\n", level, s);
281 write_ppm(s, buffer, img->Width, img->Height, 4, 0, 1, 2, GL_FALSE);
282
283 ctx->Pack = store; /* restore */
284
285 free(buffer);
286 }
287 }
288
289
290 /**
291 * Write renderbuffer image to a ppm file.
292 */
293 void
294 _mesa_write_renderbuffer_image(const struct gl_renderbuffer *rb)
295 {
296 GET_CURRENT_CONTEXT(ctx);
297 GLubyte *buffer;
298 char s[100];
299 GLenum format, type;
300
301 if (rb->_BaseFormat == GL_RGB ||
302 rb->_BaseFormat == GL_RGBA) {
303 format = GL_RGBA;
304 type = GL_UNSIGNED_BYTE;
305 }
306 else if (rb->_BaseFormat == GL_DEPTH_STENCIL) {
307 format = GL_DEPTH_STENCIL;
308 type = GL_UNSIGNED_INT_24_8;
309 }
310 else {
311 _mesa_debug(NULL,
312 "Unsupported BaseFormat 0x%x in "
313 "_mesa_write_renderbuffer_image()\n",
314 rb->_BaseFormat);
315 return;
316 }
317
318 buffer = malloc(rb->Width * rb->Height * 4);
319
320 ctx->Driver.ReadPixels(ctx, 0, 0, rb->Width, rb->Height,
321 format, type, &ctx->DefaultPacking, buffer);
322
323 /* make filename */
324 _mesa_snprintf(s, sizeof(s), "/tmp/renderbuffer%u.ppm", rb->Name);
325 _mesa_snprintf(s, sizeof(s), "C:\\renderbuffer%u.ppm", rb->Name);
326
327 printf(" Writing renderbuffer image to %s\n", s);
328
329 _mesa_debug(NULL, " Writing renderbuffer image to %s\n", s);
330
331 write_ppm(s, buffer, rb->Width, rb->Height, 4, 0, 1, 2, GL_TRUE);
332
333 free(buffer);
334 }
335
336
337 /** How many texture images (mipmap levels, faces) to write to files */
338 #define WRITE_NONE 0
339 #define WRITE_ONE 1
340 #define WRITE_ALL 2
341
342 static GLuint WriteImages;
343
344
345 static void
346 dump_texture(struct gl_texture_object *texObj, GLuint writeImages)
347 {
348 const GLuint numFaces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
349 GLboolean written = GL_FALSE;
350 GLuint i, j;
351
352 printf("Texture %u\n", texObj->Name);
353 printf(" Target %s\n", tex_target_name(texObj->Target));
354 for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
355 for (j = 0; j < numFaces; j++) {
356 struct gl_texture_image *texImg = texObj->Image[j][i];
357 if (texImg) {
358 printf(" Face %u level %u: %d x %d x %d, format %s\n",
359 j, i,
360 texImg->Width, texImg->Height, texImg->Depth,
361 _mesa_get_format_name(texImg->TexFormat));
362 if (writeImages == WRITE_ALL ||
363 (writeImages == WRITE_ONE && !written)) {
364 write_texture_image(texObj, j, i);
365 written = GL_TRUE;
366 }
367 }
368 }
369 }
370 }
371
372
373 /**
374 * Dump a single texture.
375 */
376 void
377 _mesa_dump_texture(GLuint texture, GLuint writeImages)
378 {
379 GET_CURRENT_CONTEXT(ctx);
380 struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture);
381 if (texObj) {
382 dump_texture(texObj, writeImages);
383 }
384 }
385
386
387 static void
388 dump_texture_cb(GLuint id, void *data, void *userData)
389 {
390 struct gl_texture_object *texObj = (struct gl_texture_object *) data;
391 (void) userData;
392 dump_texture(texObj, WriteImages);
393 }
394
395
396 /**
397 * Print basic info about all texture objext to stdout.
398 * If dumpImages is true, write PPM of level[0] image to a file.
399 */
400 void
401 _mesa_dump_textures(GLuint writeImages)
402 {
403 GET_CURRENT_CONTEXT(ctx);
404 WriteImages = writeImages;
405 _mesa_HashWalk(ctx->Shared->TexObjects, dump_texture_cb, ctx);
406 }
407
408
409 static void
410 dump_renderbuffer(const struct gl_renderbuffer *rb, GLboolean writeImage)
411 {
412 printf("Renderbuffer %u: %u x %u IntFormat = %s\n",
413 rb->Name, rb->Width, rb->Height,
414 _mesa_lookup_enum_by_nr(rb->InternalFormat));
415 if (writeImage) {
416 _mesa_write_renderbuffer_image(rb);
417 }
418 }
419
420
421 static void
422 dump_renderbuffer_cb(GLuint id, void *data, void *userData)
423 {
424 const struct gl_renderbuffer *rb = (const struct gl_renderbuffer *) data;
425 (void) userData;
426 dump_renderbuffer(rb, WriteImages);
427 }
428
429
430 /**
431 * Print basic info about all renderbuffers to stdout.
432 * If dumpImages is true, write PPM of level[0] image to a file.
433 */
434 void
435 _mesa_dump_renderbuffers(GLboolean writeImages)
436 {
437 GET_CURRENT_CONTEXT(ctx);
438 WriteImages = writeImages;
439 _mesa_HashWalk(ctx->Shared->RenderBuffers, dump_renderbuffer_cb, ctx);
440 }
441
442
443
444 void
445 _mesa_dump_color_buffer(const char *filename)
446 {
447 GET_CURRENT_CONTEXT(ctx);
448 const GLuint w = ctx->DrawBuffer->Width;
449 const GLuint h = ctx->DrawBuffer->Height;
450 GLubyte *buf;
451
452 buf = malloc(w * h * 4);
453
454 _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
455 _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
456 _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
457
458 _mesa_ReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buf);
459
460 printf("ReadBuffer %p 0x%x DrawBuffer %p 0x%x\n",
461 (void *) ctx->ReadBuffer->_ColorReadBuffer,
462 ctx->ReadBuffer->ColorReadBuffer,
463 (void *) ctx->DrawBuffer->_ColorDrawBuffers[0],
464 ctx->DrawBuffer->ColorDrawBuffer[0]);
465 printf("Writing %d x %d color buffer to %s\n", w, h, filename);
466 write_ppm(filename, buf, w, h, 4, 0, 1, 2, GL_TRUE);
467
468 _mesa_PopClientAttrib();
469
470 free(buf);
471 }
472
473
474 void
475 _mesa_dump_depth_buffer(const char *filename)
476 {
477 GET_CURRENT_CONTEXT(ctx);
478 const GLuint w = ctx->DrawBuffer->Width;
479 const GLuint h = ctx->DrawBuffer->Height;
480 GLuint *buf;
481 GLubyte *buf2;
482 GLuint i;
483
484 buf = malloc(w * h * 4); /* 4 bpp */
485 buf2 = malloc(w * h * 3); /* 3 bpp */
486
487 _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
488 _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
489 _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
490
491 _mesa_ReadPixels(0, 0, w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buf);
492
493 /* spread 24 bits of Z across R, G, B */
494 for (i = 0; i < w * h; i++) {
495 buf2[i*3+0] = (buf[i] >> 24) & 0xff;
496 buf2[i*3+1] = (buf[i] >> 16) & 0xff;
497 buf2[i*3+2] = (buf[i] >> 8) & 0xff;
498 }
499
500 printf("Writing %d x %d depth buffer to %s\n", w, h, filename);
501 write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE);
502
503 _mesa_PopClientAttrib();
504
505 free(buf);
506 free(buf2);
507 }
508
509
510 void
511 _mesa_dump_stencil_buffer(const char *filename)
512 {
513 GET_CURRENT_CONTEXT(ctx);
514 const GLuint w = ctx->DrawBuffer->Width;
515 const GLuint h = ctx->DrawBuffer->Height;
516 GLubyte *buf;
517 GLubyte *buf2;
518 GLuint i;
519
520 buf = malloc(w * h); /* 1 bpp */
521 buf2 = malloc(w * h * 3); /* 3 bpp */
522
523 _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
524 _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
525 _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
526
527 _mesa_ReadPixels(0, 0, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf);
528
529 for (i = 0; i < w * h; i++) {
530 buf2[i*3+0] = buf[i];
531 buf2[i*3+1] = (buf[i] & 127) * 2;
532 buf2[i*3+2] = (buf[i] - 128) * 2;
533 }
534
535 printf("Writing %d x %d stencil buffer to %s\n", w, h, filename);
536 write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE);
537
538 _mesa_PopClientAttrib();
539
540 free(buf);
541 free(buf2);
542 }
543
544
545 void
546 _mesa_dump_image(const char *filename, const void *image, GLuint w, GLuint h,
547 GLenum format, GLenum type)
548 {
549 GLboolean invert = GL_TRUE;
550
551 if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
552 write_ppm(filename, image, w, h, 4, 0, 1, 2, invert);
553 }
554 else if (format == GL_BGRA && type == GL_UNSIGNED_BYTE) {
555 write_ppm(filename, image, w, h, 4, 2, 1, 0, invert);
556 }
557 else if (format == GL_LUMINANCE_ALPHA && type == GL_UNSIGNED_BYTE) {
558 write_ppm(filename, image, w, h, 2, 1, 0, 0, invert);
559 }
560 else if (format == GL_RED && type == GL_UNSIGNED_BYTE) {
561 write_ppm(filename, image, w, h, 1, 0, 0, 0, invert);
562 }
563 else if (format == GL_RGBA && type == GL_FLOAT) {
564 /* convert floats to ubyte */
565 GLubyte *buf = malloc(w * h * 4 * sizeof(GLubyte));
566 const GLfloat *f = (const GLfloat *) image;
567 GLuint i;
568 for (i = 0; i < w * h * 4; i++) {
569 UNCLAMPED_FLOAT_TO_UBYTE(buf[i], f[i]);
570 }
571 write_ppm(filename, buf, w, h, 4, 0, 1, 2, invert);
572 free(buf);
573 }
574 else if (format == GL_RED && type == GL_FLOAT) {
575 /* convert floats to ubyte */
576 GLubyte *buf = malloc(w * h * sizeof(GLubyte));
577 const GLfloat *f = (const GLfloat *) image;
578 GLuint i;
579 for (i = 0; i < w * h; i++) {
580 UNCLAMPED_FLOAT_TO_UBYTE(buf[i], f[i]);
581 }
582 write_ppm(filename, buf, w, h, 1, 0, 0, 0, invert);
583 free(buf);
584 }
585 else {
586 _mesa_problem(NULL,
587 "Unsupported format 0x%x / type 0x%x in _mesa_dump_image()",
588 format, type);
589 }
590 }
591
592
593 /**
594 * Quick and dirty function to "print" a texture to stdout.
595 */
596 void
597 _mesa_print_texture(struct gl_context *ctx, struct gl_texture_image *img)
598 {
599 const GLint slice = 0;
600 GLint srcRowStride;
601 GLuint i, j, c;
602 GLubyte *data;
603
604 ctx->Driver.MapTextureImage(ctx, img, slice,
605 0, 0, img->Width, img->Height, GL_MAP_READ_BIT,
606 &data, &srcRowStride);
607
608 if (!data) {
609 printf("No texture data\n");
610 }
611 else {
612 /* XXX add more formats or make into a new format utility function */
613 switch (img->TexFormat) {
614 case MESA_FORMAT_A8:
615 case MESA_FORMAT_L8:
616 case MESA_FORMAT_I8:
617 c = 1;
618 break;
619 case MESA_FORMAT_AL88:
620 case MESA_FORMAT_AL88_REV:
621 c = 2;
622 break;
623 case MESA_FORMAT_RGB888:
624 case MESA_FORMAT_BGR888:
625 c = 3;
626 break;
627 case MESA_FORMAT_RGBA8888:
628 case MESA_FORMAT_ARGB8888:
629 c = 4;
630 break;
631 default:
632 _mesa_problem(NULL, "error in PrintTexture\n");
633 return;
634 }
635
636 for (i = 0; i < img->Height; i++) {
637 for (j = 0; j < img->Width; j++) {
638 if (c==1)
639 printf("%02x ", data[0]);
640 else if (c==2)
641 printf("%02x%02x ", data[0], data[1]);
642 else if (c==3)
643 printf("%02x%02x%02x ", data[0], data[1], data[2]);
644 else if (c==4)
645 printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
646 data += (srcRowStride - img->Width) * c;
647 }
648 /* XXX use img->ImageStride here */
649 printf("\n");
650
651 }
652 }
653
654 ctx->Driver.UnmapTextureImage(ctx, img, slice);
655 }