gallium: Implement pf_sprint_name as a simple static table.
[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 ULONG_PTR iFile = 0;
158 const void *pMap = NULL;
159 const char *sol, *eol, *sep;
160 static char output[1024];
161
162 result = dfault;
163 /* XXX: this creates the file if it does not exists, so it must either be
164 * disabled on release versions, or put in a less conspicuous place.
165 */
166 pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile);
167 if(pMap) {
168 sol = (const char *)pMap;
169 while(1) {
170 /* TODO: handle LF line endings */
171 eol = find(sol, NULL, '\r');
172 if(!eol || eol == sol)
173 break;
174 sep = find(sol, eol, '=');
175 if(!sep)
176 break;
177 if(compare(sol, sep, name)) {
178 copy(output, sep + 1, eol, sizeof(output));
179 result = output;
180 break;
181 }
182 sol = eol + 2;
183 }
184 EngUnmapFile(iFile);
185 }
186 #else
187
188 result = getenv(name);
189 if(!result)
190 result = dfault;
191 #endif
192
193 debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
194
195 return result;
196 }
197
198 boolean
199 debug_get_bool_option(const char *name, boolean dfault)
200 {
201 const char *str = debug_get_option(name, NULL);
202 boolean result;
203
204 if(str == NULL)
205 result = dfault;
206 else if(!util_strcmp(str, "n"))
207 result = FALSE;
208 else if(!util_strcmp(str, "no"))
209 result = FALSE;
210 else if(!util_strcmp(str, "0"))
211 result = FALSE;
212 else if(!util_strcmp(str, "f"))
213 result = FALSE;
214 else if(!util_strcmp(str, "false"))
215 result = FALSE;
216 else
217 result = TRUE;
218
219 debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
220
221 return result;
222 }
223
224
225 long
226 debug_get_num_option(const char *name, long dfault)
227 {
228 /* FIXME */
229 return dfault;
230 }
231
232
233 unsigned long
234 debug_get_flags_option(const char *name,
235 const struct debug_named_value *flags,
236 unsigned long dfault)
237 {
238 unsigned long result;
239 const char *str;
240
241 str = debug_get_option(name, NULL);
242 if(!str)
243 result = dfault;
244 else {
245 result = 0;
246 while( flags->name ) {
247 if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
248 result |= flags->value;
249 ++flags;
250 }
251 }
252
253 debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
254
255 return result;
256 }
257
258
259 void _debug_assert_fail(const char *expr,
260 const char *file,
261 unsigned line,
262 const char *function)
263 {
264 _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
265 if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
266 debug_break();
267 else
268 _debug_printf("continuing...\n");
269 }
270
271
272 const char *
273 debug_dump_enum(const struct debug_named_value *names,
274 unsigned long value)
275 {
276 static char rest[256];
277
278 while(names->name) {
279 if(names->value == value)
280 return names->name;
281 ++names;
282 }
283
284 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
285 return rest;
286 }
287
288
289 const char *
290 debug_dump_flags(const struct debug_named_value *names,
291 unsigned long value)
292 {
293 static char output[4096];
294 static char rest[256];
295 int first = 1;
296
297 output[0] = '\0';
298
299 while(names->name) {
300 if((names->value & value) == names->value) {
301 if (!first)
302 util_strncat(output, "|", sizeof(output));
303 else
304 first = 0;
305 util_strncat(output, names->name, sizeof(output));
306 value &= ~names->value;
307 }
308 ++names;
309 }
310
311 if (value) {
312 if (!first)
313 util_strncat(output, "|", sizeof(output));
314 else
315 first = 0;
316
317 util_snprintf(rest, sizeof(rest), "0x%08lx", value);
318 util_strncat(output, rest, sizeof(output));
319 }
320
321 if(first)
322 return "0";
323
324 return output;
325 }
326
327
328 char *pf_sprint_name( char *str, enum pipe_format format )
329 {
330 strcpy( str, debug_dump_enum(pipe_format_names, fmt) );
331 return str;
332 }
333
334
335 #ifdef DEBUG
336 static const struct debug_named_value pipe_format_names[] = {
337 DEBUG_NAMED_VALUE(PIPE_FORMAT_NONE),
338 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_UNORM),
339 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_UNORM),
340 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_UNORM),
341 DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_UNORM),
342 DEBUG_NAMED_VALUE(PIPE_FORMAT_A1R5G5B5_UNORM),
343 DEBUG_NAMED_VALUE(PIPE_FORMAT_A4R4G4B4_UNORM),
344 DEBUG_NAMED_VALUE(PIPE_FORMAT_R5G6B5_UNORM),
345 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_UNORM),
346 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_UNORM),
347 DEBUG_NAMED_VALUE(PIPE_FORMAT_I8_UNORM),
348 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_UNORM),
349 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR),
350 DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR_REV),
351 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z16_UNORM),
352 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_UNORM),
353 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_FLOAT),
354 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8Z24_UNORM),
355 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24S8_UNORM),
356 DEBUG_NAMED_VALUE(PIPE_FORMAT_X8Z24_UNORM),
357 DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24X8_UNORM),
358 DEBUG_NAMED_VALUE(PIPE_FORMAT_S8_UNORM),
359 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64_FLOAT),
360 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64_FLOAT),
361 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64_FLOAT),
362 DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64A64_FLOAT),
363 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_FLOAT),
364 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_FLOAT),
365 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_FLOAT),
366 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_FLOAT),
367 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_UNORM),
368 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_UNORM),
369 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_UNORM),
370 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_UNORM),
371 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_USCALED),
372 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_USCALED),
373 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_USCALED),
374 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_USCALED),
375 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SNORM),
376 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SNORM),
377 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SNORM),
378 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SNORM),
379 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SSCALED),
380 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SSCALED),
381 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SSCALED),
382 DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SSCALED),
383 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_UNORM),
384 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_UNORM),
385 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_UNORM),
386 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_UNORM),
387 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_USCALED),
388 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_USCALED),
389 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_USCALED),
390 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_USCALED),
391 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SNORM),
392 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SNORM),
393 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SNORM),
394 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SNORM),
395 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SSCALED),
396 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SSCALED),
397 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SSCALED),
398 DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SSCALED),
399 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_UNORM),
400 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_UNORM),
401 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_UNORM),
402 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_UNORM),
403 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_UNORM),
404 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_USCALED),
405 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_USCALED),
406 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_USCALED),
407 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_USCALED),
408 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_USCALED),
409 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SNORM),
410 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SNORM),
411 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SNORM),
412 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SNORM),
413 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SNORM),
414 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SSCALED),
415 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SSCALED),
416 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SSCALED),
417 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SSCALED),
418 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SSCALED),
419 DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_SRGB),
420 DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_L8_SRGB),
421 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SRGB),
422 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SRGB),
423 DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SRGB),
424 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGB),
425 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGBA),
426 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_RGBA),
427 DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_RGBA),
428 DEBUG_NAMED_VALUE_END
429 };
430
431 void debug_print_format(const char *msg, unsigned fmt )
432 {
433 debug_printf("%s: %s\n", msg, debug_dump_enum(pipe_format_names, fmt));
434 }
435 #endif
436
437
438 #ifdef DEBUG
439 void debug_dump_image(const char *prefix,
440 unsigned format, unsigned cpp,
441 unsigned width, unsigned height,
442 unsigned pitch,
443 const void *data)
444 {
445 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
446 static unsigned no = 0;
447 char filename[256];
448 WCHAR wfilename[sizeof(filename)];
449 ULONG_PTR iFile = 0;
450 struct {
451 unsigned format;
452 unsigned cpp;
453 unsigned width;
454 unsigned height;
455 } header;
456 unsigned char *pMap = NULL;
457 unsigned i;
458
459 util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix);
460 for(i = 0; i < sizeof(filename); ++i)
461 wfilename[i] = (WCHAR)filename[i];
462
463 pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + cpp*width*height, &iFile);
464 if(!pMap)
465 return;
466
467 header.format = format;
468 header.cpp = cpp;
469 header.width = width;
470 header.height = height;
471 memcpy(pMap, &header, sizeof(header));
472 pMap += sizeof(header);
473
474 for(i = 0; i < height; ++i) {
475 memcpy(pMap, (unsigned char *)data + cpp*pitch*i, cpp*width);
476 pMap += cpp*width;
477 }
478
479 EngUnmapFile(iFile);
480 #endif
481 }
482 #endif