debug.c revision 848b8605
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
40static const char *
41tex_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
70void
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 */
106void _mesa_print_info( struct gl_context *ctx )
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
115   /* use ctx as GL_EXTENSIONS will not work on 3.0 or higher
116    * core contexts.
117    */
118   _mesa_debug(NULL, "Mesa GL_EXTENSIONS = %s\n", ctx->Extensions.String);
119
120#if defined(THREADS)
121   _mesa_debug(NULL, "Mesa thread-safe: YES\n");
122#else
123   _mesa_debug(NULL, "Mesa thread-safe: NO\n");
124#endif
125#if defined(USE_X86_ASM)
126   _mesa_debug(NULL, "Mesa x86-optimized: YES\n");
127#else
128   _mesa_debug(NULL, "Mesa x86-optimized: NO\n");
129#endif
130#if defined(USE_SPARC_ASM)
131   _mesa_debug(NULL, "Mesa sparc-optimized: YES\n");
132#else
133   _mesa_debug(NULL, "Mesa sparc-optimized: NO\n");
134#endif
135}
136
137
138/**
139 * Set verbose logging flags.  When these flags are set, GL API calls
140 * in the various categories will be printed to stderr.
141 * \param str  a comma-separated list of keywords
142 */
143static void
144set_verbose_flags(const char *str)
145{
146#ifdef DEBUG
147   struct option {
148      const char *name;
149      GLbitfield flag;
150   };
151   static const struct option opts[] = {
152      { "varray",    VERBOSE_VARRAY },
153      { "tex",       VERBOSE_TEXTURE },
154      { "mat",       VERBOSE_MATERIAL },
155      { "pipe",      VERBOSE_PIPELINE },
156      { "driver",    VERBOSE_DRIVER },
157      { "state",     VERBOSE_STATE },
158      { "api",       VERBOSE_API },
159      { "list",      VERBOSE_DISPLAY_LIST },
160      { "lighting",  VERBOSE_LIGHTING },
161      { "disassem",  VERBOSE_DISASSEM },
162      { "draw",      VERBOSE_DRAW },
163      { "swap",      VERBOSE_SWAPBUFFERS }
164   };
165   GLuint i;
166
167   if (!str)
168      return;
169
170   MESA_VERBOSE = 0x0;
171   for (i = 0; i < Elements(opts); i++) {
172      if (strstr(str, opts[i].name) || strcmp(str, "all") == 0)
173         MESA_VERBOSE |= opts[i].flag;
174   }
175#endif
176}
177
178
179/**
180 * Set debugging flags.  When these flags are set, Mesa will do additional
181 * debug checks or actions.
182 * \param str  a comma-separated list of keywords
183 */
184static void
185set_debug_flags(const char *str)
186{
187#ifdef DEBUG
188   struct option {
189      const char *name;
190      GLbitfield flag;
191   };
192   static const struct option opts[] = {
193      { "silent", DEBUG_SILENT }, /* turn off debug messages */
194      { "flush", DEBUG_ALWAYS_FLUSH }, /* flush after each drawing command */
195      { "incomplete_tex", DEBUG_INCOMPLETE_TEXTURE },
196      { "incomplete_fbo", DEBUG_INCOMPLETE_FBO }
197   };
198   GLuint i;
199
200   if (!str)
201      return;
202
203   MESA_DEBUG_FLAGS = 0x0;
204   for (i = 0; i < Elements(opts); i++) {
205      if (strstr(str, opts[i].name))
206         MESA_DEBUG_FLAGS |= opts[i].flag;
207   }
208#endif
209}
210
211
212/**
213 * Initialize debugging variables from env vars.
214 */
215void
216_mesa_init_debug( struct gl_context *ctx )
217{
218   set_debug_flags(_mesa_getenv("MESA_DEBUG"));
219   set_verbose_flags(_mesa_getenv("MESA_VERBOSE"));
220}
221
222
223/*
224 * Write ppm file
225 */
226static void
227write_ppm(const char *filename, const GLubyte *buffer, int width, int height,
228          int comps, int rcomp, int gcomp, int bcomp, GLboolean invert)
229{
230   FILE *f = fopen( filename, "w" );
231   if (f) {
232      int x, y;
233      const GLubyte *ptr = buffer;
234      fprintf(f,"P6\n");
235      fprintf(f,"# ppm-file created by osdemo.c\n");
236      fprintf(f,"%i %i\n", width,height);
237      fprintf(f,"255\n");
238      fclose(f);
239      f = fopen( filename, "ab" );  /* reopen in binary append mode */
240      for (y=0; y < height; y++) {
241         for (x = 0; x < width; x++) {
242            int yy = invert ? (height - 1 - y) : y;
243            int i = (yy * width + x) * comps;
244            fputc(ptr[i+rcomp], f); /* write red */
245            fputc(ptr[i+gcomp], f); /* write green */
246            fputc(ptr[i+bcomp], f); /* write blue */
247         }
248      }
249      fclose(f);
250   }
251   else {
252      fprintf(stderr, "Unable to create %s in write_ppm()\n", filename);
253   }
254}
255
256
257/**
258 * Write a texture image to a ppm file.
259 * \param face  cube face in [0,5]
260 * \param level  mipmap level
261 */
262static void
263write_texture_image(struct gl_texture_object *texObj,
264                    GLuint face, GLuint level)
265{
266   struct gl_texture_image *img = texObj->Image[face][level];
267   if (img) {
268      GET_CURRENT_CONTEXT(ctx);
269      struct gl_pixelstore_attrib store;
270      GLubyte *buffer;
271      char s[100];
272
273      buffer = malloc(img->Width * img->Height
274                                        * img->Depth * 4);
275
276      store = ctx->Pack; /* save */
277      ctx->Pack = ctx->DefaultPacking;
278
279      ctx->Driver.GetTexImage(ctx, GL_RGBA, GL_UNSIGNED_BYTE, buffer, img);
280
281      /* make filename */
282      _mesa_snprintf(s, sizeof(s), "/tmp/tex%u.l%u.f%u.ppm", texObj->Name, level, face);
283
284      printf("  Writing image level %u to %s\n", level, s);
285      write_ppm(s, buffer, img->Width, img->Height, 4, 0, 1, 2, GL_FALSE);
286
287      ctx->Pack = store; /* restore */
288
289      free(buffer);
290   }
291}
292
293
294/**
295 * Write renderbuffer image to a ppm file.
296 */
297void
298_mesa_write_renderbuffer_image(const struct gl_renderbuffer *rb)
299{
300   GET_CURRENT_CONTEXT(ctx);
301   GLubyte *buffer;
302   char s[100];
303   GLenum format, type;
304
305   if (rb->_BaseFormat == GL_RGB ||
306       rb->_BaseFormat == GL_RGBA) {
307      format = GL_RGBA;
308      type = GL_UNSIGNED_BYTE;
309   }
310   else if (rb->_BaseFormat == GL_DEPTH_STENCIL) {
311      format = GL_DEPTH_STENCIL;
312      type = GL_UNSIGNED_INT_24_8;
313   }
314   else {
315      _mesa_debug(NULL,
316                  "Unsupported BaseFormat 0x%x in "
317                  "_mesa_write_renderbuffer_image()\n",
318                  rb->_BaseFormat);
319      return;
320   }
321
322   buffer = malloc(rb->Width * rb->Height * 4);
323
324   ctx->Driver.ReadPixels(ctx, 0, 0, rb->Width, rb->Height,
325                          format, type, &ctx->DefaultPacking, buffer);
326
327   /* make filename */
328   _mesa_snprintf(s, sizeof(s), "/tmp/renderbuffer%u.ppm", rb->Name);
329   _mesa_snprintf(s, sizeof(s), "C:\\renderbuffer%u.ppm", rb->Name);
330
331   printf("  Writing renderbuffer image to %s\n", s);
332
333   _mesa_debug(NULL, "  Writing renderbuffer image to %s\n", s);
334
335   write_ppm(s, buffer, rb->Width, rb->Height, 4, 0, 1, 2, GL_TRUE);
336
337   free(buffer);
338}
339
340
341/** How many texture images (mipmap levels, faces) to write to files */
342#define WRITE_NONE 0
343#define WRITE_ONE  1
344#define WRITE_ALL  2
345
346static GLuint WriteImages;
347
348
349static void
350dump_texture(struct gl_texture_object *texObj, GLuint writeImages)
351{
352   const GLuint numFaces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
353   GLboolean written = GL_FALSE;
354   GLuint i, j;
355
356   printf("Texture %u\n", texObj->Name);
357   printf("  Target %s\n", tex_target_name(texObj->Target));
358   for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
359      for (j = 0; j < numFaces; j++) {
360         struct gl_texture_image *texImg = texObj->Image[j][i];
361         if (texImg) {
362            printf("  Face %u level %u: %d x %d x %d, format %s\n",
363		   j, i,
364		   texImg->Width, texImg->Height, texImg->Depth,
365		   _mesa_get_format_name(texImg->TexFormat));
366            if (writeImages == WRITE_ALL ||
367                (writeImages == WRITE_ONE && !written)) {
368               write_texture_image(texObj, j, i);
369               written = GL_TRUE;
370            }
371         }
372      }
373   }
374}
375
376
377/**
378 * Dump a single texture.
379 */
380void
381_mesa_dump_texture(GLuint texture, GLuint writeImages)
382{
383   GET_CURRENT_CONTEXT(ctx);
384   struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture);
385   if (texObj) {
386      dump_texture(texObj, writeImages);
387   }
388}
389
390
391static void
392dump_texture_cb(GLuint id, void *data, void *userData)
393{
394   struct gl_texture_object *texObj = (struct gl_texture_object *) data;
395   (void) userData;
396   dump_texture(texObj, WriteImages);
397}
398
399
400/**
401 * Print basic info about all texture objext to stdout.
402 * If dumpImages is true, write PPM of level[0] image to a file.
403 */
404void
405_mesa_dump_textures(GLuint writeImages)
406{
407   GET_CURRENT_CONTEXT(ctx);
408   WriteImages = writeImages;
409   _mesa_HashWalk(ctx->Shared->TexObjects, dump_texture_cb, ctx);
410}
411
412
413static void
414dump_renderbuffer(const struct gl_renderbuffer *rb, GLboolean writeImage)
415{
416   printf("Renderbuffer %u: %u x %u  IntFormat = %s\n",
417	  rb->Name, rb->Width, rb->Height,
418	  _mesa_lookup_enum_by_nr(rb->InternalFormat));
419   if (writeImage) {
420      _mesa_write_renderbuffer_image(rb);
421   }
422}
423
424
425static void
426dump_renderbuffer_cb(GLuint id, void *data, void *userData)
427{
428   const struct gl_renderbuffer *rb = (const struct gl_renderbuffer *) data;
429   (void) userData;
430   dump_renderbuffer(rb, WriteImages);
431}
432
433
434/**
435 * Print basic info about all renderbuffers to stdout.
436 * If dumpImages is true, write PPM of level[0] image to a file.
437 */
438void
439_mesa_dump_renderbuffers(GLboolean writeImages)
440{
441   GET_CURRENT_CONTEXT(ctx);
442   WriteImages = writeImages;
443   _mesa_HashWalk(ctx->Shared->RenderBuffers, dump_renderbuffer_cb, ctx);
444}
445
446
447
448void
449_mesa_dump_color_buffer(const char *filename)
450{
451   GET_CURRENT_CONTEXT(ctx);
452   const GLuint w = ctx->DrawBuffer->Width;
453   const GLuint h = ctx->DrawBuffer->Height;
454   GLubyte *buf;
455
456   buf = malloc(w * h * 4);
457
458   _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
459   _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
460   _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
461
462   _mesa_ReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buf);
463
464   printf("ReadBuffer %p 0x%x  DrawBuffer %p 0x%x\n",
465	  (void *) ctx->ReadBuffer->_ColorReadBuffer,
466	  ctx->ReadBuffer->ColorReadBuffer,
467	  (void *) ctx->DrawBuffer->_ColorDrawBuffers[0],
468	  ctx->DrawBuffer->ColorDrawBuffer[0]);
469   printf("Writing %d x %d color buffer to %s\n", w, h, filename);
470   write_ppm(filename, buf, w, h, 4, 0, 1, 2, GL_TRUE);
471
472   _mesa_PopClientAttrib();
473
474   free(buf);
475}
476
477
478void
479_mesa_dump_depth_buffer(const char *filename)
480{
481   GET_CURRENT_CONTEXT(ctx);
482   const GLuint w = ctx->DrawBuffer->Width;
483   const GLuint h = ctx->DrawBuffer->Height;
484   GLuint *buf;
485   GLubyte *buf2;
486   GLuint i;
487
488   buf = malloc(w * h * 4);  /* 4 bpp */
489   buf2 = malloc(w * h * 3); /* 3 bpp */
490
491   _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
492   _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
493   _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
494
495   _mesa_ReadPixels(0, 0, w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buf);
496
497   /* spread 24 bits of Z across R, G, B */
498   for (i = 0; i < w * h; i++) {
499      buf2[i*3+0] = (buf[i] >> 24) & 0xff;
500      buf2[i*3+1] = (buf[i] >> 16) & 0xff;
501      buf2[i*3+2] = (buf[i] >>  8) & 0xff;
502   }
503
504   printf("Writing %d x %d depth buffer to %s\n", w, h, filename);
505   write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE);
506
507   _mesa_PopClientAttrib();
508
509   free(buf);
510   free(buf2);
511}
512
513
514void
515_mesa_dump_stencil_buffer(const char *filename)
516{
517   GET_CURRENT_CONTEXT(ctx);
518   const GLuint w = ctx->DrawBuffer->Width;
519   const GLuint h = ctx->DrawBuffer->Height;
520   GLubyte *buf;
521   GLubyte *buf2;
522   GLuint i;
523
524   buf = malloc(w * h);  /* 1 bpp */
525   buf2 = malloc(w * h * 3); /* 3 bpp */
526
527   _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
528   _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
529   _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
530
531   _mesa_ReadPixels(0, 0, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf);
532
533   for (i = 0; i < w * h; i++) {
534      buf2[i*3+0] = buf[i];
535      buf2[i*3+1] = (buf[i] & 127) * 2;
536      buf2[i*3+2] = (buf[i] - 128) * 2;
537   }
538
539   printf("Writing %d x %d stencil buffer to %s\n", w, h, filename);
540   write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE);
541
542   _mesa_PopClientAttrib();
543
544   free(buf);
545   free(buf2);
546}
547
548
549void
550_mesa_dump_image(const char *filename, const void *image, GLuint w, GLuint h,
551                 GLenum format, GLenum type)
552{
553   GLboolean invert = GL_TRUE;
554
555   if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
556      write_ppm(filename, image, w, h, 4, 0, 1, 2, invert);
557   }
558   else if (format == GL_BGRA && type == GL_UNSIGNED_BYTE) {
559      write_ppm(filename, image, w, h, 4, 2, 1, 0, invert);
560   }
561   else if (format == GL_LUMINANCE_ALPHA && type == GL_UNSIGNED_BYTE) {
562      write_ppm(filename, image, w, h, 2, 1, 0, 0, invert);
563   }
564   else if (format == GL_RED && type == GL_UNSIGNED_BYTE) {
565      write_ppm(filename, image, w, h, 1, 0, 0, 0, invert);
566   }
567   else if (format == GL_RGBA && type == GL_FLOAT) {
568      /* convert floats to ubyte */
569      GLubyte *buf = malloc(w * h * 4 * sizeof(GLubyte));
570      const GLfloat *f = (const GLfloat *) image;
571      GLuint i;
572      for (i = 0; i < w * h * 4; i++) {
573         UNCLAMPED_FLOAT_TO_UBYTE(buf[i], f[i]);
574      }
575      write_ppm(filename, buf, w, h, 4, 0, 1, 2, invert);
576      free(buf);
577   }
578   else if (format == GL_RED && type == GL_FLOAT) {
579      /* convert floats to ubyte */
580      GLubyte *buf = malloc(w * h * sizeof(GLubyte));
581      const GLfloat *f = (const GLfloat *) image;
582      GLuint i;
583      for (i = 0; i < w * h; i++) {
584         UNCLAMPED_FLOAT_TO_UBYTE(buf[i], f[i]);
585      }
586      write_ppm(filename, buf, w, h, 1, 0, 0, 0, invert);
587      free(buf);
588   }
589   else {
590      _mesa_problem(NULL,
591                 "Unsupported format 0x%x / type 0x%x in _mesa_dump_image()",
592                 format, type);
593   }
594}
595
596
597/**
598 * Quick and dirty function to "print" a texture to stdout.
599 */
600void
601_mesa_print_texture(struct gl_context *ctx, struct gl_texture_image *img)
602{
603   const GLint slice = 0;
604   GLint srcRowStride;
605   GLuint i, j, c;
606   GLubyte *data;
607
608   ctx->Driver.MapTextureImage(ctx, img, slice,
609                               0, 0, img->Width, img->Height, GL_MAP_READ_BIT,
610                               &data, &srcRowStride);
611
612   if (!data) {
613      printf("No texture data\n");
614   }
615   else {
616      /* XXX add more formats or make into a new format utility function */
617      switch (img->TexFormat) {
618         case MESA_FORMAT_A_UNORM8:
619         case MESA_FORMAT_L_UNORM8:
620         case MESA_FORMAT_I_UNORM8:
621            c = 1;
622            break;
623         case MESA_FORMAT_L8A8_UNORM:
624         case MESA_FORMAT_A8L8_UNORM:
625            c = 2;
626            break;
627         case MESA_FORMAT_BGR_UNORM8:
628         case MESA_FORMAT_RGB_UNORM8:
629            c = 3;
630            break;
631         case MESA_FORMAT_A8B8G8R8_UNORM:
632         case MESA_FORMAT_B8G8R8A8_UNORM:
633            c = 4;
634            break;
635         default:
636            _mesa_problem(NULL, "error in PrintTexture\n");
637            return;
638      }
639
640      for (i = 0; i < img->Height; i++) {
641         for (j = 0; j < img->Width; j++) {
642            if (c==1)
643               printf("%02x  ", data[0]);
644            else if (c==2)
645               printf("%02x%02x  ", data[0], data[1]);
646            else if (c==3)
647               printf("%02x%02x%02x  ", data[0], data[1], data[2]);
648            else if (c==4)
649               printf("%02x%02x%02x%02x  ", data[0], data[1], data[2], data[3]);
650            data += (srcRowStride - img->Width) * c;
651         }
652         /* XXX use img->ImageStride here */
653         printf("\n");
654
655      }
656   }
657
658   ctx->Driver.UnmapTextureImage(ctx, img, slice);
659}
660