OSDN Git Service

Merge branch 'mesa_7_5_branch'
[android-x86/external-mesa.git] / src / mesa / main / debug.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  6.5
4  *
5  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
6  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 #include "mtypes.h"
27 #include "attrib.h"
28 #include "colormac.h"
29 #include "context.h"
30 #include "hash.h"
31 #include "imports.h"
32 #include "debug.h"
33 #include "get.h"
34 #include "pixelstore.h"
35 #include "readpix.h"
36 #include "texobj.h"
37 #include "texformat.h"
38
39
40 /**
41  * Primitive names
42  */
43 const char *_mesa_prim_name[GL_POLYGON+4] = {
44    "GL_POINTS",
45    "GL_LINES",
46    "GL_LINE_LOOP",
47    "GL_LINE_STRIP",
48    "GL_TRIANGLES",
49    "GL_TRIANGLE_STRIP",
50    "GL_TRIANGLE_FAN",
51    "GL_QUADS",
52    "GL_QUAD_STRIP",
53    "GL_POLYGON",
54    "outside begin/end",
55    "inside unkown primitive",
56    "unknown state"
57 };
58
59 void
60 _mesa_print_state( const char *msg, GLuint state )
61 {
62    _mesa_debug(NULL,
63            "%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",
64            msg,
65            state,
66            (state & _NEW_MODELVIEW)       ? "ctx->ModelView, " : "",
67            (state & _NEW_PROJECTION)      ? "ctx->Projection, " : "",
68            (state & _NEW_TEXTURE_MATRIX)  ? "ctx->TextureMatrix, " : "",
69            (state & _NEW_COLOR_MATRIX)    ? "ctx->ColorMatrix, " : "",
70            (state & _NEW_ACCUM)           ? "ctx->Accum, " : "",
71            (state & _NEW_COLOR)           ? "ctx->Color, " : "",
72            (state & _NEW_DEPTH)           ? "ctx->Depth, " : "",
73            (state & _NEW_EVAL)            ? "ctx->Eval/EvalMap, " : "",
74            (state & _NEW_FOG)             ? "ctx->Fog, " : "",
75            (state & _NEW_HINT)            ? "ctx->Hint, " : "",
76            (state & _NEW_LIGHT)           ? "ctx->Light, " : "",
77            (state & _NEW_LINE)            ? "ctx->Line, " : "",
78            (state & _NEW_PIXEL)           ? "ctx->Pixel, " : "",
79            (state & _NEW_POINT)           ? "ctx->Point, " : "",
80            (state & _NEW_POLYGON)         ? "ctx->Polygon, " : "",
81            (state & _NEW_POLYGONSTIPPLE)  ? "ctx->PolygonStipple, " : "",
82            (state & _NEW_SCISSOR)         ? "ctx->Scissor, " : "",
83            (state & _NEW_TEXTURE)         ? "ctx->Texture, " : "",
84            (state & _NEW_TRANSFORM)       ? "ctx->Transform, " : "",
85            (state & _NEW_VIEWPORT)        ? "ctx->Viewport, " : "",
86            (state & _NEW_PACKUNPACK)      ? "ctx->Pack/Unpack, " : "",
87            (state & _NEW_ARRAY)           ? "ctx->Array, " : "",
88            (state & _NEW_RENDERMODE)      ? "ctx->RenderMode, " : "",
89            (state & _NEW_BUFFERS)         ? "ctx->Visual, ctx->DrawBuffer,, " : "");
90 }
91
92
93
94 void
95 _mesa_print_tri_caps( const char *name, GLuint flags )
96 {
97    _mesa_debug(NULL,
98            "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
99            name,
100            flags,
101            (flags & DD_FLATSHADE)           ? "flat-shade, " : "",
102            (flags & DD_SEPARATE_SPECULAR)   ? "separate-specular, " : "",
103            (flags & DD_TRI_LIGHT_TWOSIDE)   ? "tri-light-twoside, " : "",
104            (flags & DD_TRI_TWOSTENCIL)      ? "tri-twostencil, " : "",
105            (flags & DD_TRI_UNFILLED)        ? "tri-unfilled, " : "",
106            (flags & DD_TRI_STIPPLE)         ? "tri-stipple, " : "",
107            (flags & DD_TRI_OFFSET)          ? "tri-offset, " : "",
108            (flags & DD_TRI_SMOOTH)          ? "tri-smooth, " : "",
109            (flags & DD_LINE_SMOOTH)         ? "line-smooth, " : "",
110            (flags & DD_LINE_STIPPLE)        ? "line-stipple, " : "",
111            (flags & DD_LINE_WIDTH)          ? "line-wide, " : "",
112            (flags & DD_POINT_SMOOTH)        ? "point-smooth, " : "",
113            (flags & DD_POINT_SIZE)          ? "point-size, " : "",
114            (flags & DD_POINT_ATTEN)         ? "point-atten, " : "",
115            (flags & DD_TRI_CULL_FRONT_BACK) ? "cull-all, " : ""
116       );
117 }
118
119
120 /**
121  * Print information about this Mesa version and build options.
122  */
123 void _mesa_print_info( void )
124 {
125    _mesa_debug(NULL, "Mesa GL_VERSION = %s\n",
126            (char *) _mesa_GetString(GL_VERSION));
127    _mesa_debug(NULL, "Mesa GL_RENDERER = %s\n",
128            (char *) _mesa_GetString(GL_RENDERER));
129    _mesa_debug(NULL, "Mesa GL_VENDOR = %s\n",
130            (char *) _mesa_GetString(GL_VENDOR));
131    _mesa_debug(NULL, "Mesa GL_EXTENSIONS = %s\n",
132            (char *) _mesa_GetString(GL_EXTENSIONS));
133 #if defined(THREADS)
134    _mesa_debug(NULL, "Mesa thread-safe: YES\n");
135 #else
136    _mesa_debug(NULL, "Mesa thread-safe: NO\n");
137 #endif
138 #if defined(USE_X86_ASM)
139    _mesa_debug(NULL, "Mesa x86-optimized: YES\n");
140 #else
141    _mesa_debug(NULL, "Mesa x86-optimized: NO\n");
142 #endif
143 #if defined(USE_SPARC_ASM)
144    _mesa_debug(NULL, "Mesa sparc-optimized: YES\n");
145 #else
146    _mesa_debug(NULL, "Mesa sparc-optimized: NO\n");
147 #endif
148 }
149
150
151 /**
152  * Set the debugging flags.
153  *
154  * \param debug debug string
155  *
156  * If compiled with debugging support then search for keywords in \p debug and
157  * enables the verbose debug output of the respective feature.
158  */
159 static void add_debug_flags( const char *debug )
160 {
161 #ifdef DEBUG
162    struct debug_option {
163       const char *name;
164       GLbitfield flag;
165    };
166    static const struct debug_option debug_opt[] = {
167       { "varray",    VERBOSE_VARRAY },
168       { "tex",       VERBOSE_TEXTURE },
169       { "imm",       VERBOSE_IMMEDIATE },
170       { "pipe",      VERBOSE_PIPELINE },
171       { "driver",    VERBOSE_DRIVER },
172       { "state",     VERBOSE_STATE },
173       { "api",       VERBOSE_API },
174       { "list",      VERBOSE_DISPLAY_LIST },
175       { "lighting",  VERBOSE_LIGHTING },
176       { "disassem",  VERBOSE_DISASSEM }
177    };
178    GLuint i;
179
180    MESA_VERBOSE = 0x0;
181    for (i = 0; i < Elements(debug_opt); i++) {
182       if (_mesa_strstr(debug, debug_opt[i].name))
183          MESA_VERBOSE |= debug_opt[i].flag;
184    }
185
186    /* Debug flag:
187     */
188    if (_mesa_strstr(debug, "flush")) 
189       MESA_DEBUG_FLAGS |= DEBUG_ALWAYS_FLUSH;
190
191 #if defined(_FPU_GETCW) && defined(_FPU_SETCW)
192    if (_mesa_strstr(debug, "fpexceptions")) {
193       /* raise FP exceptions */
194       fpu_control_t mask;
195       _FPU_GETCW(mask);
196       mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM
197                 | _FPU_MASK_OM | _FPU_MASK_UM);
198       _FPU_SETCW(mask);
199    }
200 #endif
201
202 #else
203    (void) debug;
204 #endif
205 }
206
207
208 void 
209 _mesa_init_debug( GLcontext *ctx )
210 {
211    char *c;
212
213    /* Dither disable */
214    ctx->NoDither = _mesa_getenv("MESA_NO_DITHER") ? GL_TRUE : GL_FALSE;
215    if (ctx->NoDither) {
216       if (_mesa_getenv("MESA_DEBUG")) {
217          _mesa_debug(ctx, "MESA_NO_DITHER set - dithering disabled\n");
218       }
219       ctx->Color.DitherFlag = GL_FALSE;
220    }
221
222    c = _mesa_getenv("MESA_DEBUG");
223    if (c)
224       add_debug_flags(c);
225
226    c = _mesa_getenv("MESA_VERBOSE");
227    if (c)
228       add_debug_flags(c);
229 }
230
231
232 /*
233  * Write ppm file
234  */
235 static void
236 write_ppm(const char *filename, const GLubyte *buffer, int width, int height,
237           int comps, int rcomp, int gcomp, int bcomp)
238 {
239    FILE *f = fopen( filename, "w" );
240    if (f) {
241       int i, x, y;
242       const GLubyte *ptr = buffer;
243       fprintf(f,"P6\n");
244       fprintf(f,"# ppm-file created by osdemo.c\n");
245       fprintf(f,"%i %i\n", width,height);
246       fprintf(f,"255\n");
247       fclose(f);
248       f = fopen( filename, "ab" );  /* reopen in binary append mode */
249       for (y=height-1; y>=0; y--) {
250          for (x=0; x<width; x++) {
251             i = (y*width + x) * comps;
252             fputc(ptr[i+rcomp], f);   /* write red */
253             fputc(ptr[i+gcomp], f); /* write green */
254             fputc(ptr[i+bcomp], f); /* write blue */
255          }
256       }
257       fclose(f);
258    }
259 }
260
261
262 /**
263  * Write level[0] image to a ppm file.
264  */
265 static void
266 write_texture_image(struct gl_texture_object *texObj)
267 {
268    const struct gl_texture_image *img = texObj->Image[0][0];
269    if (img && img->Data) {
270       char s[100];
271
272       /* make filename */
273       sprintf(s, "/tmp/teximage%u.ppm", texObj->Name);
274
275       switch (img->TexFormat->MesaFormat) {
276       case MESA_FORMAT_RGBA8888:
277          write_ppm(s, img->Data, img->Width, img->Height, 4, 3, 2, 1);
278          break;
279       case MESA_FORMAT_ARGB8888:
280          write_ppm(s, img->Data, img->Width, img->Height, 4, 2, 1, 0);
281          break;
282       case MESA_FORMAT_RGB888:
283          write_ppm(s, img->Data, img->Width, img->Height, 3, 2, 1, 0);
284          break;
285       case MESA_FORMAT_RGB565:
286          {
287             GLubyte *buf2 = (GLubyte *) _mesa_malloc(img->Width * img->Height * 3);
288             GLuint i;
289             for (i = 0; i < img->Width * img->Height; i++) {
290                GLint r, g, b;
291                GLushort s = ((GLushort *) img->Data)[i];
292                r = UBYTE_TO_CHAN( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) );
293                g = UBYTE_TO_CHAN( ((s >> 3) & 0xfc) | ((s >>  9) & 0x3) );
294                b = UBYTE_TO_CHAN( ((s << 3) & 0xf8) | ((s >>  2) & 0x7) );
295                buf2[i*3+1] = r;
296                buf2[i*3+2] = g;
297                buf2[i*3+3] = b;
298             }
299             write_ppm(s, buf2, img->Width, img->Height, 3, 2, 1, 0);
300             _mesa_free(buf2);
301          }
302          break;
303       default:
304          printf("XXXX unsupported mesa tex format %d in %s\n",
305                 img->TexFormat->MesaFormat, __FUNCTION__);
306       }
307    }
308 }
309
310
311 static GLboolean DumpImages;
312
313
314 static void
315 dump_texture_cb(GLuint id, void *data, void *userData)
316 {
317    struct gl_texture_object *texObj = (struct gl_texture_object *) data;
318    int i;
319    (void) userData;
320
321    printf("Texture %u\n", texObj->Name);
322    printf("  Target 0x%x\n", texObj->Target);
323    for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
324       struct gl_texture_image *texImg = texObj->Image[0][i];
325       if (texImg) {
326          printf("  Image %u: %d x %d x %d at %p\n", i,
327                 texImg->Width, texImg->Height, texImg->Depth, texImg->Data);
328          if (DumpImages && i == 0) {
329             write_texture_image(texObj);
330          }
331       }
332    }
333 }
334
335
336 /**
337  * Print basic info about all texture objext to stdout.
338  * If dumpImages is true, write PPM of level[0] image to a file.
339  */
340 void
341 _mesa_dump_textures(GLboolean dumpImages)
342 {
343    GET_CURRENT_CONTEXT(ctx);
344    DumpImages = dumpImages;
345    _mesa_HashWalk(ctx->Shared->TexObjects, dump_texture_cb, ctx);
346 }
347
348
349 void
350 _mesa_dump_color_buffer(const char *filename)
351 {
352    GET_CURRENT_CONTEXT(ctx);
353    const GLuint w = ctx->DrawBuffer->Width;
354    const GLuint h = ctx->DrawBuffer->Height;
355    GLubyte *buf;
356
357    buf = (GLubyte *) _mesa_malloc(w * h * 4);
358
359    _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
360    _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
361    _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
362
363    _mesa_ReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buf);
364
365    _mesa_printf("ReadBuffer %p 0x%x  DrawBuffer %p 0x%x\n",
366                 ctx->ReadBuffer->_ColorReadBuffer,
367                 ctx->ReadBuffer->ColorReadBuffer,
368                 ctx->DrawBuffer->_ColorDrawBuffers[0],
369                 ctx->DrawBuffer->ColorDrawBuffer[0]);
370    _mesa_printf("Writing %d x %d color buffer to %s\n", w, h, filename);
371    write_ppm(filename, buf, w, h, 4, 0, 1, 2);
372
373    _mesa_PopClientAttrib();
374
375    _mesa_free(buf);
376 }
377
378
379 void
380 _mesa_dump_depth_buffer(const char *filename)
381 {
382    GET_CURRENT_CONTEXT(ctx);
383    const GLuint w = ctx->DrawBuffer->Width;
384    const GLuint h = ctx->DrawBuffer->Height;
385    GLuint *buf;
386    GLubyte *buf2;
387    GLuint i;
388
389    buf = (GLuint *) _mesa_malloc(w * h * 4);  /* 4 bpp */
390    buf2 = (GLubyte *) _mesa_malloc(w * h * 3); /* 3 bpp */
391
392    _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
393    _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
394    _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
395
396    _mesa_ReadPixels(0, 0, w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buf);
397
398    /* spread 24 bits of Z across R, G, B */
399    for (i = 0; i < w * h; i++) {
400       buf2[i*3+0] = (buf[i] >> 24) & 0xff;
401       buf2[i*3+1] = (buf[i] >> 16) & 0xff;
402       buf2[i*3+2] = (buf[i] >>  8) & 0xff;
403    }
404
405    _mesa_printf("Writing %d x %d depth buffer to %s\n", w, h, filename);
406    write_ppm(filename, buf2, w, h, 3, 0, 1, 2);
407
408    _mesa_PopClientAttrib();
409
410    _mesa_free(buf);
411    _mesa_free(buf2);
412 }
413
414
415 void
416 _mesa_dump_stencil_buffer(const char *filename)
417 {
418    GET_CURRENT_CONTEXT(ctx);
419    const GLuint w = ctx->DrawBuffer->Width;
420    const GLuint h = ctx->DrawBuffer->Height;
421    GLubyte *buf;
422    GLubyte *buf2;
423    GLuint i;
424
425    buf = (GLubyte *) _mesa_malloc(w * h);  /* 1 bpp */
426    buf2 = (GLubyte *) _mesa_malloc(w * h * 3); /* 3 bpp */
427
428    _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
429    _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
430    _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
431
432    _mesa_ReadPixels(0, 0, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf);
433
434    for (i = 0; i < w * h; i++) {
435       buf2[i*3+0] = buf[i];
436       buf2[i*3+1] = (buf[i] & 127) * 2;
437       buf2[i*3+2] = (buf[i] - 128) * 2;
438    }
439
440    _mesa_printf("Writing %d x %d stencil buffer to %s\n", w, h, filename);
441    write_ppm(filename, buf2, w, h, 3, 0, 1, 2);
442
443    _mesa_PopClientAttrib();
444
445    _mesa_free(buf);
446    _mesa_free(buf2);
447 }