debug.c revision 848b8605
1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. 5848b8605Smrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the "Software"), 9848b8605Smrg * to deal in the Software without restriction, including without limitation 10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 12848b8605Smrg * Software is furnished to do so, subject to the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice shall be included 15848b8605Smrg * in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 24848b8605Smrg */ 25848b8605Smrg 26848b8605Smrg#include "mtypes.h" 27848b8605Smrg#include "attrib.h" 28848b8605Smrg#include "colormac.h" 29848b8605Smrg#include "enums.h" 30848b8605Smrg#include "formats.h" 31848b8605Smrg#include "hash.h" 32848b8605Smrg#include "imports.h" 33848b8605Smrg#include "debug.h" 34848b8605Smrg#include "get.h" 35848b8605Smrg#include "pixelstore.h" 36848b8605Smrg#include "readpix.h" 37848b8605Smrg#include "texobj.h" 38848b8605Smrg 39848b8605Smrg 40848b8605Smrgstatic const char * 41848b8605Smrgtex_target_name(GLenum tgt) 42848b8605Smrg{ 43848b8605Smrg static const struct { 44848b8605Smrg GLenum target; 45848b8605Smrg const char *name; 46848b8605Smrg } tex_targets[] = { 47848b8605Smrg { GL_TEXTURE_1D, "GL_TEXTURE_1D" }, 48848b8605Smrg { GL_TEXTURE_2D, "GL_TEXTURE_2D" }, 49848b8605Smrg { GL_TEXTURE_3D, "GL_TEXTURE_3D" }, 50848b8605Smrg { GL_TEXTURE_CUBE_MAP, "GL_TEXTURE_CUBE_MAP" }, 51848b8605Smrg { GL_TEXTURE_RECTANGLE, "GL_TEXTURE_RECTANGLE" }, 52848b8605Smrg { GL_TEXTURE_1D_ARRAY_EXT, "GL_TEXTURE_1D_ARRAY" }, 53848b8605Smrg { GL_TEXTURE_2D_ARRAY_EXT, "GL_TEXTURE_2D_ARRAY" }, 54848b8605Smrg { GL_TEXTURE_CUBE_MAP_ARRAY, "GL_TEXTURE_CUBE_MAP_ARRAY" }, 55848b8605Smrg { GL_TEXTURE_BUFFER, "GL_TEXTURE_BUFFER" }, 56848b8605Smrg { GL_TEXTURE_2D_MULTISAMPLE, "GL_TEXTURE_2D_MULTISAMPLE" }, 57848b8605Smrg { GL_TEXTURE_2D_MULTISAMPLE_ARRAY, "GL_TEXTURE_2D_MULTISAMPLE_ARRAY" }, 58848b8605Smrg { GL_TEXTURE_EXTERNAL_OES, "GL_TEXTURE_EXTERNAL_OES" } 59848b8605Smrg }; 60848b8605Smrg GLuint i; 61848b8605Smrg STATIC_ASSERT(Elements(tex_targets) == NUM_TEXTURE_TARGETS); 62848b8605Smrg for (i = 0; i < Elements(tex_targets); i++) { 63848b8605Smrg if (tex_targets[i].target == tgt) 64848b8605Smrg return tex_targets[i].name; 65848b8605Smrg } 66848b8605Smrg return "UNKNOWN TEX TARGET"; 67848b8605Smrg} 68848b8605Smrg 69848b8605Smrg 70848b8605Smrgvoid 71848b8605Smrg_mesa_print_state( const char *msg, GLuint state ) 72848b8605Smrg{ 73848b8605Smrg _mesa_debug(NULL, 74848b8605Smrg "%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", 75848b8605Smrg msg, 76848b8605Smrg state, 77848b8605Smrg (state & _NEW_MODELVIEW) ? "ctx->ModelView, " : "", 78848b8605Smrg (state & _NEW_PROJECTION) ? "ctx->Projection, " : "", 79848b8605Smrg (state & _NEW_TEXTURE_MATRIX) ? "ctx->TextureMatrix, " : "", 80848b8605Smrg (state & _NEW_COLOR) ? "ctx->Color, " : "", 81848b8605Smrg (state & _NEW_DEPTH) ? "ctx->Depth, " : "", 82848b8605Smrg (state & _NEW_EVAL) ? "ctx->Eval/EvalMap, " : "", 83848b8605Smrg (state & _NEW_FOG) ? "ctx->Fog, " : "", 84848b8605Smrg (state & _NEW_HINT) ? "ctx->Hint, " : "", 85848b8605Smrg (state & _NEW_LIGHT) ? "ctx->Light, " : "", 86848b8605Smrg (state & _NEW_LINE) ? "ctx->Line, " : "", 87848b8605Smrg (state & _NEW_PIXEL) ? "ctx->Pixel, " : "", 88848b8605Smrg (state & _NEW_POINT) ? "ctx->Point, " : "", 89848b8605Smrg (state & _NEW_POLYGON) ? "ctx->Polygon, " : "", 90848b8605Smrg (state & _NEW_POLYGONSTIPPLE) ? "ctx->PolygonStipple, " : "", 91848b8605Smrg (state & _NEW_SCISSOR) ? "ctx->Scissor, " : "", 92848b8605Smrg (state & _NEW_STENCIL) ? "ctx->Stencil, " : "", 93848b8605Smrg (state & _NEW_TEXTURE) ? "ctx->Texture, " : "", 94848b8605Smrg (state & _NEW_TRANSFORM) ? "ctx->Transform, " : "", 95848b8605Smrg (state & _NEW_VIEWPORT) ? "ctx->Viewport, " : "", 96848b8605Smrg (state & _NEW_ARRAY) ? "ctx->Array, " : "", 97848b8605Smrg (state & _NEW_RENDERMODE) ? "ctx->RenderMode, " : "", 98848b8605Smrg (state & _NEW_BUFFERS) ? "ctx->Visual, ctx->DrawBuffer,, " : ""); 99848b8605Smrg} 100848b8605Smrg 101848b8605Smrg 102848b8605Smrg 103848b8605Smrg/** 104848b8605Smrg * Print information about this Mesa version and build options. 105848b8605Smrg */ 106848b8605Smrgvoid _mesa_print_info( struct gl_context *ctx ) 107848b8605Smrg{ 108848b8605Smrg _mesa_debug(NULL, "Mesa GL_VERSION = %s\n", 109848b8605Smrg (char *) _mesa_GetString(GL_VERSION)); 110848b8605Smrg _mesa_debug(NULL, "Mesa GL_RENDERER = %s\n", 111848b8605Smrg (char *) _mesa_GetString(GL_RENDERER)); 112848b8605Smrg _mesa_debug(NULL, "Mesa GL_VENDOR = %s\n", 113848b8605Smrg (char *) _mesa_GetString(GL_VENDOR)); 114848b8605Smrg 115848b8605Smrg /* use ctx as GL_EXTENSIONS will not work on 3.0 or higher 116848b8605Smrg * core contexts. 117848b8605Smrg */ 118848b8605Smrg _mesa_debug(NULL, "Mesa GL_EXTENSIONS = %s\n", ctx->Extensions.String); 119848b8605Smrg 120848b8605Smrg#if defined(THREADS) 121848b8605Smrg _mesa_debug(NULL, "Mesa thread-safe: YES\n"); 122848b8605Smrg#else 123848b8605Smrg _mesa_debug(NULL, "Mesa thread-safe: NO\n"); 124848b8605Smrg#endif 125848b8605Smrg#if defined(USE_X86_ASM) 126848b8605Smrg _mesa_debug(NULL, "Mesa x86-optimized: YES\n"); 127848b8605Smrg#else 128848b8605Smrg _mesa_debug(NULL, "Mesa x86-optimized: NO\n"); 129848b8605Smrg#endif 130848b8605Smrg#if defined(USE_SPARC_ASM) 131848b8605Smrg _mesa_debug(NULL, "Mesa sparc-optimized: YES\n"); 132848b8605Smrg#else 133848b8605Smrg _mesa_debug(NULL, "Mesa sparc-optimized: NO\n"); 134848b8605Smrg#endif 135848b8605Smrg} 136848b8605Smrg 137848b8605Smrg 138848b8605Smrg/** 139848b8605Smrg * Set verbose logging flags. When these flags are set, GL API calls 140848b8605Smrg * in the various categories will be printed to stderr. 141848b8605Smrg * \param str a comma-separated list of keywords 142848b8605Smrg */ 143848b8605Smrgstatic void 144848b8605Smrgset_verbose_flags(const char *str) 145848b8605Smrg{ 146848b8605Smrg#ifdef DEBUG 147848b8605Smrg struct option { 148848b8605Smrg const char *name; 149848b8605Smrg GLbitfield flag; 150848b8605Smrg }; 151848b8605Smrg static const struct option opts[] = { 152848b8605Smrg { "varray", VERBOSE_VARRAY }, 153848b8605Smrg { "tex", VERBOSE_TEXTURE }, 154848b8605Smrg { "mat", VERBOSE_MATERIAL }, 155848b8605Smrg { "pipe", VERBOSE_PIPELINE }, 156848b8605Smrg { "driver", VERBOSE_DRIVER }, 157848b8605Smrg { "state", VERBOSE_STATE }, 158848b8605Smrg { "api", VERBOSE_API }, 159848b8605Smrg { "list", VERBOSE_DISPLAY_LIST }, 160848b8605Smrg { "lighting", VERBOSE_LIGHTING }, 161848b8605Smrg { "disassem", VERBOSE_DISASSEM }, 162848b8605Smrg { "draw", VERBOSE_DRAW }, 163848b8605Smrg { "swap", VERBOSE_SWAPBUFFERS } 164848b8605Smrg }; 165848b8605Smrg GLuint i; 166848b8605Smrg 167848b8605Smrg if (!str) 168848b8605Smrg return; 169848b8605Smrg 170848b8605Smrg MESA_VERBOSE = 0x0; 171848b8605Smrg for (i = 0; i < Elements(opts); i++) { 172848b8605Smrg if (strstr(str, opts[i].name) || strcmp(str, "all") == 0) 173848b8605Smrg MESA_VERBOSE |= opts[i].flag; 174848b8605Smrg } 175848b8605Smrg#endif 176848b8605Smrg} 177848b8605Smrg 178848b8605Smrg 179848b8605Smrg/** 180848b8605Smrg * Set debugging flags. When these flags are set, Mesa will do additional 181848b8605Smrg * debug checks or actions. 182848b8605Smrg * \param str a comma-separated list of keywords 183848b8605Smrg */ 184848b8605Smrgstatic void 185848b8605Smrgset_debug_flags(const char *str) 186848b8605Smrg{ 187848b8605Smrg#ifdef DEBUG 188848b8605Smrg struct option { 189848b8605Smrg const char *name; 190848b8605Smrg GLbitfield flag; 191848b8605Smrg }; 192848b8605Smrg static const struct option opts[] = { 193848b8605Smrg { "silent", DEBUG_SILENT }, /* turn off debug messages */ 194848b8605Smrg { "flush", DEBUG_ALWAYS_FLUSH }, /* flush after each drawing command */ 195848b8605Smrg { "incomplete_tex", DEBUG_INCOMPLETE_TEXTURE }, 196848b8605Smrg { "incomplete_fbo", DEBUG_INCOMPLETE_FBO } 197848b8605Smrg }; 198848b8605Smrg GLuint i; 199848b8605Smrg 200848b8605Smrg if (!str) 201848b8605Smrg return; 202848b8605Smrg 203848b8605Smrg MESA_DEBUG_FLAGS = 0x0; 204848b8605Smrg for (i = 0; i < Elements(opts); i++) { 205848b8605Smrg if (strstr(str, opts[i].name)) 206848b8605Smrg MESA_DEBUG_FLAGS |= opts[i].flag; 207848b8605Smrg } 208848b8605Smrg#endif 209848b8605Smrg} 210848b8605Smrg 211848b8605Smrg 212848b8605Smrg/** 213848b8605Smrg * Initialize debugging variables from env vars. 214848b8605Smrg */ 215848b8605Smrgvoid 216848b8605Smrg_mesa_init_debug( struct gl_context *ctx ) 217848b8605Smrg{ 218848b8605Smrg set_debug_flags(_mesa_getenv("MESA_DEBUG")); 219848b8605Smrg set_verbose_flags(_mesa_getenv("MESA_VERBOSE")); 220848b8605Smrg} 221848b8605Smrg 222848b8605Smrg 223848b8605Smrg/* 224848b8605Smrg * Write ppm file 225848b8605Smrg */ 226848b8605Smrgstatic void 227848b8605Smrgwrite_ppm(const char *filename, const GLubyte *buffer, int width, int height, 228848b8605Smrg int comps, int rcomp, int gcomp, int bcomp, GLboolean invert) 229848b8605Smrg{ 230848b8605Smrg FILE *f = fopen( filename, "w" ); 231848b8605Smrg if (f) { 232848b8605Smrg int x, y; 233848b8605Smrg const GLubyte *ptr = buffer; 234848b8605Smrg fprintf(f,"P6\n"); 235848b8605Smrg fprintf(f,"# ppm-file created by osdemo.c\n"); 236848b8605Smrg fprintf(f,"%i %i\n", width,height); 237848b8605Smrg fprintf(f,"255\n"); 238848b8605Smrg fclose(f); 239848b8605Smrg f = fopen( filename, "ab" ); /* reopen in binary append mode */ 240848b8605Smrg for (y=0; y < height; y++) { 241848b8605Smrg for (x = 0; x < width; x++) { 242848b8605Smrg int yy = invert ? (height - 1 - y) : y; 243848b8605Smrg int i = (yy * width + x) * comps; 244848b8605Smrg fputc(ptr[i+rcomp], f); /* write red */ 245848b8605Smrg fputc(ptr[i+gcomp], f); /* write green */ 246848b8605Smrg fputc(ptr[i+bcomp], f); /* write blue */ 247848b8605Smrg } 248848b8605Smrg } 249848b8605Smrg fclose(f); 250848b8605Smrg } 251848b8605Smrg else { 252848b8605Smrg fprintf(stderr, "Unable to create %s in write_ppm()\n", filename); 253848b8605Smrg } 254848b8605Smrg} 255848b8605Smrg 256848b8605Smrg 257848b8605Smrg/** 258848b8605Smrg * Write a texture image to a ppm file. 259848b8605Smrg * \param face cube face in [0,5] 260848b8605Smrg * \param level mipmap level 261848b8605Smrg */ 262848b8605Smrgstatic void 263848b8605Smrgwrite_texture_image(struct gl_texture_object *texObj, 264848b8605Smrg GLuint face, GLuint level) 265848b8605Smrg{ 266848b8605Smrg struct gl_texture_image *img = texObj->Image[face][level]; 267848b8605Smrg if (img) { 268848b8605Smrg GET_CURRENT_CONTEXT(ctx); 269848b8605Smrg struct gl_pixelstore_attrib store; 270848b8605Smrg GLubyte *buffer; 271848b8605Smrg char s[100]; 272848b8605Smrg 273848b8605Smrg buffer = malloc(img->Width * img->Height 274848b8605Smrg * img->Depth * 4); 275848b8605Smrg 276848b8605Smrg store = ctx->Pack; /* save */ 277848b8605Smrg ctx->Pack = ctx->DefaultPacking; 278848b8605Smrg 279848b8605Smrg ctx->Driver.GetTexImage(ctx, GL_RGBA, GL_UNSIGNED_BYTE, buffer, img); 280848b8605Smrg 281848b8605Smrg /* make filename */ 282848b8605Smrg _mesa_snprintf(s, sizeof(s), "/tmp/tex%u.l%u.f%u.ppm", texObj->Name, level, face); 283848b8605Smrg 284848b8605Smrg printf(" Writing image level %u to %s\n", level, s); 285848b8605Smrg write_ppm(s, buffer, img->Width, img->Height, 4, 0, 1, 2, GL_FALSE); 286848b8605Smrg 287848b8605Smrg ctx->Pack = store; /* restore */ 288848b8605Smrg 289848b8605Smrg free(buffer); 290848b8605Smrg } 291848b8605Smrg} 292848b8605Smrg 293848b8605Smrg 294848b8605Smrg/** 295848b8605Smrg * Write renderbuffer image to a ppm file. 296848b8605Smrg */ 297848b8605Smrgvoid 298848b8605Smrg_mesa_write_renderbuffer_image(const struct gl_renderbuffer *rb) 299848b8605Smrg{ 300848b8605Smrg GET_CURRENT_CONTEXT(ctx); 301848b8605Smrg GLubyte *buffer; 302848b8605Smrg char s[100]; 303848b8605Smrg GLenum format, type; 304848b8605Smrg 305848b8605Smrg if (rb->_BaseFormat == GL_RGB || 306848b8605Smrg rb->_BaseFormat == GL_RGBA) { 307848b8605Smrg format = GL_RGBA; 308848b8605Smrg type = GL_UNSIGNED_BYTE; 309848b8605Smrg } 310848b8605Smrg else if (rb->_BaseFormat == GL_DEPTH_STENCIL) { 311848b8605Smrg format = GL_DEPTH_STENCIL; 312848b8605Smrg type = GL_UNSIGNED_INT_24_8; 313848b8605Smrg } 314848b8605Smrg else { 315848b8605Smrg _mesa_debug(NULL, 316848b8605Smrg "Unsupported BaseFormat 0x%x in " 317848b8605Smrg "_mesa_write_renderbuffer_image()\n", 318848b8605Smrg rb->_BaseFormat); 319848b8605Smrg return; 320848b8605Smrg } 321848b8605Smrg 322848b8605Smrg buffer = malloc(rb->Width * rb->Height * 4); 323848b8605Smrg 324848b8605Smrg ctx->Driver.ReadPixels(ctx, 0, 0, rb->Width, rb->Height, 325848b8605Smrg format, type, &ctx->DefaultPacking, buffer); 326848b8605Smrg 327848b8605Smrg /* make filename */ 328848b8605Smrg _mesa_snprintf(s, sizeof(s), "/tmp/renderbuffer%u.ppm", rb->Name); 329848b8605Smrg _mesa_snprintf(s, sizeof(s), "C:\\renderbuffer%u.ppm", rb->Name); 330848b8605Smrg 331848b8605Smrg printf(" Writing renderbuffer image to %s\n", s); 332848b8605Smrg 333848b8605Smrg _mesa_debug(NULL, " Writing renderbuffer image to %s\n", s); 334848b8605Smrg 335848b8605Smrg write_ppm(s, buffer, rb->Width, rb->Height, 4, 0, 1, 2, GL_TRUE); 336848b8605Smrg 337848b8605Smrg free(buffer); 338848b8605Smrg} 339848b8605Smrg 340848b8605Smrg 341848b8605Smrg/** How many texture images (mipmap levels, faces) to write to files */ 342848b8605Smrg#define WRITE_NONE 0 343848b8605Smrg#define WRITE_ONE 1 344848b8605Smrg#define WRITE_ALL 2 345848b8605Smrg 346848b8605Smrgstatic GLuint WriteImages; 347848b8605Smrg 348848b8605Smrg 349848b8605Smrgstatic void 350848b8605Smrgdump_texture(struct gl_texture_object *texObj, GLuint writeImages) 351848b8605Smrg{ 352848b8605Smrg const GLuint numFaces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1; 353848b8605Smrg GLboolean written = GL_FALSE; 354848b8605Smrg GLuint i, j; 355848b8605Smrg 356848b8605Smrg printf("Texture %u\n", texObj->Name); 357848b8605Smrg printf(" Target %s\n", tex_target_name(texObj->Target)); 358848b8605Smrg for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { 359848b8605Smrg for (j = 0; j < numFaces; j++) { 360848b8605Smrg struct gl_texture_image *texImg = texObj->Image[j][i]; 361848b8605Smrg if (texImg) { 362848b8605Smrg printf(" Face %u level %u: %d x %d x %d, format %s\n", 363848b8605Smrg j, i, 364848b8605Smrg texImg->Width, texImg->Height, texImg->Depth, 365848b8605Smrg _mesa_get_format_name(texImg->TexFormat)); 366848b8605Smrg if (writeImages == WRITE_ALL || 367848b8605Smrg (writeImages == WRITE_ONE && !written)) { 368848b8605Smrg write_texture_image(texObj, j, i); 369848b8605Smrg written = GL_TRUE; 370848b8605Smrg } 371848b8605Smrg } 372848b8605Smrg } 373848b8605Smrg } 374848b8605Smrg} 375848b8605Smrg 376848b8605Smrg 377848b8605Smrg/** 378848b8605Smrg * Dump a single texture. 379848b8605Smrg */ 380848b8605Smrgvoid 381848b8605Smrg_mesa_dump_texture(GLuint texture, GLuint writeImages) 382848b8605Smrg{ 383848b8605Smrg GET_CURRENT_CONTEXT(ctx); 384848b8605Smrg struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture); 385848b8605Smrg if (texObj) { 386848b8605Smrg dump_texture(texObj, writeImages); 387848b8605Smrg } 388848b8605Smrg} 389848b8605Smrg 390848b8605Smrg 391848b8605Smrgstatic void 392848b8605Smrgdump_texture_cb(GLuint id, void *data, void *userData) 393848b8605Smrg{ 394848b8605Smrg struct gl_texture_object *texObj = (struct gl_texture_object *) data; 395848b8605Smrg (void) userData; 396848b8605Smrg dump_texture(texObj, WriteImages); 397848b8605Smrg} 398848b8605Smrg 399848b8605Smrg 400848b8605Smrg/** 401848b8605Smrg * Print basic info about all texture objext to stdout. 402848b8605Smrg * If dumpImages is true, write PPM of level[0] image to a file. 403848b8605Smrg */ 404848b8605Smrgvoid 405848b8605Smrg_mesa_dump_textures(GLuint writeImages) 406848b8605Smrg{ 407848b8605Smrg GET_CURRENT_CONTEXT(ctx); 408848b8605Smrg WriteImages = writeImages; 409848b8605Smrg _mesa_HashWalk(ctx->Shared->TexObjects, dump_texture_cb, ctx); 410848b8605Smrg} 411848b8605Smrg 412848b8605Smrg 413848b8605Smrgstatic void 414848b8605Smrgdump_renderbuffer(const struct gl_renderbuffer *rb, GLboolean writeImage) 415848b8605Smrg{ 416848b8605Smrg printf("Renderbuffer %u: %u x %u IntFormat = %s\n", 417848b8605Smrg rb->Name, rb->Width, rb->Height, 418848b8605Smrg _mesa_lookup_enum_by_nr(rb->InternalFormat)); 419848b8605Smrg if (writeImage) { 420848b8605Smrg _mesa_write_renderbuffer_image(rb); 421848b8605Smrg } 422848b8605Smrg} 423848b8605Smrg 424848b8605Smrg 425848b8605Smrgstatic void 426848b8605Smrgdump_renderbuffer_cb(GLuint id, void *data, void *userData) 427848b8605Smrg{ 428848b8605Smrg const struct gl_renderbuffer *rb = (const struct gl_renderbuffer *) data; 429848b8605Smrg (void) userData; 430848b8605Smrg dump_renderbuffer(rb, WriteImages); 431848b8605Smrg} 432848b8605Smrg 433848b8605Smrg 434848b8605Smrg/** 435848b8605Smrg * Print basic info about all renderbuffers to stdout. 436848b8605Smrg * If dumpImages is true, write PPM of level[0] image to a file. 437848b8605Smrg */ 438848b8605Smrgvoid 439848b8605Smrg_mesa_dump_renderbuffers(GLboolean writeImages) 440848b8605Smrg{ 441848b8605Smrg GET_CURRENT_CONTEXT(ctx); 442848b8605Smrg WriteImages = writeImages; 443848b8605Smrg _mesa_HashWalk(ctx->Shared->RenderBuffers, dump_renderbuffer_cb, ctx); 444848b8605Smrg} 445848b8605Smrg 446848b8605Smrg 447848b8605Smrg 448848b8605Smrgvoid 449848b8605Smrg_mesa_dump_color_buffer(const char *filename) 450848b8605Smrg{ 451848b8605Smrg GET_CURRENT_CONTEXT(ctx); 452848b8605Smrg const GLuint w = ctx->DrawBuffer->Width; 453848b8605Smrg const GLuint h = ctx->DrawBuffer->Height; 454848b8605Smrg GLubyte *buf; 455848b8605Smrg 456848b8605Smrg buf = malloc(w * h * 4); 457848b8605Smrg 458848b8605Smrg _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); 459848b8605Smrg _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1); 460848b8605Smrg _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); 461848b8605Smrg 462848b8605Smrg _mesa_ReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buf); 463848b8605Smrg 464848b8605Smrg printf("ReadBuffer %p 0x%x DrawBuffer %p 0x%x\n", 465848b8605Smrg (void *) ctx->ReadBuffer->_ColorReadBuffer, 466848b8605Smrg ctx->ReadBuffer->ColorReadBuffer, 467848b8605Smrg (void *) ctx->DrawBuffer->_ColorDrawBuffers[0], 468848b8605Smrg ctx->DrawBuffer->ColorDrawBuffer[0]); 469848b8605Smrg printf("Writing %d x %d color buffer to %s\n", w, h, filename); 470848b8605Smrg write_ppm(filename, buf, w, h, 4, 0, 1, 2, GL_TRUE); 471848b8605Smrg 472848b8605Smrg _mesa_PopClientAttrib(); 473848b8605Smrg 474848b8605Smrg free(buf); 475848b8605Smrg} 476848b8605Smrg 477848b8605Smrg 478848b8605Smrgvoid 479848b8605Smrg_mesa_dump_depth_buffer(const char *filename) 480848b8605Smrg{ 481848b8605Smrg GET_CURRENT_CONTEXT(ctx); 482848b8605Smrg const GLuint w = ctx->DrawBuffer->Width; 483848b8605Smrg const GLuint h = ctx->DrawBuffer->Height; 484848b8605Smrg GLuint *buf; 485848b8605Smrg GLubyte *buf2; 486848b8605Smrg GLuint i; 487848b8605Smrg 488848b8605Smrg buf = malloc(w * h * 4); /* 4 bpp */ 489848b8605Smrg buf2 = malloc(w * h * 3); /* 3 bpp */ 490848b8605Smrg 491848b8605Smrg _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); 492848b8605Smrg _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1); 493848b8605Smrg _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); 494848b8605Smrg 495848b8605Smrg _mesa_ReadPixels(0, 0, w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buf); 496848b8605Smrg 497848b8605Smrg /* spread 24 bits of Z across R, G, B */ 498848b8605Smrg for (i = 0; i < w * h; i++) { 499848b8605Smrg buf2[i*3+0] = (buf[i] >> 24) & 0xff; 500848b8605Smrg buf2[i*3+1] = (buf[i] >> 16) & 0xff; 501848b8605Smrg buf2[i*3+2] = (buf[i] >> 8) & 0xff; 502848b8605Smrg } 503848b8605Smrg 504848b8605Smrg printf("Writing %d x %d depth buffer to %s\n", w, h, filename); 505848b8605Smrg write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE); 506848b8605Smrg 507848b8605Smrg _mesa_PopClientAttrib(); 508848b8605Smrg 509848b8605Smrg free(buf); 510848b8605Smrg free(buf2); 511848b8605Smrg} 512848b8605Smrg 513848b8605Smrg 514848b8605Smrgvoid 515848b8605Smrg_mesa_dump_stencil_buffer(const char *filename) 516848b8605Smrg{ 517848b8605Smrg GET_CURRENT_CONTEXT(ctx); 518848b8605Smrg const GLuint w = ctx->DrawBuffer->Width; 519848b8605Smrg const GLuint h = ctx->DrawBuffer->Height; 520848b8605Smrg GLubyte *buf; 521848b8605Smrg GLubyte *buf2; 522848b8605Smrg GLuint i; 523848b8605Smrg 524848b8605Smrg buf = malloc(w * h); /* 1 bpp */ 525848b8605Smrg buf2 = malloc(w * h * 3); /* 3 bpp */ 526848b8605Smrg 527848b8605Smrg _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); 528848b8605Smrg _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1); 529848b8605Smrg _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); 530848b8605Smrg 531848b8605Smrg _mesa_ReadPixels(0, 0, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf); 532848b8605Smrg 533848b8605Smrg for (i = 0; i < w * h; i++) { 534848b8605Smrg buf2[i*3+0] = buf[i]; 535848b8605Smrg buf2[i*3+1] = (buf[i] & 127) * 2; 536848b8605Smrg buf2[i*3+2] = (buf[i] - 128) * 2; 537848b8605Smrg } 538848b8605Smrg 539848b8605Smrg printf("Writing %d x %d stencil buffer to %s\n", w, h, filename); 540848b8605Smrg write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE); 541848b8605Smrg 542848b8605Smrg _mesa_PopClientAttrib(); 543848b8605Smrg 544848b8605Smrg free(buf); 545848b8605Smrg free(buf2); 546848b8605Smrg} 547848b8605Smrg 548848b8605Smrg 549848b8605Smrgvoid 550848b8605Smrg_mesa_dump_image(const char *filename, const void *image, GLuint w, GLuint h, 551848b8605Smrg GLenum format, GLenum type) 552848b8605Smrg{ 553848b8605Smrg GLboolean invert = GL_TRUE; 554848b8605Smrg 555848b8605Smrg if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) { 556848b8605Smrg write_ppm(filename, image, w, h, 4, 0, 1, 2, invert); 557848b8605Smrg } 558848b8605Smrg else if (format == GL_BGRA && type == GL_UNSIGNED_BYTE) { 559848b8605Smrg write_ppm(filename, image, w, h, 4, 2, 1, 0, invert); 560848b8605Smrg } 561848b8605Smrg else if (format == GL_LUMINANCE_ALPHA && type == GL_UNSIGNED_BYTE) { 562848b8605Smrg write_ppm(filename, image, w, h, 2, 1, 0, 0, invert); 563848b8605Smrg } 564848b8605Smrg else if (format == GL_RED && type == GL_UNSIGNED_BYTE) { 565848b8605Smrg write_ppm(filename, image, w, h, 1, 0, 0, 0, invert); 566848b8605Smrg } 567848b8605Smrg else if (format == GL_RGBA && type == GL_FLOAT) { 568848b8605Smrg /* convert floats to ubyte */ 569848b8605Smrg GLubyte *buf = malloc(w * h * 4 * sizeof(GLubyte)); 570848b8605Smrg const GLfloat *f = (const GLfloat *) image; 571848b8605Smrg GLuint i; 572848b8605Smrg for (i = 0; i < w * h * 4; i++) { 573848b8605Smrg UNCLAMPED_FLOAT_TO_UBYTE(buf[i], f[i]); 574848b8605Smrg } 575848b8605Smrg write_ppm(filename, buf, w, h, 4, 0, 1, 2, invert); 576848b8605Smrg free(buf); 577848b8605Smrg } 578848b8605Smrg else if (format == GL_RED && type == GL_FLOAT) { 579848b8605Smrg /* convert floats to ubyte */ 580848b8605Smrg GLubyte *buf = malloc(w * h * sizeof(GLubyte)); 581848b8605Smrg const GLfloat *f = (const GLfloat *) image; 582848b8605Smrg GLuint i; 583848b8605Smrg for (i = 0; i < w * h; i++) { 584848b8605Smrg UNCLAMPED_FLOAT_TO_UBYTE(buf[i], f[i]); 585848b8605Smrg } 586848b8605Smrg write_ppm(filename, buf, w, h, 1, 0, 0, 0, invert); 587848b8605Smrg free(buf); 588848b8605Smrg } 589848b8605Smrg else { 590848b8605Smrg _mesa_problem(NULL, 591848b8605Smrg "Unsupported format 0x%x / type 0x%x in _mesa_dump_image()", 592848b8605Smrg format, type); 593848b8605Smrg } 594848b8605Smrg} 595848b8605Smrg 596848b8605Smrg 597848b8605Smrg/** 598848b8605Smrg * Quick and dirty function to "print" a texture to stdout. 599848b8605Smrg */ 600848b8605Smrgvoid 601848b8605Smrg_mesa_print_texture(struct gl_context *ctx, struct gl_texture_image *img) 602848b8605Smrg{ 603848b8605Smrg const GLint slice = 0; 604848b8605Smrg GLint srcRowStride; 605848b8605Smrg GLuint i, j, c; 606848b8605Smrg GLubyte *data; 607848b8605Smrg 608848b8605Smrg ctx->Driver.MapTextureImage(ctx, img, slice, 609848b8605Smrg 0, 0, img->Width, img->Height, GL_MAP_READ_BIT, 610848b8605Smrg &data, &srcRowStride); 611848b8605Smrg 612848b8605Smrg if (!data) { 613848b8605Smrg printf("No texture data\n"); 614848b8605Smrg } 615848b8605Smrg else { 616848b8605Smrg /* XXX add more formats or make into a new format utility function */ 617848b8605Smrg switch (img->TexFormat) { 618848b8605Smrg case MESA_FORMAT_A_UNORM8: 619848b8605Smrg case MESA_FORMAT_L_UNORM8: 620848b8605Smrg case MESA_FORMAT_I_UNORM8: 621848b8605Smrg c = 1; 622848b8605Smrg break; 623848b8605Smrg case MESA_FORMAT_L8A8_UNORM: 624848b8605Smrg case MESA_FORMAT_A8L8_UNORM: 625848b8605Smrg c = 2; 626848b8605Smrg break; 627848b8605Smrg case MESA_FORMAT_BGR_UNORM8: 628848b8605Smrg case MESA_FORMAT_RGB_UNORM8: 629848b8605Smrg c = 3; 630848b8605Smrg break; 631848b8605Smrg case MESA_FORMAT_A8B8G8R8_UNORM: 632848b8605Smrg case MESA_FORMAT_B8G8R8A8_UNORM: 633848b8605Smrg c = 4; 634848b8605Smrg break; 635848b8605Smrg default: 636848b8605Smrg _mesa_problem(NULL, "error in PrintTexture\n"); 637848b8605Smrg return; 638848b8605Smrg } 639848b8605Smrg 640848b8605Smrg for (i = 0; i < img->Height; i++) { 641848b8605Smrg for (j = 0; j < img->Width; j++) { 642848b8605Smrg if (c==1) 643848b8605Smrg printf("%02x ", data[0]); 644848b8605Smrg else if (c==2) 645848b8605Smrg printf("%02x%02x ", data[0], data[1]); 646848b8605Smrg else if (c==3) 647848b8605Smrg printf("%02x%02x%02x ", data[0], data[1], data[2]); 648848b8605Smrg else if (c==4) 649848b8605Smrg printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); 650848b8605Smrg data += (srcRowStride - img->Width) * c; 651848b8605Smrg } 652848b8605Smrg /* XXX use img->ImageStride here */ 653848b8605Smrg printf("\n"); 654848b8605Smrg 655848b8605Smrg } 656848b8605Smrg } 657848b8605Smrg 658848b8605Smrg ctx->Driver.UnmapTextureImage(ctx, img, slice); 659848b8605Smrg} 660