debug.c revision 3464ebd5
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 404a49301eSmrgstatic const char * 414a49301eSmrgtex_target_name(GLenum tgt) 424a49301eSmrg{ 434a49301eSmrg static const struct { 444a49301eSmrg GLenum target; 454a49301eSmrg const char *name; 464a49301eSmrg } tex_targets[] = { 474a49301eSmrg { GL_TEXTURE_1D, "GL_TEXTURE_1D" }, 484a49301eSmrg { GL_TEXTURE_2D, "GL_TEXTURE_2D" }, 494a49301eSmrg { GL_TEXTURE_3D, "GL_TEXTURE_3D" }, 504a49301eSmrg { GL_TEXTURE_CUBE_MAP, "GL_TEXTURE_CUBE_MAP" }, 514a49301eSmrg { GL_TEXTURE_RECTANGLE, "GL_TEXTURE_RECTANGLE" }, 524a49301eSmrg { GL_TEXTURE_1D_ARRAY_EXT, "GL_TEXTURE_1D_ARRAY" }, 534a49301eSmrg { GL_TEXTURE_2D_ARRAY_EXT, "GL_TEXTURE_2D_ARRAY" } 544a49301eSmrg }; 554a49301eSmrg GLuint i; 564a49301eSmrg for (i = 0; i < Elements(tex_targets); i++) { 574a49301eSmrg if (tex_targets[i].target == tgt) 584a49301eSmrg return tex_targets[i].name; 594a49301eSmrg } 604a49301eSmrg return "UNKNOWN TEX TARGET"; 614a49301eSmrg} 624a49301eSmrg 634a49301eSmrg 647117f1b4Smrgvoid 657117f1b4Smrg_mesa_print_state( const char *msg, GLuint state ) 667117f1b4Smrg{ 677117f1b4Smrg _mesa_debug(NULL, 683464ebd5Sriastradh "%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\n", 697117f1b4Smrg msg, 707117f1b4Smrg state, 717117f1b4Smrg (state & _NEW_MODELVIEW) ? "ctx->ModelView, " : "", 727117f1b4Smrg (state & _NEW_PROJECTION) ? "ctx->Projection, " : "", 737117f1b4Smrg (state & _NEW_TEXTURE_MATRIX) ? "ctx->TextureMatrix, " : "", 747117f1b4Smrg (state & _NEW_COLOR) ? "ctx->Color, " : "", 757117f1b4Smrg (state & _NEW_DEPTH) ? "ctx->Depth, " : "", 767117f1b4Smrg (state & _NEW_EVAL) ? "ctx->Eval/EvalMap, " : "", 777117f1b4Smrg (state & _NEW_FOG) ? "ctx->Fog, " : "", 787117f1b4Smrg (state & _NEW_HINT) ? "ctx->Hint, " : "", 797117f1b4Smrg (state & _NEW_LIGHT) ? "ctx->Light, " : "", 807117f1b4Smrg (state & _NEW_LINE) ? "ctx->Line, " : "", 817117f1b4Smrg (state & _NEW_PIXEL) ? "ctx->Pixel, " : "", 827117f1b4Smrg (state & _NEW_POINT) ? "ctx->Point, " : "", 837117f1b4Smrg (state & _NEW_POLYGON) ? "ctx->Polygon, " : "", 847117f1b4Smrg (state & _NEW_POLYGONSTIPPLE) ? "ctx->PolygonStipple, " : "", 857117f1b4Smrg (state & _NEW_SCISSOR) ? "ctx->Scissor, " : "", 863464ebd5Sriastradh (state & _NEW_STENCIL) ? "ctx->Stencil, " : "", 877117f1b4Smrg (state & _NEW_TEXTURE) ? "ctx->Texture, " : "", 887117f1b4Smrg (state & _NEW_TRANSFORM) ? "ctx->Transform, " : "", 897117f1b4Smrg (state & _NEW_VIEWPORT) ? "ctx->Viewport, " : "", 907117f1b4Smrg (state & _NEW_PACKUNPACK) ? "ctx->Pack/Unpack, " : "", 917117f1b4Smrg (state & _NEW_ARRAY) ? "ctx->Array, " : "", 927117f1b4Smrg (state & _NEW_RENDERMODE) ? "ctx->RenderMode, " : "", 937117f1b4Smrg (state & _NEW_BUFFERS) ? "ctx->Visual, ctx->DrawBuffer,, " : ""); 947117f1b4Smrg} 957117f1b4Smrg 967117f1b4Smrg 977117f1b4Smrg 987117f1b4Smrgvoid 997117f1b4Smrg_mesa_print_tri_caps( const char *name, GLuint flags ) 1007117f1b4Smrg{ 1017117f1b4Smrg _mesa_debug(NULL, 1023464ebd5Sriastradh "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s\n", 1037117f1b4Smrg name, 1047117f1b4Smrg flags, 1057117f1b4Smrg (flags & DD_FLATSHADE) ? "flat-shade, " : "", 1067117f1b4Smrg (flags & DD_SEPARATE_SPECULAR) ? "separate-specular, " : "", 1077117f1b4Smrg (flags & DD_TRI_LIGHT_TWOSIDE) ? "tri-light-twoside, " : "", 1087117f1b4Smrg (flags & DD_TRI_TWOSTENCIL) ? "tri-twostencil, " : "", 1097117f1b4Smrg (flags & DD_TRI_UNFILLED) ? "tri-unfilled, " : "", 1107117f1b4Smrg (flags & DD_TRI_STIPPLE) ? "tri-stipple, " : "", 1117117f1b4Smrg (flags & DD_TRI_OFFSET) ? "tri-offset, " : "", 1127117f1b4Smrg (flags & DD_TRI_SMOOTH) ? "tri-smooth, " : "", 1137117f1b4Smrg (flags & DD_LINE_SMOOTH) ? "line-smooth, " : "", 1147117f1b4Smrg (flags & DD_LINE_STIPPLE) ? "line-stipple, " : "", 1157117f1b4Smrg (flags & DD_POINT_SMOOTH) ? "point-smooth, " : "", 1167117f1b4Smrg (flags & DD_POINT_ATTEN) ? "point-atten, " : "", 1177117f1b4Smrg (flags & DD_TRI_CULL_FRONT_BACK) ? "cull-all, " : "" 1187117f1b4Smrg ); 1197117f1b4Smrg} 1207117f1b4Smrg 1217117f1b4Smrg 1227117f1b4Smrg/** 1237117f1b4Smrg * Print information about this Mesa version and build options. 1247117f1b4Smrg */ 1257117f1b4Smrgvoid _mesa_print_info( void ) 1267117f1b4Smrg{ 1277117f1b4Smrg _mesa_debug(NULL, "Mesa GL_VERSION = %s\n", 1287117f1b4Smrg (char *) _mesa_GetString(GL_VERSION)); 1297117f1b4Smrg _mesa_debug(NULL, "Mesa GL_RENDERER = %s\n", 1307117f1b4Smrg (char *) _mesa_GetString(GL_RENDERER)); 1317117f1b4Smrg _mesa_debug(NULL, "Mesa GL_VENDOR = %s\n", 1327117f1b4Smrg (char *) _mesa_GetString(GL_VENDOR)); 1337117f1b4Smrg _mesa_debug(NULL, "Mesa GL_EXTENSIONS = %s\n", 1347117f1b4Smrg (char *) _mesa_GetString(GL_EXTENSIONS)); 1357117f1b4Smrg#if defined(THREADS) 1367117f1b4Smrg _mesa_debug(NULL, "Mesa thread-safe: YES\n"); 1377117f1b4Smrg#else 1387117f1b4Smrg _mesa_debug(NULL, "Mesa thread-safe: NO\n"); 1397117f1b4Smrg#endif 1407117f1b4Smrg#if defined(USE_X86_ASM) 1417117f1b4Smrg _mesa_debug(NULL, "Mesa x86-optimized: YES\n"); 1427117f1b4Smrg#else 1437117f1b4Smrg _mesa_debug(NULL, "Mesa x86-optimized: NO\n"); 1447117f1b4Smrg#endif 1457117f1b4Smrg#if defined(USE_SPARC_ASM) 1467117f1b4Smrg _mesa_debug(NULL, "Mesa sparc-optimized: YES\n"); 1477117f1b4Smrg#else 1487117f1b4Smrg _mesa_debug(NULL, "Mesa sparc-optimized: NO\n"); 1497117f1b4Smrg#endif 1507117f1b4Smrg} 1517117f1b4Smrg 1527117f1b4Smrg 1537117f1b4Smrg/** 1547117f1b4Smrg * Set the debugging flags. 1557117f1b4Smrg * 1567117f1b4Smrg * \param debug debug string 1577117f1b4Smrg * 1587117f1b4Smrg * If compiled with debugging support then search for keywords in \p debug and 1597117f1b4Smrg * enables the verbose debug output of the respective feature. 1607117f1b4Smrg */ 1617117f1b4Smrgstatic void add_debug_flags( const char *debug ) 1627117f1b4Smrg{ 1637117f1b4Smrg#ifdef DEBUG 164c1f859d4Smrg struct debug_option { 165c1f859d4Smrg const char *name; 166c1f859d4Smrg GLbitfield flag; 167c1f859d4Smrg }; 168c1f859d4Smrg static const struct debug_option debug_opt[] = { 169c1f859d4Smrg { "varray", VERBOSE_VARRAY }, 170c1f859d4Smrg { "tex", VERBOSE_TEXTURE }, 1714a49301eSmrg { "mat", VERBOSE_MATERIAL }, 172c1f859d4Smrg { "pipe", VERBOSE_PIPELINE }, 173c1f859d4Smrg { "driver", VERBOSE_DRIVER }, 174c1f859d4Smrg { "state", VERBOSE_STATE }, 175c1f859d4Smrg { "api", VERBOSE_API }, 176c1f859d4Smrg { "list", VERBOSE_DISPLAY_LIST }, 177c1f859d4Smrg { "lighting", VERBOSE_LIGHTING }, 178c1f859d4Smrg { "disassem", VERBOSE_DISASSEM }, 1794a49301eSmrg { "draw", VERBOSE_DRAW }, 1804a49301eSmrg { "swap", VERBOSE_SWAPBUFFERS } 181c1f859d4Smrg }; 182c1f859d4Smrg GLuint i; 183c1f859d4Smrg 184c1f859d4Smrg MESA_VERBOSE = 0x0; 185c1f859d4Smrg for (i = 0; i < Elements(debug_opt); i++) { 1863464ebd5Sriastradh if (strstr(debug, debug_opt[i].name) || strcmp(debug, "all") == 0) 187c1f859d4Smrg MESA_VERBOSE |= debug_opt[i].flag; 188c1f859d4Smrg } 1897117f1b4Smrg 1907117f1b4Smrg /* Debug flag: 1917117f1b4Smrg */ 192cdc920a0Smrg if (strstr(debug, "flush")) 1937117f1b4Smrg MESA_DEBUG_FLAGS |= DEBUG_ALWAYS_FLUSH; 1947117f1b4Smrg 1957117f1b4Smrg#if defined(_FPU_GETCW) && defined(_FPU_SETCW) 196cdc920a0Smrg if (strstr(debug, "fpexceptions")) { 1977117f1b4Smrg /* raise FP exceptions */ 1987117f1b4Smrg fpu_control_t mask; 1997117f1b4Smrg _FPU_GETCW(mask); 2007117f1b4Smrg mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM 2017117f1b4Smrg | _FPU_MASK_OM | _FPU_MASK_UM); 2027117f1b4Smrg _FPU_SETCW(mask); 2037117f1b4Smrg } 2047117f1b4Smrg#endif 2057117f1b4Smrg 2067117f1b4Smrg#else 2077117f1b4Smrg (void) debug; 2087117f1b4Smrg#endif 2097117f1b4Smrg} 2107117f1b4Smrg 2117117f1b4Smrg 2127117f1b4Smrgvoid 2133464ebd5Sriastradh_mesa_init_debug( struct gl_context *ctx ) 2147117f1b4Smrg{ 2157117f1b4Smrg char *c; 2167117f1b4Smrg c = _mesa_getenv("MESA_DEBUG"); 2177117f1b4Smrg if (c) 2187117f1b4Smrg add_debug_flags(c); 2197117f1b4Smrg 2207117f1b4Smrg c = _mesa_getenv("MESA_VERBOSE"); 2217117f1b4Smrg if (c) 2227117f1b4Smrg add_debug_flags(c); 2237117f1b4Smrg} 2247117f1b4Smrg 2254a49301eSmrg 2264a49301eSmrg/* 2274a49301eSmrg * Write ppm file 2284a49301eSmrg */ 2294a49301eSmrgstatic void 2304a49301eSmrgwrite_ppm(const char *filename, const GLubyte *buffer, int width, int height, 2314a49301eSmrg int comps, int rcomp, int gcomp, int bcomp, GLboolean invert) 2324a49301eSmrg{ 2334a49301eSmrg FILE *f = fopen( filename, "w" ); 2344a49301eSmrg if (f) { 2354a49301eSmrg int x, y; 2364a49301eSmrg const GLubyte *ptr = buffer; 2374a49301eSmrg fprintf(f,"P6\n"); 2384a49301eSmrg fprintf(f,"# ppm-file created by osdemo.c\n"); 2394a49301eSmrg fprintf(f,"%i %i\n", width,height); 2404a49301eSmrg fprintf(f,"255\n"); 2414a49301eSmrg fclose(f); 2424a49301eSmrg f = fopen( filename, "ab" ); /* reopen in binary append mode */ 2434a49301eSmrg for (y=0; y < height; y++) { 2444a49301eSmrg for (x = 0; x < width; x++) { 2454a49301eSmrg int yy = invert ? (height - 1 - y) : y; 2464a49301eSmrg int i = (yy * width + x) * comps; 2474a49301eSmrg fputc(ptr[i+rcomp], f); /* write red */ 2484a49301eSmrg fputc(ptr[i+gcomp], f); /* write green */ 2494a49301eSmrg fputc(ptr[i+bcomp], f); /* write blue */ 2504a49301eSmrg } 2514a49301eSmrg } 2524a49301eSmrg fclose(f); 2534a49301eSmrg } 2543464ebd5Sriastradh else { 2553464ebd5Sriastradh fprintf(stderr, "Unable to create %s in write_ppm()\n", filename); 2563464ebd5Sriastradh } 2574a49301eSmrg} 2584a49301eSmrg 2594a49301eSmrg 2604a49301eSmrg/** 2614a49301eSmrg * Write a texture image to a ppm file. 2624a49301eSmrg * \param face cube face in [0,5] 2634a49301eSmrg * \param level mipmap level 2644a49301eSmrg */ 2654a49301eSmrgstatic void 2664a49301eSmrgwrite_texture_image(struct gl_texture_object *texObj, 2674a49301eSmrg GLuint face, GLuint level) 2684a49301eSmrg{ 2694a49301eSmrg struct gl_texture_image *img = texObj->Image[face][level]; 2704a49301eSmrg if (img) { 2714a49301eSmrg GET_CURRENT_CONTEXT(ctx); 2724a49301eSmrg struct gl_pixelstore_attrib store; 2734a49301eSmrg GLubyte *buffer; 2744a49301eSmrg char s[100]; 2754a49301eSmrg 276cdc920a0Smrg buffer = (GLubyte *) malloc(img->Width * img->Height 2774a49301eSmrg * img->Depth * 4); 2784a49301eSmrg 2794a49301eSmrg store = ctx->Pack; /* save */ 2804a49301eSmrg ctx->Pack = ctx->DefaultPacking; 2814a49301eSmrg 2824a49301eSmrg ctx->Driver.GetTexImage(ctx, texObj->Target, level, 2834a49301eSmrg GL_RGBA, GL_UNSIGNED_BYTE, 2844a49301eSmrg buffer, texObj, img); 2854a49301eSmrg 2864a49301eSmrg /* make filename */ 2873464ebd5Sriastradh _mesa_snprintf(s, sizeof(s), "/tmp/tex%u.l%u.f%u.ppm", texObj->Name, level, face); 2884a49301eSmrg 289cdc920a0Smrg printf(" Writing image level %u to %s\n", level, s); 2904a49301eSmrg write_ppm(s, buffer, img->Width, img->Height, 4, 0, 1, 2, GL_FALSE); 2914a49301eSmrg 2924a49301eSmrg ctx->Pack = store; /* restore */ 2934a49301eSmrg 294cdc920a0Smrg free(buffer); 2954a49301eSmrg } 2964a49301eSmrg} 2974a49301eSmrg 2984a49301eSmrg 2994a49301eSmrg/** 3004a49301eSmrg * Write renderbuffer image to a ppm file. 3014a49301eSmrg */ 3023464ebd5Sriastradhvoid 3033464ebd5Sriastradh_mesa_write_renderbuffer_image(const struct gl_renderbuffer *rb) 3044a49301eSmrg{ 3054a49301eSmrg GET_CURRENT_CONTEXT(ctx); 3064a49301eSmrg GLubyte *buffer; 3074a49301eSmrg char s[100]; 3084a49301eSmrg GLenum format, type; 3094a49301eSmrg 3104a49301eSmrg if (rb->_BaseFormat == GL_RGB || 3114a49301eSmrg rb->_BaseFormat == GL_RGBA) { 3124a49301eSmrg format = GL_RGBA; 3134a49301eSmrg type = GL_UNSIGNED_BYTE; 3144a49301eSmrg } 3154a49301eSmrg else if (rb->_BaseFormat == GL_DEPTH_STENCIL) { 3164a49301eSmrg format = GL_DEPTH_STENCIL; 3174a49301eSmrg type = GL_UNSIGNED_INT_24_8; 3184a49301eSmrg } 3194a49301eSmrg else { 3203464ebd5Sriastradh _mesa_debug(NULL, 3213464ebd5Sriastradh "Unsupported BaseFormat 0x%x in " 3223464ebd5Sriastradh "_mesa_write_renderbuffer_image()\n", 3233464ebd5Sriastradh rb->_BaseFormat); 3244a49301eSmrg return; 3254a49301eSmrg } 3264a49301eSmrg 327cdc920a0Smrg buffer = (GLubyte *) malloc(rb->Width * rb->Height * 4); 3284a49301eSmrg 3294a49301eSmrg ctx->Driver.ReadPixels(ctx, 0, 0, rb->Width, rb->Height, 3304a49301eSmrg format, type, &ctx->DefaultPacking, buffer); 3314a49301eSmrg 3324a49301eSmrg /* make filename */ 3333464ebd5Sriastradh _mesa_snprintf(s, sizeof(s), "/tmp/renderbuffer%u.ppm", rb->Name); 3343464ebd5Sriastradh _mesa_snprintf(s, sizeof(s), "C:\\renderbuffer%u.ppm", rb->Name); 3354a49301eSmrg 336cdc920a0Smrg printf(" Writing renderbuffer image to %s\n", s); 3373464ebd5Sriastradh 3383464ebd5Sriastradh _mesa_debug(NULL, " Writing renderbuffer image to %s\n", s); 3393464ebd5Sriastradh 3404a49301eSmrg write_ppm(s, buffer, rb->Width, rb->Height, 4, 0, 1, 2, GL_TRUE); 3414a49301eSmrg 342cdc920a0Smrg free(buffer); 3434a49301eSmrg} 3444a49301eSmrg 3454a49301eSmrg 3464a49301eSmrg/** How many texture images (mipmap levels, faces) to write to files */ 3474a49301eSmrg#define WRITE_NONE 0 3484a49301eSmrg#define WRITE_ONE 1 3494a49301eSmrg#define WRITE_ALL 2 3504a49301eSmrg 3514a49301eSmrgstatic GLuint WriteImages; 3524a49301eSmrg 3534a49301eSmrg 3544a49301eSmrgstatic void 3554a49301eSmrgdump_texture(struct gl_texture_object *texObj, GLuint writeImages) 3564a49301eSmrg{ 3574a49301eSmrg const GLuint numFaces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1; 3584a49301eSmrg GLboolean written = GL_FALSE; 3594a49301eSmrg GLuint i, j; 3604a49301eSmrg 361cdc920a0Smrg printf("Texture %u\n", texObj->Name); 362cdc920a0Smrg printf(" Target %s\n", tex_target_name(texObj->Target)); 3634a49301eSmrg for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { 3644a49301eSmrg for (j = 0; j < numFaces; j++) { 3654a49301eSmrg struct gl_texture_image *texImg = texObj->Image[j][i]; 3664a49301eSmrg if (texImg) { 367cdc920a0Smrg printf(" Face %u level %u: %d x %d x %d, format %s at %p\n", 368cdc920a0Smrg j, i, 369cdc920a0Smrg texImg->Width, texImg->Height, texImg->Depth, 370cdc920a0Smrg _mesa_get_format_name(texImg->TexFormat), 371cdc920a0Smrg texImg->Data); 3724a49301eSmrg if (writeImages == WRITE_ALL || 3734a49301eSmrg (writeImages == WRITE_ONE && !written)) { 3744a49301eSmrg write_texture_image(texObj, j, i); 3754a49301eSmrg written = GL_TRUE; 3764a49301eSmrg } 3774a49301eSmrg } 3784a49301eSmrg } 3794a49301eSmrg } 3804a49301eSmrg} 3814a49301eSmrg 3824a49301eSmrg 3834a49301eSmrg/** 3844a49301eSmrg * Dump a single texture. 3854a49301eSmrg */ 3864a49301eSmrgvoid 3874a49301eSmrg_mesa_dump_texture(GLuint texture, GLuint writeImages) 3884a49301eSmrg{ 3894a49301eSmrg GET_CURRENT_CONTEXT(ctx); 3904a49301eSmrg struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture); 3914a49301eSmrg if (texObj) { 3924a49301eSmrg dump_texture(texObj, writeImages); 3934a49301eSmrg } 3944a49301eSmrg} 3954a49301eSmrg 3964a49301eSmrg 3974a49301eSmrgstatic void 3984a49301eSmrgdump_texture_cb(GLuint id, void *data, void *userData) 3994a49301eSmrg{ 4004a49301eSmrg struct gl_texture_object *texObj = (struct gl_texture_object *) data; 4014a49301eSmrg (void) userData; 4024a49301eSmrg dump_texture(texObj, WriteImages); 4034a49301eSmrg} 4044a49301eSmrg 4054a49301eSmrg 4064a49301eSmrg/** 4074a49301eSmrg * Print basic info about all texture objext to stdout. 4084a49301eSmrg * If dumpImages is true, write PPM of level[0] image to a file. 4094a49301eSmrg */ 4104a49301eSmrgvoid 4114a49301eSmrg_mesa_dump_textures(GLuint writeImages) 4124a49301eSmrg{ 4134a49301eSmrg GET_CURRENT_CONTEXT(ctx); 4144a49301eSmrg WriteImages = writeImages; 4154a49301eSmrg _mesa_HashWalk(ctx->Shared->TexObjects, dump_texture_cb, ctx); 4164a49301eSmrg} 4174a49301eSmrg 4184a49301eSmrg 4194a49301eSmrgstatic void 4204a49301eSmrgdump_renderbuffer(const struct gl_renderbuffer *rb, GLboolean writeImage) 4214a49301eSmrg{ 422cdc920a0Smrg printf("Renderbuffer %u: %u x %u IntFormat = %s\n", 423cdc920a0Smrg rb->Name, rb->Width, rb->Height, 424cdc920a0Smrg _mesa_lookup_enum_by_nr(rb->InternalFormat)); 4254a49301eSmrg if (writeImage) { 4263464ebd5Sriastradh _mesa_write_renderbuffer_image(rb); 4274a49301eSmrg } 4284a49301eSmrg} 4294a49301eSmrg 4304a49301eSmrg 4314a49301eSmrgstatic void 4324a49301eSmrgdump_renderbuffer_cb(GLuint id, void *data, void *userData) 4334a49301eSmrg{ 4344a49301eSmrg const struct gl_renderbuffer *rb = (const struct gl_renderbuffer *) data; 4354a49301eSmrg (void) userData; 4364a49301eSmrg dump_renderbuffer(rb, WriteImages); 4374a49301eSmrg} 4384a49301eSmrg 4394a49301eSmrg 4404a49301eSmrg/** 4414a49301eSmrg * Print basic info about all renderbuffers to stdout. 4424a49301eSmrg * If dumpImages is true, write PPM of level[0] image to a file. 4434a49301eSmrg */ 4444a49301eSmrgvoid 4454a49301eSmrg_mesa_dump_renderbuffers(GLboolean writeImages) 4464a49301eSmrg{ 4474a49301eSmrg GET_CURRENT_CONTEXT(ctx); 4484a49301eSmrg WriteImages = writeImages; 4494a49301eSmrg _mesa_HashWalk(ctx->Shared->RenderBuffers, dump_renderbuffer_cb, ctx); 4504a49301eSmrg} 4514a49301eSmrg 4524a49301eSmrg 4534a49301eSmrg 4544a49301eSmrgvoid 4554a49301eSmrg_mesa_dump_color_buffer(const char *filename) 4564a49301eSmrg{ 4574a49301eSmrg GET_CURRENT_CONTEXT(ctx); 4584a49301eSmrg const GLuint w = ctx->DrawBuffer->Width; 4594a49301eSmrg const GLuint h = ctx->DrawBuffer->Height; 4604a49301eSmrg GLubyte *buf; 4614a49301eSmrg 462cdc920a0Smrg buf = (GLubyte *) malloc(w * h * 4); 4634a49301eSmrg 4644a49301eSmrg _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); 4654a49301eSmrg _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1); 4664a49301eSmrg _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); 4674a49301eSmrg 4684a49301eSmrg _mesa_ReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buf); 4694a49301eSmrg 470cdc920a0Smrg printf("ReadBuffer %p 0x%x DrawBuffer %p 0x%x\n", 471cdc920a0Smrg (void *) ctx->ReadBuffer->_ColorReadBuffer, 472cdc920a0Smrg ctx->ReadBuffer->ColorReadBuffer, 473cdc920a0Smrg (void *) ctx->DrawBuffer->_ColorDrawBuffers[0], 474cdc920a0Smrg ctx->DrawBuffer->ColorDrawBuffer[0]); 475cdc920a0Smrg printf("Writing %d x %d color buffer to %s\n", w, h, filename); 4764a49301eSmrg write_ppm(filename, buf, w, h, 4, 0, 1, 2, GL_TRUE); 4774a49301eSmrg 4784a49301eSmrg _mesa_PopClientAttrib(); 4794a49301eSmrg 480cdc920a0Smrg free(buf); 4814a49301eSmrg} 4824a49301eSmrg 4834a49301eSmrg 4844a49301eSmrgvoid 4854a49301eSmrg_mesa_dump_depth_buffer(const char *filename) 4864a49301eSmrg{ 4874a49301eSmrg GET_CURRENT_CONTEXT(ctx); 4884a49301eSmrg const GLuint w = ctx->DrawBuffer->Width; 4894a49301eSmrg const GLuint h = ctx->DrawBuffer->Height; 4904a49301eSmrg GLuint *buf; 4914a49301eSmrg GLubyte *buf2; 4924a49301eSmrg GLuint i; 4934a49301eSmrg 494cdc920a0Smrg buf = (GLuint *) malloc(w * h * 4); /* 4 bpp */ 495cdc920a0Smrg buf2 = (GLubyte *) malloc(w * h * 3); /* 3 bpp */ 4964a49301eSmrg 4974a49301eSmrg _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); 4984a49301eSmrg _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1); 4994a49301eSmrg _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); 5004a49301eSmrg 5014a49301eSmrg _mesa_ReadPixels(0, 0, w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buf); 5024a49301eSmrg 5034a49301eSmrg /* spread 24 bits of Z across R, G, B */ 5044a49301eSmrg for (i = 0; i < w * h; i++) { 5054a49301eSmrg buf2[i*3+0] = (buf[i] >> 24) & 0xff; 5064a49301eSmrg buf2[i*3+1] = (buf[i] >> 16) & 0xff; 5074a49301eSmrg buf2[i*3+2] = (buf[i] >> 8) & 0xff; 5084a49301eSmrg } 5094a49301eSmrg 510cdc920a0Smrg printf("Writing %d x %d depth buffer to %s\n", w, h, filename); 5114a49301eSmrg write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE); 5124a49301eSmrg 5134a49301eSmrg _mesa_PopClientAttrib(); 5144a49301eSmrg 515cdc920a0Smrg free(buf); 516cdc920a0Smrg free(buf2); 5174a49301eSmrg} 5184a49301eSmrg 5194a49301eSmrg 5204a49301eSmrgvoid 5214a49301eSmrg_mesa_dump_stencil_buffer(const char *filename) 5224a49301eSmrg{ 5234a49301eSmrg GET_CURRENT_CONTEXT(ctx); 5244a49301eSmrg const GLuint w = ctx->DrawBuffer->Width; 5254a49301eSmrg const GLuint h = ctx->DrawBuffer->Height; 5264a49301eSmrg GLubyte *buf; 5274a49301eSmrg GLubyte *buf2; 5284a49301eSmrg GLuint i; 5294a49301eSmrg 530cdc920a0Smrg buf = (GLubyte *) malloc(w * h); /* 1 bpp */ 531cdc920a0Smrg buf2 = (GLubyte *) malloc(w * h * 3); /* 3 bpp */ 5324a49301eSmrg 5334a49301eSmrg _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); 5344a49301eSmrg _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1); 5354a49301eSmrg _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); 5364a49301eSmrg 5374a49301eSmrg _mesa_ReadPixels(0, 0, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf); 5384a49301eSmrg 5394a49301eSmrg for (i = 0; i < w * h; i++) { 5404a49301eSmrg buf2[i*3+0] = buf[i]; 5414a49301eSmrg buf2[i*3+1] = (buf[i] & 127) * 2; 5424a49301eSmrg buf2[i*3+2] = (buf[i] - 128) * 2; 5434a49301eSmrg } 5444a49301eSmrg 545cdc920a0Smrg printf("Writing %d x %d stencil buffer to %s\n", w, h, filename); 5464a49301eSmrg write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE); 5474a49301eSmrg 5484a49301eSmrg _mesa_PopClientAttrib(); 5494a49301eSmrg 550cdc920a0Smrg free(buf); 551cdc920a0Smrg free(buf2); 5524a49301eSmrg} 5534a49301eSmrg 5544a49301eSmrg 5553464ebd5Sriastradhvoid 5563464ebd5Sriastradh_mesa_dump_image(const char *filename, const void *image, GLuint w, GLuint h, 5573464ebd5Sriastradh GLenum format, GLenum type) 5583464ebd5Sriastradh{ 5593464ebd5Sriastradh GLboolean invert = GL_TRUE; 5603464ebd5Sriastradh 5613464ebd5Sriastradh if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) { 5623464ebd5Sriastradh write_ppm(filename, image, w, h, 4, 0, 1, 2, invert); 5633464ebd5Sriastradh } 5643464ebd5Sriastradh else if (format == GL_BGRA && type == GL_UNSIGNED_BYTE) { 5653464ebd5Sriastradh write_ppm(filename, image, w, h, 4, 2, 1, 0, invert); 5663464ebd5Sriastradh } 5673464ebd5Sriastradh else if (format == GL_LUMINANCE_ALPHA && type == GL_UNSIGNED_BYTE) { 5683464ebd5Sriastradh write_ppm(filename, image, w, h, 2, 1, 0, 0, invert); 5693464ebd5Sriastradh } 5703464ebd5Sriastradh else { 5713464ebd5Sriastradh _mesa_problem(NULL, "Unsupported format/type in _mesa_dump_image()"); 5723464ebd5Sriastradh } 5733464ebd5Sriastradh} 5743464ebd5Sriastradh 5753464ebd5Sriastradh 5764a49301eSmrg/** 5774a49301eSmrg * Quick and dirty function to "print" a texture to stdout. 5784a49301eSmrg */ 5794a49301eSmrgvoid 5803464ebd5Sriastradh_mesa_print_texture(struct gl_context *ctx, const struct gl_texture_image *img) 5814a49301eSmrg{ 5824a49301eSmrg#if CHAN_TYPE != GL_UNSIGNED_BYTE 5834a49301eSmrg _mesa_problem(NULL, "PrintTexture not supported"); 5844a49301eSmrg#else 5854a49301eSmrg GLuint i, j, c; 5864a49301eSmrg const GLubyte *data = (const GLubyte *) img->Data; 5874a49301eSmrg 5884a49301eSmrg if (!data) { 589cdc920a0Smrg printf("No texture data\n"); 5904a49301eSmrg return; 5914a49301eSmrg } 5924a49301eSmrg 5934a49301eSmrg /* XXX add more formats or make into a new format utility function */ 5944a49301eSmrg switch (img->TexFormat) { 5954a49301eSmrg case MESA_FORMAT_A8: 5964a49301eSmrg case MESA_FORMAT_L8: 5974a49301eSmrg case MESA_FORMAT_I8: 5984a49301eSmrg case MESA_FORMAT_CI8: 5994a49301eSmrg c = 1; 6004a49301eSmrg break; 6014a49301eSmrg case MESA_FORMAT_AL88: 6024a49301eSmrg case MESA_FORMAT_AL88_REV: 6034a49301eSmrg c = 2; 6044a49301eSmrg break; 6054a49301eSmrg case MESA_FORMAT_RGB888: 6064a49301eSmrg case MESA_FORMAT_BGR888: 6074a49301eSmrg c = 3; 6084a49301eSmrg break; 6094a49301eSmrg case MESA_FORMAT_RGBA8888: 6104a49301eSmrg case MESA_FORMAT_ARGB8888: 6114a49301eSmrg c = 4; 6124a49301eSmrg break; 6134a49301eSmrg default: 6144a49301eSmrg _mesa_problem(NULL, "error in PrintTexture\n"); 6154a49301eSmrg return; 6164a49301eSmrg } 6174a49301eSmrg 6184a49301eSmrg for (i = 0; i < img->Height; i++) { 6194a49301eSmrg for (j = 0; j < img->Width; j++) { 6204a49301eSmrg if (c==1) 621cdc920a0Smrg printf("%02x ", data[0]); 6224a49301eSmrg else if (c==2) 623cdc920a0Smrg printf("%02x%02x ", data[0], data[1]); 6244a49301eSmrg else if (c==3) 625cdc920a0Smrg printf("%02x%02x%02x ", data[0], data[1], data[2]); 6264a49301eSmrg else if (c==4) 627cdc920a0Smrg printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); 6284a49301eSmrg data += (img->RowStride - img->Width) * c; 6294a49301eSmrg } 6304a49301eSmrg /* XXX use img->ImageStride here */ 631cdc920a0Smrg printf("\n"); 6324a49301eSmrg } 6334a49301eSmrg#endif 6344a49301eSmrg} 635