• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2008 VMware, Inc.
4  * Copyright (c) 2008 VMware, Inc.
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  *
27  **************************************************************************/
28 
29 
30 #include "pipe/p_config.h"
31 
32 #include "pipe/p_compiler.h"
33 #include "util/u_debug.h"
34 #include "pipe/p_format.h"
35 #include "pipe/p_state.h"
36 #include "util/u_inlines.h"
37 #include "util/u_format.h"
38 #include "util/u_memory.h"
39 #include "util/u_string.h"
40 #include "util/u_math.h"
41 #include "util/u_prim.h"
42 #include "util/u_surface.h"
43 
44 #include <stdio.h>
45 #include <limits.h> /* CHAR_BIT */
46 #include <ctype.h> /* isalnum */
47 
48 #ifdef _WIN32
49 #include <windows.h>
50 #include <stdlib.h>
51 #endif
52 
53 
_debug_vprintf(const char * format,va_list ap)54 void _debug_vprintf(const char *format, va_list ap)
55 {
56    static char buf[4096] = {'\0'};
57 #if defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_EMBEDDED)
58    /* We buffer until we find a newline. */
59    size_t len = strlen(buf);
60    int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
61    if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
62       os_log_message(buf);
63       buf[0] = '\0';
64    }
65 #else
66    util_vsnprintf(buf, sizeof(buf), format, ap);
67    os_log_message(buf);
68 #endif
69 }
70 
71 
72 void
debug_disable_error_message_boxes(void)73 debug_disable_error_message_boxes(void)
74 {
75 #ifdef _WIN32
76    /* When Windows' error message boxes are disabled for this process (as is
77     * typically the case when running tests in an automated fashion) we disable
78     * CRT message boxes too.
79     */
80    UINT uMode = SetErrorMode(0);
81    SetErrorMode(uMode);
82    if (uMode & SEM_FAILCRITICALERRORS) {
83       /* Disable assertion failure message box.
84        * http://msdn.microsoft.com/en-us/library/sas1dkb2.aspx
85        */
86       _set_error_mode(_OUT_TO_STDERR);
87 #ifdef _MSC_VER
88       /* Disable abort message box.
89        * http://msdn.microsoft.com/en-us/library/e631wekh.aspx
90        */
91       _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
92 #endif
93    }
94 #endif /* _WIN32 */
95 }
96 
97 
98 #ifdef DEBUG
debug_print_blob(const char * name,const void * blob,unsigned size)99 void debug_print_blob( const char *name,
100                        const void *blob,
101                        unsigned size )
102 {
103    const unsigned *ublob = (const unsigned *)blob;
104    unsigned i;
105 
106    debug_printf("%s (%d dwords%s)\n", name, size/4,
107                 size%4 ? "... plus a few bytes" : "");
108 
109    for (i = 0; i < size/4; i++) {
110       debug_printf("%d:\t%08x\n", i, ublob[i]);
111    }
112 }
113 #endif
114 
115 
116 static boolean
debug_get_option_should_print(void)117 debug_get_option_should_print(void)
118 {
119    static boolean first = TRUE;
120    static boolean value = FALSE;
121 
122    if (!first)
123       return value;
124 
125    /* Oh hey this will call into this function,
126     * but its cool since we set first to false
127     */
128    first = FALSE;
129    value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", FALSE);
130    /* XXX should we print this option? Currently it wont */
131    return value;
132 }
133 
134 const char *
debug_get_option(const char * name,const char * dfault)135 debug_get_option(const char *name, const char *dfault)
136 {
137    const char *result;
138 
139    result = os_get_option(name);
140    if(!result)
141       result = dfault;
142 
143    if (debug_get_option_should_print())
144       debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
145 
146    return result;
147 }
148 
149 boolean
debug_get_bool_option(const char * name,boolean dfault)150 debug_get_bool_option(const char *name, boolean dfault)
151 {
152    const char *str = os_get_option(name);
153    boolean result;
154 
155    if(str == NULL)
156       result = dfault;
157    else if(!util_strcmp(str, "n"))
158       result = FALSE;
159    else if(!util_strcmp(str, "no"))
160       result = FALSE;
161    else if(!util_strcmp(str, "0"))
162       result = FALSE;
163    else if(!util_strcmp(str, "f"))
164       result = FALSE;
165    else if(!util_strcmp(str, "F"))
166       result = FALSE;
167    else if(!util_strcmp(str, "false"))
168       result = FALSE;
169    else if(!util_strcmp(str, "FALSE"))
170       result = FALSE;
171    else
172       result = TRUE;
173 
174    if (debug_get_option_should_print())
175       debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
176 
177    return result;
178 }
179 
180 
181 long
debug_get_num_option(const char * name,long dfault)182 debug_get_num_option(const char *name, long dfault)
183 {
184    long result;
185    const char *str;
186 
187    str = os_get_option(name);
188    if(!str)
189       result = dfault;
190    else {
191       long sign;
192       char c;
193       c = *str++;
194       if(c == '-') {
195 	 sign = -1;
196 	 c = *str++;
197       }
198       else {
199 	 sign = 1;
200       }
201       result = 0;
202       while('0' <= c && c <= '9') {
203 	 result = result*10 + (c - '0');
204 	 c = *str++;
205       }
206       result *= sign;
207    }
208 
209    if (debug_get_option_should_print())
210       debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
211 
212    return result;
213 }
214 
str_has_option(const char * str,const char * name)215 static boolean str_has_option(const char *str, const char *name)
216 {
217    /* Empty string. */
218    if (!*str) {
219       return FALSE;
220    }
221 
222    /* OPTION=all */
223    if (!util_strcmp(str, "all")) {
224       return TRUE;
225    }
226 
227    /* Find 'name' in 'str' surrounded by non-alphanumeric characters. */
228    {
229       const char *start = str;
230       unsigned name_len = strlen(name);
231 
232       /* 'start' is the beginning of the currently-parsed word,
233        * we increment 'str' each iteration.
234        * if we find either the end of string or a non-alphanumeric character,
235        * we compare 'start' up to 'str-1' with 'name'. */
236 
237       while (1) {
238          if (!*str || !(isalnum(*str) || *str == '_')) {
239             if (str-start == name_len &&
240                 !memcmp(start, name, name_len)) {
241                return TRUE;
242             }
243 
244             if (!*str) {
245                return FALSE;
246             }
247 
248             start = str+1;
249          }
250 
251          str++;
252       }
253    }
254 
255    return FALSE;
256 }
257 
258 unsigned long
debug_get_flags_option(const char * name,const struct debug_named_value * flags,unsigned long dfault)259 debug_get_flags_option(const char *name,
260                        const struct debug_named_value *flags,
261                        unsigned long dfault)
262 {
263    unsigned long result;
264    const char *str;
265    const struct debug_named_value *orig = flags;
266    unsigned namealign = 0;
267 
268    str = os_get_option(name);
269    if(!str)
270       result = dfault;
271    else if (!util_strcmp(str, "help")) {
272       result = dfault;
273       _debug_printf("%s: help for %s:\n", __FUNCTION__, name);
274       for (; flags->name; ++flags)
275          namealign = MAX2(namealign, strlen(flags->name));
276       for (flags = orig; flags->name; ++flags)
277          _debug_printf("| %*s [0x%0*lx]%s%s\n", namealign, flags->name,
278                       (int)sizeof(unsigned long)*CHAR_BIT/4, flags->value,
279                       flags->desc ? " " : "", flags->desc ? flags->desc : "");
280    }
281    else {
282       result = 0;
283       while( flags->name ) {
284 	 if (str_has_option(str, flags->name))
285 	    result |= flags->value;
286 	 ++flags;
287       }
288    }
289 
290    if (debug_get_option_should_print()) {
291       if (str) {
292          debug_printf("%s: %s = 0x%lx (%s)\n", __FUNCTION__, name, result, str);
293       } else {
294          debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
295       }
296    }
297 
298    return result;
299 }
300 
301 
_debug_assert_fail(const char * expr,const char * file,unsigned line,const char * function)302 void _debug_assert_fail(const char *expr,
303                         const char *file,
304                         unsigned line,
305                         const char *function)
306 {
307    _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
308    os_abort();
309 }
310 
311 
312 const char *
debug_dump_enum(const struct debug_named_value * names,unsigned long value)313 debug_dump_enum(const struct debug_named_value *names,
314                 unsigned long value)
315 {
316    static char rest[64];
317 
318    while(names->name) {
319       if(names->value == value)
320 	 return names->name;
321       ++names;
322    }
323 
324    util_snprintf(rest, sizeof(rest), "0x%08lx", value);
325    return rest;
326 }
327 
328 
329 const char *
debug_dump_enum_noprefix(const struct debug_named_value * names,const char * prefix,unsigned long value)330 debug_dump_enum_noprefix(const struct debug_named_value *names,
331                          const char *prefix,
332                          unsigned long value)
333 {
334    static char rest[64];
335 
336    while(names->name) {
337       if(names->value == value) {
338          const char *name = names->name;
339          while (*name == *prefix) {
340             name++;
341             prefix++;
342          }
343          return name;
344       }
345       ++names;
346    }
347 
348 
349 
350    util_snprintf(rest, sizeof(rest), "0x%08lx", value);
351    return rest;
352 }
353 
354 
355 const char *
debug_dump_flags(const struct debug_named_value * names,unsigned long value)356 debug_dump_flags(const struct debug_named_value *names,
357                  unsigned long value)
358 {
359    static char output[4096];
360    static char rest[256];
361    int first = 1;
362 
363    output[0] = '\0';
364 
365    while(names->name) {
366       if((names->value & value) == names->value) {
367 	 if (!first)
368 	    util_strncat(output, "|", sizeof(output) - strlen(output) - 1);
369 	 else
370 	    first = 0;
371 	 util_strncat(output, names->name, sizeof(output) - strlen(output) - 1);
372 	 output[sizeof(output) - 1] = '\0';
373 	 value &= ~names->value;
374       }
375       ++names;
376    }
377 
378    if (value) {
379       if (!first)
380 	 util_strncat(output, "|", sizeof(output) - strlen(output) - 1);
381       else
382 	 first = 0;
383 
384       util_snprintf(rest, sizeof(rest), "0x%08lx", value);
385       util_strncat(output, rest, sizeof(output) - strlen(output) - 1);
386       output[sizeof(output) - 1] = '\0';
387    }
388 
389    if(first)
390       return "0";
391 
392    return output;
393 }
394 
395 
396 #ifdef DEBUG
debug_print_format(const char * msg,unsigned fmt)397 void debug_print_format(const char *msg, unsigned fmt )
398 {
399    debug_printf("%s: %s\n", msg, util_format_name(fmt));
400 }
401 #endif
402 
403 
404 
405 static const struct debug_named_value pipe_prim_names[] = {
406 #ifdef DEBUG
407    DEBUG_NAMED_VALUE(PIPE_PRIM_POINTS),
408    DEBUG_NAMED_VALUE(PIPE_PRIM_LINES),
409    DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_LOOP),
410    DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP),
411    DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES),
412    DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP),
413    DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_FAN),
414    DEBUG_NAMED_VALUE(PIPE_PRIM_QUADS),
415    DEBUG_NAMED_VALUE(PIPE_PRIM_QUAD_STRIP),
416    DEBUG_NAMED_VALUE(PIPE_PRIM_POLYGON),
417    DEBUG_NAMED_VALUE(PIPE_PRIM_LINES_ADJACENCY),
418    DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP_ADJACENCY),
419    DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES_ADJACENCY),
420    DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY),
421 #endif
422    DEBUG_NAMED_VALUE_END
423 };
424 
425 
u_prim_name(unsigned prim)426 const char *u_prim_name( unsigned prim )
427 {
428    return debug_dump_enum(pipe_prim_names, prim);
429 }
430 
431 
432 
433 #ifdef DEBUG
434 int fl_indent = 0;
435 const char* fl_function[1024];
436 
437 int
debug_funclog_enter(const char * f,UNUSED const int line,UNUSED const char * file)438 debug_funclog_enter(const char* f, UNUSED const int line,
439                     UNUSED const char* file)
440 {
441    int i;
442 
443    for (i = 0; i < fl_indent; i++)
444       debug_printf("  ");
445    debug_printf("%s\n", f);
446 
447    assert(fl_indent < 1023);
448    fl_function[fl_indent++] = f;
449 
450    return 0;
451 }
452 
453 void
debug_funclog_exit(const char * f,UNUSED const int line,UNUSED const char * file)454 debug_funclog_exit(const char* f, UNUSED const int line,
455                    UNUSED const char* file)
456 {
457    --fl_indent;
458    assert(fl_indent >= 0);
459    assert(fl_function[fl_indent] == f);
460 }
461 
462 void
debug_funclog_enter_exit(const char * f,UNUSED const int line,UNUSED const char * file)463 debug_funclog_enter_exit(const char* f, UNUSED const int line,
464                          UNUSED const char* file)
465 {
466    int i;
467    for (i = 0; i < fl_indent; i++)
468       debug_printf("  ");
469    debug_printf("%s\n", f);
470 }
471 #endif
472 
473 
474 
475 #ifdef DEBUG
476 /**
477  * Print PIPE_TRANSFER_x flags with a message.
478  */
479 void
debug_print_transfer_flags(const char * msg,unsigned usage)480 debug_print_transfer_flags(const char *msg, unsigned usage)
481 {
482 #define FLAG(x)  { x, #x }
483    static const struct {
484       unsigned bit;
485       const char *name;
486    } flags[] = {
487       FLAG(PIPE_TRANSFER_READ),
488       FLAG(PIPE_TRANSFER_WRITE),
489       FLAG(PIPE_TRANSFER_MAP_DIRECTLY),
490       FLAG(PIPE_TRANSFER_DISCARD_RANGE),
491       FLAG(PIPE_TRANSFER_DONTBLOCK),
492       FLAG(PIPE_TRANSFER_UNSYNCHRONIZED),
493       FLAG(PIPE_TRANSFER_FLUSH_EXPLICIT),
494       FLAG(PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE)
495    };
496    unsigned i;
497 
498    debug_printf("%s ", msg);
499 
500    for (i = 0; i < ARRAY_SIZE(flags); i++) {
501       if (usage & flags[i].bit) {
502          debug_printf("%s", flags[i].name);
503          usage &= ~flags[i].bit;
504          if (usage) {
505             debug_printf(" | ");
506          }
507       }
508    }
509 
510    debug_printf("\n");
511 #undef FLAG
512 }
513 
514 
515 
516 #endif
517