Merge branch 'gallium-0.1' into gallium-tex-surfaces
[mesa.git] / src / gallium / auxiliary / util / p_debug.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * 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
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29 #include "pipe/p_config.h"
30
31 #include <stdarg.h>
32
33 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
34 #include <windows.h>
35 #include <winddi.h>
36 #else
37 #include <stdio.h>
38 #include <stdlib.h>
39 #endif
40
41 #include "pipe/p_compiler.h"
42 #include "pipe/p_util.h"
43 #include "pipe/p_debug.h"
44 #include "pipe/p_format.h"
45 #include "util/u_string.h"
46
47
48 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
49 static INLINE void
50 _EngDebugPrint(const char *format, ...)
51 {
52 va_list ap;
53 va_start(ap, format);
54 EngDebugPrint("", (PCHAR)format, ap);
55 va_end(ap);
56 }
57 #endif
58
59
60 void _debug_vprintf(const char *format, va_list ap)
61 {
62 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
63 #ifndef WINCE
64 /* EngDebugPrint does not handle float point arguments, so we need to use
65 * our own vsnprintf implementation. It is also very slow, so buffer until
66 * we find a newline. */
67 static char buf[512 + 1] = {'\0'};
68 size_t len = strlen(buf);
69 int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
70 if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
71 _EngDebugPrint("%s", buf);
72 buf[0] = '\0';
73 }
74 #else
75 /* TODO: Implement debug print for WINCE */
76 #endif
77 #else
78 vfprintf(stderr, format, ap);
79 #endif
80 }
81
82
83 #ifdef DEBUG
84 void debug_print_blob( const char *name,
85 const void *blob,
86 unsigned size )
87 {
88 const unsigned *ublob = (const unsigned *)blob;
89 unsigned i;
90
91 debug_printf("%s (%d dwords%s)\n", name, size/4,
92 size%4 ? "... plus a few bytes" : "");
93
94 for (i = 0; i < size/4; i++) {
95 debug_printf("%d:\t%08x\n", i, ublob[i]);
96 }
97 }
98 #endif
99
100
101 void _debug_break(void)
102 {
103 #if (defined(__i386__) || defined(__386__)) && defined(__GNUC__)
104 __asm("int3");
105 #elif (defined(__i386__) || defined(__386__)) && defined(__MSC__)
106 _asm {int 3};
107 #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
108 EngDebugBreak();
109 #else
110 abort();
111 #endif
112 }
113
114
115 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
116 static const char *
117 find(const char *start, const char *end, char c)
118 {
119 const char *p;
120 for(p = start; !end || p != end; ++p) {
121 if(*p == c)
122 return p;
123 if(*p < 32)
124 break;
125 }
126 return NULL;
127 }
128
129 static int
130 compare(const char *start, const char *end, const char *s)
131 {
132 const char *p, *q;
133 for(p = start, q = s; p != end && *q != '\0'; ++p, ++q) {
134 if(*p != *q)
135 return 0;
136 }
137 return p == end && *q == '\0';
138 }
139
140 static void
141 copy(char *dst, const char *start, const char *end, size_t n)
142 {
143 const char *p;
144 char *q;
145 for(p = start, q = dst, n = n - 1; p != end && n; ++p, ++q, --n)
146 *q = *p;
147 *q = '\0';
148 }
149 #endif
150
151
152 const char *
153 debug_get_option(const char *name, const char *dfault)
154 {
155 const char *result;
156 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
157 #ifdef DEBUG
158 ULONG_PTR iFile = 0;
159 const void *pMap = NULL;
160 const char *sol, *eol, *sep;
161 static char output[1024];
162
163 result = dfault;
164 /* XXX: this creates the file if it does not exists, so it must either be
165 * disabled on release versions, or put in a less conspicuous place.
166 */
167 pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile);
168 if(pMap) {
169 sol = (const char *)pMap;
170 while(1) {
171 /* TODO: handle LF line endings */
172 eol = find(sol, NULL, '\r');
173 if(!eol || eol == sol)
174 break;
175 sep = find(sol, eol, '=');
176 if(!sep)
177 break;
178 if(compare(sol, sep, name)) {
179 copy(output, sep + 1, eol, sizeof(output));
180 result = output;
181 break;
182 }
183 sol = eol + 2;
184 }
185 EngUnmapFile(iFile);
186 }
187 #else
188 result = dfault;
189 #endif
190 #else
191
192 result = getenv(name);
193 if(!result)
194 result = dfault;
195 #endif
196
197 debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
198
199 return result;
200 }
201
202 boolean
203 debug_get_bool_option(const char *name, boolean dfault)
204 {
205 const char *str = debug_get_option(name, NULL);
206 boolean result;
207
208 if(str == NULL)
209 result = dfault;
210 else if(!util_strcmp(str, "n"))
211 result = FALSE;
212 else if(!util_strcmp(str, "no"))
213 result = FALSE;
214 else if(!util_strcmp(str, "0"))
215 result = FALSE;
216 else if(!util_strcmp(str, "f"))
217 result = FALSE;
218 else if(!util_strcmp(str, "false"))
219 result = FALSE;
220 else
221 result = TRUE;
222
223 debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
224
225 return result;
226 }
227
228
229 long
230 debug_get_num_option(const char *name, long dfault)
231 {
232 /* FIXME */
233 return dfault;
234 }
235
236
237 unsigned long
238 debug_get_flags_option(const char *name,
239 const struct debug_named_value *flags,
240 unsigned long dfault)
241 {
242 unsigned long result;
243 const char *str;
244
245 str = debug_get_option(name, NULL);
246 if(!str)
247 result = dfault;
248 else {
249 result = 0;
250 while( flags->name ) {
251 if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
252 result |= flags->value;
253 ++flags;
254 }
255 }
256
257 debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
258
259 return result;
260 }
261
262
263 void _debug_assert_fail(const char *expr,
264 const char *file,
265 unsigned line,
266 const char *function)
267 {
268 _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
269 if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
270 debug_break();
271 else
272 _debug_printf("continuing...\n");
273 }
274
275
276 const char *
277 debug_dump_enum(const struct debug_named_value *names,
278 unsigned long value)
279 {
280 static char rest[256];
281
282 while(names->name) {
283 if(names->value == value)
284 return names->name;
285 ++names;
286 }
287
288 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
289 return rest;
290 }
291
292
293 const char *
294 debug_dump_flags(const struct debug_named_value *names,
295 unsigned long value)
296 {
297 static char output[4096];
298 static char rest[256];
299 int first = 1;
300
301 output[0] = '\0';
302
303 while(names->name) {
304 if((names->value & value) == names->value) {
305 if (!first)
306 util_strncat(output, "|", sizeof(output));
307 else
308 first = 0;
309 util_strncat(output, names->name, sizeof(output));
310 value &= ~names->value;
311 }
312 ++names;
313 }
314
315 if (value) {
316 if (!first)
317 util_strncat(output, "|", sizeof(output));
318 else
319 first = 0;
320
321 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
322 util_strncat(output, rest, sizeof(output));
323 }
324
325 if(first)
326 return "0";
327
328 return output;
329 }
330
331
332 static const struct debug_named_value pipe_format_names[] = {
333 #ifdef DEBUG
334 DEBUG_NAMED_VALUE(PIPE_FORMAT_NONE),
335 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_UNORM),
336 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_UNORM),
337 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_UNORM),
338 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_UNORM),
339 DEBUG_NAMED_VALUE(PIPE_FORMAT_A1R5G5B5_UNORM),
340 DEBUG_NAMED_VALUE(PIPE_FORMAT_A4R4G4B4_UNORM),
341 DEBUG_NAMED_VALUE(PIPE_FORMAT_R5G6B5_UNORM),
342 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_UNORM),
343 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_UNORM),
344 DEBUG_NAMED_VALUE(PIPE_FORMAT_I8_UNORM),
345 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_UNORM),
346 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR),
347 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR_REV),
348 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z16_UNORM),
349 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_UNORM),
350 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_FLOAT),
351 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8Z24_UNORM),
352 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24S8_UNORM),
353 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8Z24_UNORM),
354 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24X8_UNORM),
355 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8_UNORM),
356 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64_FLOAT),
357 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64_FLOAT),
358 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64_FLOAT),
359 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64A64_FLOAT),
360 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_FLOAT),
361 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_FLOAT),
362 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_FLOAT),
363 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_FLOAT),
364 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_UNORM),
365 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_UNORM),
366 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_UNORM),
367 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_UNORM),
368 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_USCALED),
369 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_USCALED),
370 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_USCALED),
371 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_USCALED),
372 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SNORM),
373 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SNORM),
374 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SNORM),
375 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SNORM),
376 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SSCALED),
377 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SSCALED),
378 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SSCALED),
379 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SSCALED),
380 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_UNORM),
381 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_UNORM),
382 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_UNORM),
383 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_UNORM),
384 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_USCALED),
385 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_USCALED),
386 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_USCALED),
387 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_USCALED),
388 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SNORM),
389 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SNORM),
390 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SNORM),
391 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SNORM),
392 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SSCALED),
393 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SSCALED),
394 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SSCALED),
395 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SSCALED),
396 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_UNORM),
397 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_UNORM),
398 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_UNORM),
399 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_UNORM),
400 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_UNORM),
401 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_USCALED),
402 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_USCALED),
403 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_USCALED),
404 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_USCALED),
405 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_USCALED),
406 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SNORM),
407 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SNORM),
408 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SNORM),
409 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SNORM),
410 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SNORM),
411 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SSCALED),
412 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SSCALED),
413 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SSCALED),
414 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SSCALED),
415 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SSCALED),
416 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_SRGB),
417 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_L8_SRGB),
418 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SRGB),
419 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SRGB),
420 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SRGB),
421 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGB),
422 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGBA),
423 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_RGBA),
424 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_RGBA),
425 #endif
426 DEBUG_NAMED_VALUE_END
427 };
428
429 #ifdef DEBUG
430 void debug_print_format(const char *msg, unsigned fmt )
431 {
432 debug_printf("%s: %s\n", msg, debug_dump_enum(pipe_format_names, fmt));
433 }
434 #endif
435
436 char *pf_sprint_name( char *str, enum pipe_format format )
437 {
438 strcpy( str, debug_dump_enum(pipe_format_names, format) );
439 return str;
440 }
441
442
443 #ifdef DEBUG
444 void debug_dump_image(const char *prefix,
445 unsigned format, unsigned cpp,
446 unsigned width, unsigned height,
447 unsigned pitch,
448 const void *data)
449 {
450 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
451 static unsigned no = 0;
452 char filename[256];
453 WCHAR wfilename[sizeof(filename)];
454 ULONG_PTR iFile = 0;
455 struct {
456 unsigned format;
457 unsigned cpp;
458 unsigned width;
459 unsigned height;
460 } header;
461 unsigned char *pMap = NULL;
462 unsigned i;
463
464 util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix);
465 for(i = 0; i < sizeof(filename); ++i)
466 wfilename[i] = (WCHAR)filename[i];
467
468 pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + cpp*width*height, &iFile);
469 if(!pMap)
470 return;
471
472 header.format = format;
473 header.cpp = cpp;
474 header.width = width;
475 header.height = height;
476 memcpy(pMap, &header, sizeof(header));
477 pMap += sizeof(header);
478
479 for(i = 0; i < height; ++i) {
480 memcpy(pMap, (unsigned char *)data + cpp*pitch*i, cpp*width);
481 pMap += cpp*width;
482 }
483
484 EngUnmapFile(iFile);
485 #endif
486 }
487 #endif