debug.c revision cdc920a0
17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
37117f1b4Smrg * Version:  6.5
47117f1b4Smrg *
57117f1b4Smrg * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
64a49301eSmrg * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
77117f1b4Smrg *
87117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
97117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
107117f1b4Smrg * to deal in the Software without restriction, including without limitation
117117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
127117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
137117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
147117f1b4Smrg *
157117f1b4Smrg * The above copyright notice and this permission notice shall be included
167117f1b4Smrg * in all copies or substantial portions of the Software.
177117f1b4Smrg *
187117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
197117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
207117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
217117f1b4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
227117f1b4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
237117f1b4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
247117f1b4Smrg */
257117f1b4Smrg
267117f1b4Smrg#include "mtypes.h"
274a49301eSmrg#include "attrib.h"
284a49301eSmrg#include "colormac.h"
294a49301eSmrg#include "enums.h"
304a49301eSmrg#include "formats.h"
314a49301eSmrg#include "hash.h"
327117f1b4Smrg#include "imports.h"
337117f1b4Smrg#include "debug.h"
347117f1b4Smrg#include "get.h"
354a49301eSmrg#include "pixelstore.h"
364a49301eSmrg#include "readpix.h"
374a49301eSmrg#include "texobj.h"
384a49301eSmrg
397117f1b4Smrg
407117f1b4Smrg/**
417117f1b4Smrg * Primitive names
427117f1b4Smrg */
437117f1b4Smrgconst char *_mesa_prim_name[GL_POLYGON+4] = {
447117f1b4Smrg   "GL_POINTS",
457117f1b4Smrg   "GL_LINES",
467117f1b4Smrg   "GL_LINE_LOOP",
477117f1b4Smrg   "GL_LINE_STRIP",
487117f1b4Smrg   "GL_TRIANGLES",
497117f1b4Smrg   "GL_TRIANGLE_STRIP",
507117f1b4Smrg   "GL_TRIANGLE_FAN",
517117f1b4Smrg   "GL_QUADS",
527117f1b4Smrg   "GL_QUAD_STRIP",
537117f1b4Smrg   "GL_POLYGON",
547117f1b4Smrg   "outside begin/end",
554a49301eSmrg   "inside unknown primitive",
567117f1b4Smrg   "unknown state"
577117f1b4Smrg};
587117f1b4Smrg
594a49301eSmrg
604a49301eSmrgstatic const char *
614a49301eSmrgtex_target_name(GLenum tgt)
624a49301eSmrg{
634a49301eSmrg   static const struct {
644a49301eSmrg      GLenum target;
654a49301eSmrg      const char *name;
664a49301eSmrg   } tex_targets[] = {
674a49301eSmrg      { GL_TEXTURE_1D, "GL_TEXTURE_1D" },
684a49301eSmrg      { GL_TEXTURE_2D, "GL_TEXTURE_2D" },
694a49301eSmrg      { GL_TEXTURE_3D, "GL_TEXTURE_3D" },
704a49301eSmrg      { GL_TEXTURE_CUBE_MAP, "GL_TEXTURE_CUBE_MAP" },
714a49301eSmrg      { GL_TEXTURE_RECTANGLE, "GL_TEXTURE_RECTANGLE" },
724a49301eSmrg      { GL_TEXTURE_1D_ARRAY_EXT, "GL_TEXTURE_1D_ARRAY" },
734a49301eSmrg      { GL_TEXTURE_2D_ARRAY_EXT, "GL_TEXTURE_2D_ARRAY" }
744a49301eSmrg   };
754a49301eSmrg   GLuint i;
764a49301eSmrg   for (i = 0; i < Elements(tex_targets); i++) {
774a49301eSmrg      if (tex_targets[i].target == tgt)
784a49301eSmrg         return tex_targets[i].name;
794a49301eSmrg   }
804a49301eSmrg   return "UNKNOWN TEX TARGET";
814a49301eSmrg}
824a49301eSmrg
834a49301eSmrg
847117f1b4Smrgvoid
857117f1b4Smrg_mesa_print_state( const char *msg, GLuint state )
867117f1b4Smrg{
877117f1b4Smrg   _mesa_debug(NULL,
887117f1b4Smrg	   "%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%s%s\n",
897117f1b4Smrg	   msg,
907117f1b4Smrg	   state,
917117f1b4Smrg	   (state & _NEW_MODELVIEW)       ? "ctx->ModelView, " : "",
927117f1b4Smrg	   (state & _NEW_PROJECTION)      ? "ctx->Projection, " : "",
937117f1b4Smrg	   (state & _NEW_TEXTURE_MATRIX)  ? "ctx->TextureMatrix, " : "",
947117f1b4Smrg	   (state & _NEW_COLOR_MATRIX)    ? "ctx->ColorMatrix, " : "",
957117f1b4Smrg	   (state & _NEW_ACCUM)           ? "ctx->Accum, " : "",
967117f1b4Smrg	   (state & _NEW_COLOR)           ? "ctx->Color, " : "",
977117f1b4Smrg	   (state & _NEW_DEPTH)           ? "ctx->Depth, " : "",
987117f1b4Smrg	   (state & _NEW_EVAL)            ? "ctx->Eval/EvalMap, " : "",
997117f1b4Smrg	   (state & _NEW_FOG)             ? "ctx->Fog, " : "",
1007117f1b4Smrg	   (state & _NEW_HINT)            ? "ctx->Hint, " : "",
1017117f1b4Smrg	   (state & _NEW_LIGHT)           ? "ctx->Light, " : "",
1027117f1b4Smrg	   (state & _NEW_LINE)            ? "ctx->Line, " : "",
1037117f1b4Smrg	   (state & _NEW_PIXEL)           ? "ctx->Pixel, " : "",
1047117f1b4Smrg	   (state & _NEW_POINT)           ? "ctx->Point, " : "",
1057117f1b4Smrg	   (state & _NEW_POLYGON)         ? "ctx->Polygon, " : "",
1067117f1b4Smrg	   (state & _NEW_POLYGONSTIPPLE)  ? "ctx->PolygonStipple, " : "",
1077117f1b4Smrg	   (state & _NEW_SCISSOR)         ? "ctx->Scissor, " : "",
1087117f1b4Smrg	   (state & _NEW_TEXTURE)         ? "ctx->Texture, " : "",
1097117f1b4Smrg	   (state & _NEW_TRANSFORM)       ? "ctx->Transform, " : "",
1107117f1b4Smrg	   (state & _NEW_VIEWPORT)        ? "ctx->Viewport, " : "",
1117117f1b4Smrg	   (state & _NEW_PACKUNPACK)      ? "ctx->Pack/Unpack, " : "",
1127117f1b4Smrg	   (state & _NEW_ARRAY)           ? "ctx->Array, " : "",
1137117f1b4Smrg	   (state & _NEW_RENDERMODE)      ? "ctx->RenderMode, " : "",
1147117f1b4Smrg	   (state & _NEW_BUFFERS)         ? "ctx->Visual, ctx->DrawBuffer,, " : "");
1157117f1b4Smrg}
1167117f1b4Smrg
1177117f1b4Smrg
1187117f1b4Smrg
1197117f1b4Smrgvoid
1207117f1b4Smrg_mesa_print_tri_caps( const char *name, GLuint flags )
1217117f1b4Smrg{
1227117f1b4Smrg   _mesa_debug(NULL,
1237117f1b4Smrg	   "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
1247117f1b4Smrg	   name,
1257117f1b4Smrg	   flags,
1267117f1b4Smrg	   (flags & DD_FLATSHADE)           ? "flat-shade, " : "",
1277117f1b4Smrg	   (flags & DD_SEPARATE_SPECULAR)   ? "separate-specular, " : "",
1287117f1b4Smrg	   (flags & DD_TRI_LIGHT_TWOSIDE)   ? "tri-light-twoside, " : "",
1297117f1b4Smrg	   (flags & DD_TRI_TWOSTENCIL)      ? "tri-twostencil, " : "",
1307117f1b4Smrg	   (flags & DD_TRI_UNFILLED)        ? "tri-unfilled, " : "",
1317117f1b4Smrg	   (flags & DD_TRI_STIPPLE)         ? "tri-stipple, " : "",
1327117f1b4Smrg	   (flags & DD_TRI_OFFSET)          ? "tri-offset, " : "",
1337117f1b4Smrg	   (flags & DD_TRI_SMOOTH)          ? "tri-smooth, " : "",
1347117f1b4Smrg	   (flags & DD_LINE_SMOOTH)         ? "line-smooth, " : "",
1357117f1b4Smrg	   (flags & DD_LINE_STIPPLE)        ? "line-stipple, " : "",
1367117f1b4Smrg	   (flags & DD_LINE_WIDTH)          ? "line-wide, " : "",
1377117f1b4Smrg	   (flags & DD_POINT_SMOOTH)        ? "point-smooth, " : "",
1387117f1b4Smrg	   (flags & DD_POINT_SIZE)          ? "point-size, " : "",
1397117f1b4Smrg	   (flags & DD_POINT_ATTEN)         ? "point-atten, " : "",
1407117f1b4Smrg	   (flags & DD_TRI_CULL_FRONT_BACK) ? "cull-all, " : ""
1417117f1b4Smrg      );
1427117f1b4Smrg}
1437117f1b4Smrg
1447117f1b4Smrg
1457117f1b4Smrg/**
1467117f1b4Smrg * Print information about this Mesa version and build options.
1477117f1b4Smrg */
1487117f1b4Smrgvoid _mesa_print_info( void )
1497117f1b4Smrg{
1507117f1b4Smrg   _mesa_debug(NULL, "Mesa GL_VERSION = %s\n",
1517117f1b4Smrg	   (char *) _mesa_GetString(GL_VERSION));
1527117f1b4Smrg   _mesa_debug(NULL, "Mesa GL_RENDERER = %s\n",
1537117f1b4Smrg	   (char *) _mesa_GetString(GL_RENDERER));
1547117f1b4Smrg   _mesa_debug(NULL, "Mesa GL_VENDOR = %s\n",
1557117f1b4Smrg	   (char *) _mesa_GetString(GL_VENDOR));
1567117f1b4Smrg   _mesa_debug(NULL, "Mesa GL_EXTENSIONS = %s\n",
1577117f1b4Smrg	   (char *) _mesa_GetString(GL_EXTENSIONS));
1587117f1b4Smrg#if defined(THREADS)
1597117f1b4Smrg   _mesa_debug(NULL, "Mesa thread-safe: YES\n");
1607117f1b4Smrg#else
1617117f1b4Smrg   _mesa_debug(NULL, "Mesa thread-safe: NO\n");
1627117f1b4Smrg#endif
1637117f1b4Smrg#if defined(USE_X86_ASM)
1647117f1b4Smrg   _mesa_debug(NULL, "Mesa x86-optimized: YES\n");
1657117f1b4Smrg#else
1667117f1b4Smrg   _mesa_debug(NULL, "Mesa x86-optimized: NO\n");
1677117f1b4Smrg#endif
1687117f1b4Smrg#if defined(USE_SPARC_ASM)
1697117f1b4Smrg   _mesa_debug(NULL, "Mesa sparc-optimized: YES\n");
1707117f1b4Smrg#else
1717117f1b4Smrg   _mesa_debug(NULL, "Mesa sparc-optimized: NO\n");
1727117f1b4Smrg#endif
1737117f1b4Smrg}
1747117f1b4Smrg
1757117f1b4Smrg
1767117f1b4Smrg/**
1777117f1b4Smrg * Set the debugging flags.
1787117f1b4Smrg *
1797117f1b4Smrg * \param debug debug string
1807117f1b4Smrg *
1817117f1b4Smrg * If compiled with debugging support then search for keywords in \p debug and
1827117f1b4Smrg * enables the verbose debug output of the respective feature.
1837117f1b4Smrg */
1847117f1b4Smrgstatic void add_debug_flags( const char *debug )
1857117f1b4Smrg{
1867117f1b4Smrg#ifdef DEBUG
187c1f859d4Smrg   struct debug_option {
188c1f859d4Smrg      const char *name;
189c1f859d4Smrg      GLbitfield flag;
190c1f859d4Smrg   };
191c1f859d4Smrg   static const struct debug_option debug_opt[] = {
192c1f859d4Smrg      { "varray",    VERBOSE_VARRAY },
193c1f859d4Smrg      { "tex",       VERBOSE_TEXTURE },
1944a49301eSmrg      { "mat",       VERBOSE_MATERIAL },
195c1f859d4Smrg      { "pipe",      VERBOSE_PIPELINE },
196c1f859d4Smrg      { "driver",    VERBOSE_DRIVER },
197c1f859d4Smrg      { "state",     VERBOSE_STATE },
198c1f859d4Smrg      { "api",       VERBOSE_API },
199c1f859d4Smrg      { "list",      VERBOSE_DISPLAY_LIST },
200c1f859d4Smrg      { "lighting",  VERBOSE_LIGHTING },
201c1f859d4Smrg      { "disassem",  VERBOSE_DISASSEM },
2024a49301eSmrg      { "draw",      VERBOSE_DRAW },
2034a49301eSmrg      { "swap",      VERBOSE_SWAPBUFFERS }
204c1f859d4Smrg   };
205c1f859d4Smrg   GLuint i;
206c1f859d4Smrg
207c1f859d4Smrg   MESA_VERBOSE = 0x0;
208c1f859d4Smrg   for (i = 0; i < Elements(debug_opt); i++) {
209cdc920a0Smrg      if (strstr(debug, debug_opt[i].name))
210c1f859d4Smrg         MESA_VERBOSE |= debug_opt[i].flag;
211c1f859d4Smrg   }
2127117f1b4Smrg
2137117f1b4Smrg   /* Debug flag:
2147117f1b4Smrg    */
215cdc920a0Smrg   if (strstr(debug, "flush"))
2167117f1b4Smrg      MESA_DEBUG_FLAGS |= DEBUG_ALWAYS_FLUSH;
2177117f1b4Smrg
2187117f1b4Smrg#if defined(_FPU_GETCW) && defined(_FPU_SETCW)
219cdc920a0Smrg   if (strstr(debug, "fpexceptions")) {
2207117f1b4Smrg      /* raise FP exceptions */
2217117f1b4Smrg      fpu_control_t mask;
2227117f1b4Smrg      _FPU_GETCW(mask);
2237117f1b4Smrg      mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM
2247117f1b4Smrg                | _FPU_MASK_OM | _FPU_MASK_UM);
2257117f1b4Smrg      _FPU_SETCW(mask);
2267117f1b4Smrg   }
2277117f1b4Smrg#endif
2287117f1b4Smrg
2297117f1b4Smrg#else
2307117f1b4Smrg   (void) debug;
2317117f1b4Smrg#endif
2327117f1b4Smrg}
2337117f1b4Smrg
2347117f1b4Smrg
2357117f1b4Smrgvoid
2367117f1b4Smrg_mesa_init_debug( GLcontext *ctx )
2377117f1b4Smrg{
2387117f1b4Smrg   char *c;
2397117f1b4Smrg
2407117f1b4Smrg   /* Dither disable */
2417117f1b4Smrg   ctx->NoDither = _mesa_getenv("MESA_NO_DITHER") ? GL_TRUE : GL_FALSE;
2427117f1b4Smrg   if (ctx->NoDither) {
2437117f1b4Smrg      if (_mesa_getenv("MESA_DEBUG")) {
2447117f1b4Smrg         _mesa_debug(ctx, "MESA_NO_DITHER set - dithering disabled\n");
2457117f1b4Smrg      }
2467117f1b4Smrg      ctx->Color.DitherFlag = GL_FALSE;
2477117f1b4Smrg   }
2487117f1b4Smrg
2497117f1b4Smrg   c = _mesa_getenv("MESA_DEBUG");
2507117f1b4Smrg   if (c)
2517117f1b4Smrg      add_debug_flags(c);
2527117f1b4Smrg
2537117f1b4Smrg   c = _mesa_getenv("MESA_VERBOSE");
2547117f1b4Smrg   if (c)
2557117f1b4Smrg      add_debug_flags(c);
2567117f1b4Smrg}
2577117f1b4Smrg
2584a49301eSmrg
2594a49301eSmrg/*
2604a49301eSmrg * Write ppm file
2614a49301eSmrg */
2624a49301eSmrgstatic void
2634a49301eSmrgwrite_ppm(const char *filename, const GLubyte *buffer, int width, int height,
2644a49301eSmrg          int comps, int rcomp, int gcomp, int bcomp, GLboolean invert)
2654a49301eSmrg{
2664a49301eSmrg   FILE *f = fopen( filename, "w" );
2674a49301eSmrg   if (f) {
2684a49301eSmrg      int x, y;
2694a49301eSmrg      const GLubyte *ptr = buffer;
2704a49301eSmrg      fprintf(f,"P6\n");
2714a49301eSmrg      fprintf(f,"# ppm-file created by osdemo.c\n");
2724a49301eSmrg      fprintf(f,"%i %i\n", width,height);
2734a49301eSmrg      fprintf(f,"255\n");
2744a49301eSmrg      fclose(f);
2754a49301eSmrg      f = fopen( filename, "ab" );  /* reopen in binary append mode */
2764a49301eSmrg      for (y=0; y < height; y++) {
2774a49301eSmrg         for (x = 0; x < width; x++) {
2784a49301eSmrg            int yy = invert ? (height - 1 - y) : y;
2794a49301eSmrg            int i = (yy * width + x) * comps;
2804a49301eSmrg            fputc(ptr[i+rcomp], f); /* write red */
2814a49301eSmrg            fputc(ptr[i+gcomp], f); /* write green */
2824a49301eSmrg            fputc(ptr[i+bcomp], f); /* write blue */
2834a49301eSmrg         }
2844a49301eSmrg      }
2854a49301eSmrg      fclose(f);
2864a49301eSmrg   }
2874a49301eSmrg}
2884a49301eSmrg
2894a49301eSmrg
2904a49301eSmrg/**
2914a49301eSmrg * Write a texture image to a ppm file.
2924a49301eSmrg * \param face  cube face in [0,5]
2934a49301eSmrg * \param level  mipmap level
2944a49301eSmrg */
2954a49301eSmrgstatic void
2964a49301eSmrgwrite_texture_image(struct gl_texture_object *texObj,
2974a49301eSmrg                    GLuint face, GLuint level)
2984a49301eSmrg{
2994a49301eSmrg   struct gl_texture_image *img = texObj->Image[face][level];
3004a49301eSmrg   if (img) {
3014a49301eSmrg      GET_CURRENT_CONTEXT(ctx);
3024a49301eSmrg      struct gl_pixelstore_attrib store;
3034a49301eSmrg      GLubyte *buffer;
3044a49301eSmrg      char s[100];
3054a49301eSmrg
306cdc920a0Smrg      buffer = (GLubyte *) malloc(img->Width * img->Height
3074a49301eSmrg                                        * img->Depth * 4);
3084a49301eSmrg
3094a49301eSmrg      store = ctx->Pack; /* save */
3104a49301eSmrg      ctx->Pack = ctx->DefaultPacking;
3114a49301eSmrg
3124a49301eSmrg      ctx->Driver.GetTexImage(ctx, texObj->Target, level,
3134a49301eSmrg                              GL_RGBA, GL_UNSIGNED_BYTE,
3144a49301eSmrg                              buffer, texObj, img);
3154a49301eSmrg
3164a49301eSmrg      /* make filename */
317cdc920a0Smrg      sprintf(s, "/tmp/tex%u.l%u.f%u.ppm", texObj->Name, level, face);
3184a49301eSmrg
319cdc920a0Smrg      printf("  Writing image level %u to %s\n", level, s);
3204a49301eSmrg      write_ppm(s, buffer, img->Width, img->Height, 4, 0, 1, 2, GL_FALSE);
3214a49301eSmrg
3224a49301eSmrg      ctx->Pack = store; /* restore */
3234a49301eSmrg
324cdc920a0Smrg      free(buffer);
3254a49301eSmrg   }
3264a49301eSmrg}
3274a49301eSmrg
3284a49301eSmrg
3294a49301eSmrg/**
3304a49301eSmrg * Write renderbuffer image to a ppm file.
3314a49301eSmrg */
3324a49301eSmrgstatic void
3334a49301eSmrgwrite_renderbuffer_image(const struct gl_renderbuffer *rb)
3344a49301eSmrg{
3354a49301eSmrg   GET_CURRENT_CONTEXT(ctx);
3364a49301eSmrg   GLubyte *buffer;
3374a49301eSmrg   char s[100];
3384a49301eSmrg   GLenum format, type;
3394a49301eSmrg
3404a49301eSmrg   if (rb->_BaseFormat == GL_RGB ||
3414a49301eSmrg       rb->_BaseFormat == GL_RGBA) {
3424a49301eSmrg      format = GL_RGBA;
3434a49301eSmrg      type = GL_UNSIGNED_BYTE;
3444a49301eSmrg   }
3454a49301eSmrg   else if (rb->_BaseFormat == GL_DEPTH_STENCIL) {
3464a49301eSmrg      format = GL_DEPTH_STENCIL;
3474a49301eSmrg      type = GL_UNSIGNED_INT_24_8;
3484a49301eSmrg   }
3494a49301eSmrg   else {
3504a49301eSmrg      return;
3514a49301eSmrg   }
3524a49301eSmrg
353cdc920a0Smrg   buffer = (GLubyte *) malloc(rb->Width * rb->Height * 4);
3544a49301eSmrg
3554a49301eSmrg   ctx->Driver.ReadPixels(ctx, 0, 0, rb->Width, rb->Height,
3564a49301eSmrg                          format, type, &ctx->DefaultPacking, buffer);
3574a49301eSmrg
3584a49301eSmrg   /* make filename */
359cdc920a0Smrg   sprintf(s, "/tmp/renderbuffer%u.ppm", rb->Name);
3604a49301eSmrg
361cdc920a0Smrg   printf("  Writing renderbuffer image to %s\n", s);
3624a49301eSmrg   write_ppm(s, buffer, rb->Width, rb->Height, 4, 0, 1, 2, GL_TRUE);
3634a49301eSmrg
364cdc920a0Smrg   free(buffer);
3654a49301eSmrg}
3664a49301eSmrg
3674a49301eSmrg
3684a49301eSmrg/** How many texture images (mipmap levels, faces) to write to files */
3694a49301eSmrg#define WRITE_NONE 0
3704a49301eSmrg#define WRITE_ONE  1
3714a49301eSmrg#define WRITE_ALL  2
3724a49301eSmrg
3734a49301eSmrgstatic GLuint WriteImages;
3744a49301eSmrg
3754a49301eSmrg
3764a49301eSmrgstatic void
3774a49301eSmrgdump_texture(struct gl_texture_object *texObj, GLuint writeImages)
3784a49301eSmrg{
3794a49301eSmrg   const GLuint numFaces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
3804a49301eSmrg   GLboolean written = GL_FALSE;
3814a49301eSmrg   GLuint i, j;
3824a49301eSmrg
383cdc920a0Smrg   printf("Texture %u\n", texObj->Name);
384cdc920a0Smrg   printf("  Target %s\n", tex_target_name(texObj->Target));
3854a49301eSmrg   for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
3864a49301eSmrg      for (j = 0; j < numFaces; j++) {
3874a49301eSmrg         struct gl_texture_image *texImg = texObj->Image[j][i];
3884a49301eSmrg         if (texImg) {
389cdc920a0Smrg            printf("  Face %u level %u: %d x %d x %d, format %s at %p\n",
390cdc920a0Smrg		   j, i,
391cdc920a0Smrg		   texImg->Width, texImg->Height, texImg->Depth,
392cdc920a0Smrg		   _mesa_get_format_name(texImg->TexFormat),
393cdc920a0Smrg		   texImg->Data);
3944a49301eSmrg            if (writeImages == WRITE_ALL ||
3954a49301eSmrg                (writeImages == WRITE_ONE && !written)) {
3964a49301eSmrg               write_texture_image(texObj, j, i);
3974a49301eSmrg               written = GL_TRUE;
3984a49301eSmrg            }
3994a49301eSmrg         }
4004a49301eSmrg      }
4014a49301eSmrg   }
4024a49301eSmrg}
4034a49301eSmrg
4044a49301eSmrg
4054a49301eSmrg/**
4064a49301eSmrg * Dump a single texture.
4074a49301eSmrg */
4084a49301eSmrgvoid
4094a49301eSmrg_mesa_dump_texture(GLuint texture, GLuint writeImages)
4104a49301eSmrg{
4114a49301eSmrg   GET_CURRENT_CONTEXT(ctx);
4124a49301eSmrg   struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture);
4134a49301eSmrg   if (texObj) {
4144a49301eSmrg      dump_texture(texObj, writeImages);
4154a49301eSmrg   }
4164a49301eSmrg}
4174a49301eSmrg
4184a49301eSmrg
4194a49301eSmrgstatic void
4204a49301eSmrgdump_texture_cb(GLuint id, void *data, void *userData)
4214a49301eSmrg{
4224a49301eSmrg   struct gl_texture_object *texObj = (struct gl_texture_object *) data;
4234a49301eSmrg   (void) userData;
4244a49301eSmrg   dump_texture(texObj, WriteImages);
4254a49301eSmrg}
4264a49301eSmrg
4274a49301eSmrg
4284a49301eSmrg/**
4294a49301eSmrg * Print basic info about all texture objext to stdout.
4304a49301eSmrg * If dumpImages is true, write PPM of level[0] image to a file.
4314a49301eSmrg */
4324a49301eSmrgvoid
4334a49301eSmrg_mesa_dump_textures(GLuint writeImages)
4344a49301eSmrg{
4354a49301eSmrg   GET_CURRENT_CONTEXT(ctx);
4364a49301eSmrg   WriteImages = writeImages;
4374a49301eSmrg   _mesa_HashWalk(ctx->Shared->TexObjects, dump_texture_cb, ctx);
4384a49301eSmrg}
4394a49301eSmrg
4404a49301eSmrg
4414a49301eSmrgstatic void
4424a49301eSmrgdump_renderbuffer(const struct gl_renderbuffer *rb, GLboolean writeImage)
4434a49301eSmrg{
444cdc920a0Smrg   printf("Renderbuffer %u: %u x %u  IntFormat = %s\n",
445cdc920a0Smrg	  rb->Name, rb->Width, rb->Height,
446cdc920a0Smrg	  _mesa_lookup_enum_by_nr(rb->InternalFormat));
4474a49301eSmrg   if (writeImage) {
4484a49301eSmrg      write_renderbuffer_image(rb);
4494a49301eSmrg   }
4504a49301eSmrg}
4514a49301eSmrg
4524a49301eSmrg
4534a49301eSmrgstatic void
4544a49301eSmrgdump_renderbuffer_cb(GLuint id, void *data, void *userData)
4554a49301eSmrg{
4564a49301eSmrg   const struct gl_renderbuffer *rb = (const struct gl_renderbuffer *) data;
4574a49301eSmrg   (void) userData;
4584a49301eSmrg   dump_renderbuffer(rb, WriteImages);
4594a49301eSmrg}
4604a49301eSmrg
4614a49301eSmrg
4624a49301eSmrg/**
4634a49301eSmrg * Print basic info about all renderbuffers to stdout.
4644a49301eSmrg * If dumpImages is true, write PPM of level[0] image to a file.
4654a49301eSmrg */
4664a49301eSmrgvoid
4674a49301eSmrg_mesa_dump_renderbuffers(GLboolean writeImages)
4684a49301eSmrg{
4694a49301eSmrg   GET_CURRENT_CONTEXT(ctx);
4704a49301eSmrg   WriteImages = writeImages;
4714a49301eSmrg   _mesa_HashWalk(ctx->Shared->RenderBuffers, dump_renderbuffer_cb, ctx);
4724a49301eSmrg}
4734a49301eSmrg
4744a49301eSmrg
4754a49301eSmrg
4764a49301eSmrgvoid
4774a49301eSmrg_mesa_dump_color_buffer(const char *filename)
4784a49301eSmrg{
4794a49301eSmrg   GET_CURRENT_CONTEXT(ctx);
4804a49301eSmrg   const GLuint w = ctx->DrawBuffer->Width;
4814a49301eSmrg   const GLuint h = ctx->DrawBuffer->Height;
4824a49301eSmrg   GLubyte *buf;
4834a49301eSmrg
484cdc920a0Smrg   buf = (GLubyte *) malloc(w * h * 4);
4854a49301eSmrg
4864a49301eSmrg   _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
4874a49301eSmrg   _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
4884a49301eSmrg   _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
4894a49301eSmrg
4904a49301eSmrg   _mesa_ReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buf);
4914a49301eSmrg
492cdc920a0Smrg   printf("ReadBuffer %p 0x%x  DrawBuffer %p 0x%x\n",
493cdc920a0Smrg	  (void *) ctx->ReadBuffer->_ColorReadBuffer,
494cdc920a0Smrg	  ctx->ReadBuffer->ColorReadBuffer,
495cdc920a0Smrg	  (void *) ctx->DrawBuffer->_ColorDrawBuffers[0],
496cdc920a0Smrg	  ctx->DrawBuffer->ColorDrawBuffer[0]);
497cdc920a0Smrg   printf("Writing %d x %d color buffer to %s\n", w, h, filename);
4984a49301eSmrg   write_ppm(filename, buf, w, h, 4, 0, 1, 2, GL_TRUE);
4994a49301eSmrg
5004a49301eSmrg   _mesa_PopClientAttrib();
5014a49301eSmrg
502cdc920a0Smrg   free(buf);
5034a49301eSmrg}
5044a49301eSmrg
5054a49301eSmrg
5064a49301eSmrgvoid
5074a49301eSmrg_mesa_dump_depth_buffer(const char *filename)
5084a49301eSmrg{
5094a49301eSmrg   GET_CURRENT_CONTEXT(ctx);
5104a49301eSmrg   const GLuint w = ctx->DrawBuffer->Width;
5114a49301eSmrg   const GLuint h = ctx->DrawBuffer->Height;
5124a49301eSmrg   GLuint *buf;
5134a49301eSmrg   GLubyte *buf2;
5144a49301eSmrg   GLuint i;
5154a49301eSmrg
516cdc920a0Smrg   buf = (GLuint *) malloc(w * h * 4);  /* 4 bpp */
517cdc920a0Smrg   buf2 = (GLubyte *) malloc(w * h * 3); /* 3 bpp */
5184a49301eSmrg
5194a49301eSmrg   _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
5204a49301eSmrg   _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
5214a49301eSmrg   _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
5224a49301eSmrg
5234a49301eSmrg   _mesa_ReadPixels(0, 0, w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buf);
5244a49301eSmrg
5254a49301eSmrg   /* spread 24 bits of Z across R, G, B */
5264a49301eSmrg   for (i = 0; i < w * h; i++) {
5274a49301eSmrg      buf2[i*3+0] = (buf[i] >> 24) & 0xff;
5284a49301eSmrg      buf2[i*3+1] = (buf[i] >> 16) & 0xff;
5294a49301eSmrg      buf2[i*3+2] = (buf[i] >>  8) & 0xff;
5304a49301eSmrg   }
5314a49301eSmrg
532cdc920a0Smrg   printf("Writing %d x %d depth buffer to %s\n", w, h, filename);
5334a49301eSmrg   write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE);
5344a49301eSmrg
5354a49301eSmrg   _mesa_PopClientAttrib();
5364a49301eSmrg
537cdc920a0Smrg   free(buf);
538cdc920a0Smrg   free(buf2);
5394a49301eSmrg}
5404a49301eSmrg
5414a49301eSmrg
5424a49301eSmrgvoid
5434a49301eSmrg_mesa_dump_stencil_buffer(const char *filename)
5444a49301eSmrg{
5454a49301eSmrg   GET_CURRENT_CONTEXT(ctx);
5464a49301eSmrg   const GLuint w = ctx->DrawBuffer->Width;
5474a49301eSmrg   const GLuint h = ctx->DrawBuffer->Height;
5484a49301eSmrg   GLubyte *buf;
5494a49301eSmrg   GLubyte *buf2;
5504a49301eSmrg   GLuint i;
5514a49301eSmrg
552cdc920a0Smrg   buf = (GLubyte *) malloc(w * h);  /* 1 bpp */
553cdc920a0Smrg   buf2 = (GLubyte *) malloc(w * h * 3); /* 3 bpp */
5544a49301eSmrg
5554a49301eSmrg   _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
5564a49301eSmrg   _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
5574a49301eSmrg   _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
5584a49301eSmrg
5594a49301eSmrg   _mesa_ReadPixels(0, 0, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf);
5604a49301eSmrg
5614a49301eSmrg   for (i = 0; i < w * h; i++) {
5624a49301eSmrg      buf2[i*3+0] = buf[i];
5634a49301eSmrg      buf2[i*3+1] = (buf[i] & 127) * 2;
5644a49301eSmrg      buf2[i*3+2] = (buf[i] - 128) * 2;
5654a49301eSmrg   }
5664a49301eSmrg
567cdc920a0Smrg   printf("Writing %d x %d stencil buffer to %s\n", w, h, filename);
5684a49301eSmrg   write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE);
5694a49301eSmrg
5704a49301eSmrg   _mesa_PopClientAttrib();
5714a49301eSmrg
572cdc920a0Smrg   free(buf);
573cdc920a0Smrg   free(buf2);
5744a49301eSmrg}
5754a49301eSmrg
5764a49301eSmrg
5774a49301eSmrg/**
5784a49301eSmrg * Quick and dirty function to "print" a texture to stdout.
5794a49301eSmrg */
5804a49301eSmrgvoid
5814a49301eSmrg_mesa_print_texture(GLcontext *ctx, const struct gl_texture_image *img)
5824a49301eSmrg{
5834a49301eSmrg#if CHAN_TYPE != GL_UNSIGNED_BYTE
5844a49301eSmrg   _mesa_problem(NULL, "PrintTexture not supported");
5854a49301eSmrg#else
5864a49301eSmrg   GLuint i, j, c;
5874a49301eSmrg   const GLubyte *data = (const GLubyte *) img->Data;
5884a49301eSmrg
5894a49301eSmrg   if (!data) {
590cdc920a0Smrg      printf("No texture data\n");
5914a49301eSmrg      return;
5924a49301eSmrg   }
5934a49301eSmrg
5944a49301eSmrg   /* XXX add more formats or make into a new format utility function */
5954a49301eSmrg   switch (img->TexFormat) {
5964a49301eSmrg      case MESA_FORMAT_A8:
5974a49301eSmrg      case MESA_FORMAT_L8:
5984a49301eSmrg      case MESA_FORMAT_I8:
5994a49301eSmrg      case MESA_FORMAT_CI8:
6004a49301eSmrg         c = 1;
6014a49301eSmrg         break;
6024a49301eSmrg      case MESA_FORMAT_AL88:
6034a49301eSmrg      case MESA_FORMAT_AL88_REV:
6044a49301eSmrg         c = 2;
6054a49301eSmrg         break;
6064a49301eSmrg      case MESA_FORMAT_RGB888:
6074a49301eSmrg      case MESA_FORMAT_BGR888:
6084a49301eSmrg         c = 3;
6094a49301eSmrg         break;
6104a49301eSmrg      case MESA_FORMAT_RGBA8888:
6114a49301eSmrg      case MESA_FORMAT_ARGB8888:
6124a49301eSmrg         c = 4;
6134a49301eSmrg         break;
6144a49301eSmrg      default:
6154a49301eSmrg         _mesa_problem(NULL, "error in PrintTexture\n");
6164a49301eSmrg         return;
6174a49301eSmrg   }
6184a49301eSmrg
6194a49301eSmrg   for (i = 0; i < img->Height; i++) {
6204a49301eSmrg      for (j = 0; j < img->Width; j++) {
6214a49301eSmrg         if (c==1)
622cdc920a0Smrg            printf("%02x  ", data[0]);
6234a49301eSmrg         else if (c==2)
624cdc920a0Smrg            printf("%02x%02x  ", data[0], data[1]);
6254a49301eSmrg         else if (c==3)
626cdc920a0Smrg            printf("%02x%02x%02x  ", data[0], data[1], data[2]);
6274a49301eSmrg         else if (c==4)
628cdc920a0Smrg            printf("%02x%02x%02x%02x  ", data[0], data[1], data[2], data[3]);
6294a49301eSmrg         data += (img->RowStride - img->Width) * c;
6304a49301eSmrg      }
6314a49301eSmrg      /* XXX use img->ImageStride here */
632cdc920a0Smrg      printf("\n");
6334a49301eSmrg   }
6344a49301eSmrg#endif
6354a49301eSmrg}
636