util: require debug options to be separated by commas
[mesa.git] / src / gallium / auxiliary / util / u_debug.c
index 27e0b0d1595cbd1d670469c9a7eef9f599123115..8cf76608e681eee8d698a3763992633262586b9f 100644 (file)
 
 #include "pipe/p_config.h" 
 
-#include <stdarg.h>
-
-
-#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
-
-#include <windows.h>
-#include <winddi.h>
-
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_CE)
-
-#include <stdio.h> 
-#include <stdlib.h> 
-#include <windows.h> 
-#include <types.h> 
-
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN      // Exclude rarely-used stuff from Windows headers
-#endif
-#include <windows.h>
-#include <stdio.h>
-
-#else
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#endif
-
-#include "pipe/p_compiler.h" 
+#include "pipe/p_compiler.h"
+#include "os/os_stream.h"
 #include "util/u_debug.h" 
 #include "pipe/p_format.h" 
 #include "pipe/p_state.h" 
-#include "pipe/p_inlines.h" 
+#include "util/u_inlines.h" 
 #include "util/u_format.h"
 #include "util/u_memory.h" 
 #include "util/u_string.h" 
-#include "util/u_stream.h" 
 #include "util/u_math.h" 
 #include "util/u_tile.h" 
+#include "util/u_prim.h"
+#include "util/u_surface.h"
 
-
-#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
-static INLINE void 
-_EngDebugPrint(const char *format, ...)
-{
-   va_list ap;
-   va_start(ap, format);
-   EngDebugPrint("", (PCHAR)format, ap);
-   va_end(ap);
-}
-#endif
-
+#include <limits.h> /* CHAR_BIT */
 
 void _debug_vprintf(const char *format, va_list ap)
 {
-#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
-   /* EngDebugPrint does not handle float point arguments, so we need to use
-    * our own vsnprintf implementation. It is also very slow, so buffer until
-    * we find a newline. */
-   static char buf[512] = {'\0'};
-   size_t len = strlen(buf);
-   int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
-   if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
-      _EngDebugPrint("%s", buf);
-      buf[0] = '\0';
-   }
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
-   /* OutputDebugStringA can be very slow, so buffer until we find a newline. */
+#if defined(PIPE_OS_WINDOWS) || defined(PIPE_OS_EMBEDDED)
+   /* We buffer until we find a newline. */
    static char buf[4096] = {'\0'};
    size_t len = strlen(buf);
    int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
    if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
-      OutputDebugStringA(buf);
+      os_log_message(buf);
       buf[0] = '\0';
    }
-   
-   if(GetConsoleWindow() && !IsDebuggerPresent()) {
-      fflush(stdout);
-      vfprintf(stderr, format, ap);
-      fflush(stderr);
-   }
-   
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_CE)
-   wchar_t *wide_format;
-   long wide_str_len;   
-   char buf[512];   
-   int ret;   
-#if (_WIN32_WCE < 600)
-   ret = vsprintf(buf, format, ap);   
-   if(ret < 0){   
-       sprintf(buf, "Cant handle debug print!");   
-       ret = 25;
-   }
 #else
-   ret = vsprintf_s(buf, 512, format, ap);   
-   if(ret < 0){   
-       sprintf_s(buf, 512, "Cant handle debug print!");   
-       ret = 25;
-   }
-#endif
-   buf[ret] = '\0';   
-   /* Format is ascii - needs to be converted to wchar_t for printing */   
-   wide_str_len = MultiByteToWideChar(CP_ACP, 0, (const char *) buf, -1, NULL, 0);   
-   wide_format = (wchar_t *) malloc((wide_str_len+1) * sizeof(wchar_t));   
-   if (wide_format) {   
-      MultiByteToWideChar(CP_ACP, 0, (const char *) buf, -1,   
-            wide_format, wide_str_len);   
-      NKDbgPrintfW(wide_format, wide_format);   
-      free(wide_format);   
-   } 
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
-   /* TODO */
-#else /* !PIPE_SUBSYSTEM_WINDOWS */
-   fflush(stdout);
+   /* Just print as-is to stderr */
    vfprintf(stderr, format, ap);
 #endif
 }
@@ -168,100 +81,22 @@ void debug_print_blob( const char *name,
 #endif
 
 
-#ifndef debug_break
-void debug_break(void) 
-{
-#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
-   DebugBreak();
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
-   EngDebugBreak();
-#else
-   abort();
-#endif
-}
-#endif
-
-
-#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
-static const char *
-find(const char *start, const char *end, char c) 
-{
-   const char *p;
-   for(p = start; !end || p != end; ++p) {
-      if(*p == c)
-        return p;
-      if(*p < 32)
-        break;
-   }
-   return NULL;
-}
-
-static int 
-compare(const char *start, const char *end, const char *s)
-{
-   const char *p, *q;
-   for(p = start, q = s; p != end && *q != '\0'; ++p, ++q) {
-      if(*p != *q)
-        return 0;
-   }
-   return p == end && *q == '\0';
-}
-
-static void 
-copy(char *dst, const char *start, const char *end, size_t n) 
-{
-   const char *p;
-   char *q;
-   for(p = start, q = dst, n = n - 1; p != end && n; ++p, ++q, --n)
-      *q = *p;
-   *q = '\0';
-}
-#endif
-
-
-static INLINE const char *
-_debug_get_option(const char *name)
+static boolean
+debug_get_option_should_print(void)
 {
-#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
-   /* EngMapFile creates the file if it does not exists, so it must either be
-    * disabled on release versions (or put in a less conspicuous place). */
-#ifdef DEBUG
-   const char *result = NULL;
-   ULONG_PTR iFile = 0;
-   const void *pMap = NULL;
-   const char *sol, *eol, *sep;
-   static char output[1024];
-   
-   pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile);
-   if(pMap) {
-      sol = (const char *)pMap;
-      while(1) {
-        /* TODO: handle LF line endings */
-        eol = find(sol, NULL, '\r');
-        if(!eol || eol == sol)
-           break;
-        sep = find(sol, eol, '=');
-        if(!sep)
-           break;
-        if(compare(sol, sep, name)) {
-           copy(output, sep + 1, eol, sizeof(output));
-           result = output;
-           break;
-        }
-        sol = eol + 2;
-      }
-      EngUnmapFile(iFile);
-   }
-   return result;
-#else
-   return NULL;
-#endif
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) 
-   /* TODO: implement */
-   return NULL;
-#else
-   return getenv(name);
-#endif
+   static boolean first = TRUE;
+   static boolean value = FALSE;
+
+   if (!first)
+      return value;
+
+   /* Oh hey this will call into this function,
+    * but its cool since we set first to false
+    */
+   first = FALSE;
+   value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", FALSE);
+   /* XXX should we print this option? Currently it wont */
+   return value;
 }
 
 const char *
@@ -269,11 +104,12 @@ debug_get_option(const char *name, const char *dfault)
 {
    const char *result;
 
-   result = _debug_get_option(name);
+   result = os_get_option(name);
    if(!result)
       result = dfault;
-      
-   debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
+
+   if (debug_get_option_should_print())
+      debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
    
    return result;
 }
@@ -281,7 +117,7 @@ debug_get_option(const char *name, const char *dfault)
 boolean
 debug_get_bool_option(const char *name, boolean dfault)
 {
-   const char *str = _debug_get_option(name);
+   const char *str = os_get_option(name);
    boolean result;
    
    if(str == NULL)
@@ -294,12 +130,17 @@ debug_get_bool_option(const char *name, boolean dfault)
       result = FALSE;
    else if(!util_strcmp(str, "f"))
       result = FALSE;
+   else if(!util_strcmp(str, "F"))
+      result = FALSE;
    else if(!util_strcmp(str, "false"))
       result = FALSE;
+   else if(!util_strcmp(str, "FALSE"))
+      result = FALSE;
    else
       result = TRUE;
 
-   debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
+   if (debug_get_option_should_print())
+      debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
    
    return result;
 }
@@ -311,7 +152,7 @@ debug_get_num_option(const char *name, long dfault)
    long result;
    const char *str;
    
-   str = _debug_get_option(name);
+   str = os_get_option(name);
    if(!str)
       result = dfault;
    else {
@@ -332,12 +173,50 @@ debug_get_num_option(const char *name, long dfault)
       }
       result *= sign;
    }
-   
-   debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
+
+   if (debug_get_option_should_print())
+      debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
 
    return result;
 }
 
+static boolean str_has_option(const char *str, const char *name)
+{
+   const char *substr;
+
+   /* OPTION=all */
+   if (!util_strcmp(str, "all")) {
+      return TRUE;
+   }
+
+   /* OPTION=name */
+   if (!util_strcmp(str, name)) {
+      return TRUE;
+   }
+
+   substr = util_strstr(str, name);
+
+   if (substr) {
+      unsigned name_len = strlen(name);
+
+      /* OPTION=name,... */
+      if (substr == str && substr[name_len] == ',') {
+         return TRUE;
+      }
+
+      /* OPTION=...,name */
+      if (substr+name_len == str+strlen(str) && substr[-1] == ',') {
+         return TRUE;
+      }
+
+      /* OPTION=...,name,... */
+      if (substr[-1] == ',' && substr[name_len] == ',') {
+         return TRUE;
+      }
+   }
+
+   return FALSE;
+}
 
 unsigned long
 debug_get_flags_option(const char *name, 
@@ -346,31 +225,37 @@ debug_get_flags_option(const char *name,
 {
    unsigned long result;
    const char *str;
+   const struct debug_named_value *orig = flags;
+   int namealign = 0;
    
-   str = _debug_get_option(name);
+   str = os_get_option(name);
    if(!str)
       result = dfault;
    else if (!util_strcmp(str, "help")) {
       result = dfault;
-      while (flags->name) {
-         debug_printf("%s: help for %s: %s [0x%lx]\n", __FUNCTION__, name, flags->name, flags->value);
-         flags++;
-      }
+      _debug_printf("%s: help for %s:\n", __FUNCTION__, name);
+      for (; flags->name; ++flags)
+         namealign = MAX2(namealign, strlen(flags->name));
+      for (flags = orig; flags->name; ++flags)
+         _debug_printf("| %*s [0x%0*lx]%s%s\n", namealign, flags->name,
+                      (int)sizeof(unsigned long)*CHAR_BIT/4, flags->value,
+                      flags->desc ? " " : "", flags->desc ? flags->desc : "");
    }
    else {
       result = 0;
       while( flags->name ) {
-        if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
+        if (str_has_option(str, flags->name))
            result |= flags->value;
         ++flags;
       }
    }
 
-   if (str) {
-      debug_printf("%s: %s = 0x%lx (%s)\n", __FUNCTION__, name, result, str);
-   }
-   else {
-      debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
+   if (debug_get_option_should_print()) {
+      if (str) {
+         debug_printf("%s: %s = 0x%lx (%s)\n", __FUNCTION__, name, result, str);
+      } else {
+         debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
+      }
    }
 
    return result;
@@ -388,7 +273,7 @@ void _debug_assert_fail(const char *expr,
 #else
    if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
 #endif
-      debug_break();
+      os_abort();
    else
       _debug_printf("continuing...\n");
 }
@@ -453,7 +338,8 @@ debug_dump_flags(const struct debug_named_value *names,
            util_strncat(output, "|", sizeof(output));
         else
            first = 0;
-        util_strncat(output, names->name, sizeof(output));
+        util_strncat(output, names->name, sizeof(output) - 1);
+        output[sizeof(output) - 1] = '\0';
         value &= ~names->value;
       }
       ++names;
@@ -466,7 +352,8 @@ debug_dump_flags(const struct debug_named_value *names,
         first = 0;
       
       util_snprintf(rest, sizeof(rest), "0x%08lx", value);
-      util_strncat(output, rest, sizeof(output));
+      util_strncat(output, rest, sizeof(output) - 1);
+      output[sizeof(output) - 1] = '\0';
    }
    
    if(first)
@@ -476,132 +363,84 @@ debug_dump_flags(const struct debug_named_value *names,
 }
 
 
-static const struct debug_named_value pipe_format_names[] = {
 #ifdef DEBUG
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_NONE),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_A1R5G5B5_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_A4R4G4B4_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R5G6B5_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_A2B10G10R10_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_I8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_L16_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR_REV),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_Z16_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_FLOAT),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_S8Z24_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24S8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_X8Z24_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24X8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_S8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R64_FLOAT),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64_FLOAT),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64_FLOAT),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64A64_FLOAT),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_FLOAT),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_FLOAT),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_FLOAT),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_FLOAT),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_UNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_USCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_B6G5R5_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_A8B8G8R8_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_X8B8G8R8_SNORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SSCALED),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_SRGB),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_SRGB),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SRGB),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SRGB),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SRGB),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_SRGB),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_SRGB),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_SRGB),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_SRGB),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_X8UB8UG8SR8S_NORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_B6UG5SR5S_NORM),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGB),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGBA),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_RGBA),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_RGBA),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_SRGB),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_SRGBA),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_SRGBA),
-   DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_SRGBA),
+void debug_print_format(const char *msg, unsigned fmt )
+{
+   debug_printf("%s: %s\n", msg, util_format_name(fmt));
+}
+#endif
+
+
+
+static const struct debug_named_value pipe_prim_names[] = {
+#ifdef DEBUG
+   DEBUG_NAMED_VALUE(PIPE_PRIM_POINTS),
+   DEBUG_NAMED_VALUE(PIPE_PRIM_LINES),
+   DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_LOOP),
+   DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP),
+   DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES),
+   DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP),
+   DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_FAN),
+   DEBUG_NAMED_VALUE(PIPE_PRIM_QUADS),
+   DEBUG_NAMED_VALUE(PIPE_PRIM_QUAD_STRIP),
+   DEBUG_NAMED_VALUE(PIPE_PRIM_POLYGON),
 #endif
    DEBUG_NAMED_VALUE_END
 };
 
+
+const char *u_prim_name( unsigned prim )
+{
+   return debug_dump_enum(pipe_prim_names, prim);
+}
+
+
+
 #ifdef DEBUG
-void debug_print_format(const char *msg, unsigned fmt )
+int fl_indent = 0;
+const char* fl_function[1024];
+
+int debug_funclog_enter(const char* f, const int line, const char* file)
 {
-   debug_printf("%s: %s\n", msg, debug_dump_enum(pipe_format_names, fmt)); 
+   int i;
+
+   for (i = 0; i < fl_indent; i++)
+      debug_printf("  ");
+   debug_printf("%s\n", f);
+
+   assert(fl_indent < 1023);
+   fl_function[fl_indent++] = f;
+
+   return 0;
 }
-#endif
 
-const char *pf_name( enum pipe_format format )
+void debug_funclog_exit(const char* f, const int line, const char* file)
 {
-   return debug_dump_enum(pipe_format_names, format);
+   --fl_indent;
+   assert(fl_indent >= 0);
+   assert(fl_function[fl_indent] == f);
 }
 
+void debug_funclog_enter_exit(const char* f, const int line, const char* file)
+{
+   int i;
+   for (i = 0; i < fl_indent; i++)
+      debug_printf("  ");
+   debug_printf("%s\n", f);
+}
+#endif
+
+
 
 #ifdef DEBUG
+/**
+ * Dump an image to a .raw or .ppm file (depends on OS).
+ * \param format  PIPE_FORMAT_x
+ * \param cpp  bytes per pixel
+ * \param width  width in pixels
+ * \param height height in pixels
+ * \param stride  row stride in bytes
+ */
 void debug_dump_image(const char *prefix,
                       unsigned format, unsigned cpp,
                       unsigned width, unsigned height,
@@ -643,43 +482,115 @@ void debug_dump_image(const char *prefix,
    }
       
    EngUnmapFile(iFile);
+#elif defined(PIPE_OS_UNIX)
+   /* write a ppm file */
+   char filename[256];
+   FILE *f;
+
+   util_snprintf(filename, sizeof(filename), "%s.ppm", prefix);
+
+   f = fopen(filename, "w");
+   if (f) {
+      int i, x, y;
+      int r, g, b;
+      const uint8_t *ptr = (uint8_t *) data;
+
+      /* XXX this is a hack */
+      switch (format) {
+      case PIPE_FORMAT_B8G8R8A8_UNORM:
+         r = 2;
+         g = 1;
+         b = 0;
+         break;
+      default:
+         r = 0;
+         g = 1;
+         b = 1;
+      }
+
+      fprintf(f, "P6\n");
+      fprintf(f, "# ppm-file created by osdemo.c\n");
+      fprintf(f, "%i %i\n", width, height);
+      fprintf(f, "255\n");
+      fclose(f);
+
+      f = fopen(filename, "ab");  /* reopen in binary append mode */
+      for (y = 0; y < height; y++) {
+         for (x = 0; x < width; x++) {
+            i = y * stride + x * cpp;
+            fputc(ptr[i + r], f); /* write red */
+            fputc(ptr[i + g], f); /* write green */
+            fputc(ptr[i + b], f); /* write blue */
+         }
+      }
+      fclose(f);
+   }
+   else {
+      fprintf(stderr, "Can't open %s for writing\n", filename);
+   }
 #endif
 }
 
-void debug_dump_surface(const char *prefix,
-                        struct pipe_surface *surface)     
+/* FIXME: dump resources, not surfaces... */
+void debug_dump_surface(struct pipe_context *pipe,
+                        const char *prefix,
+                        struct pipe_surface *surface)
 {
-   struct pipe_texture *texture;
-   struct pipe_screen *screen;
+   struct pipe_resource *texture;
    struct pipe_transfer *transfer;
    void *data;
 
    if (!surface)
       return;
 
+   /* XXX: this doesn't necessarily work, as the driver may be using
+    * temporary storage for the surface which hasn't been propagated
+    * back into the texture.  Need to nail down the semantics of views
+    * and transfers a bit better before we can say if extra work needs
+    * to be done here:
+    */
    texture = surface->texture;
-   screen = texture->screen;
 
-   transfer = screen->get_tex_transfer(screen, texture, surface->face,
-                                       surface->level, surface->zslice,
-                                       PIPE_TRANSFER_READ, 0, 0, surface->width,
-                                       surface->height);
-   
-   data = screen->transfer_map(screen, transfer);
+   transfer = pipe_get_transfer(pipe, texture, surface->u.tex.level,
+                                surface->u.tex.first_layer,
+                                PIPE_TRANSFER_READ,
+                                0, 0, surface->width, surface->height);
+
+   data = pipe->transfer_map(pipe, transfer);
    if(!data)
       goto error;
-   
-   debug_dump_image(prefix, 
+
+   debug_dump_image(prefix,
                     texture->format,
-                    util_format_get_blocksize(texture->format), 
-                    util_format_get_nblocksx(texture->format, transfer->width),
-                    util_format_get_nblocksy(texture->format, transfer->height),
+                    util_format_get_blocksize(texture->format),
+                    util_format_get_nblocksx(texture->format, surface->width),
+                    util_format_get_nblocksy(texture->format, surface->height),
                     transfer->stride,
                     data);
-   
-   screen->transfer_unmap(screen, transfer);
+
+   pipe->transfer_unmap(pipe, transfer);
 error:
-   screen->tex_transfer_destroy(transfer);
+   pipe->transfer_destroy(pipe, transfer);
+}
+
+
+void debug_dump_texture(struct pipe_context *pipe,
+                        const char *prefix,
+                        struct pipe_resource *texture)
+{
+   struct pipe_surface *surface, surf_tmpl;
+
+   if (!texture)
+      return;
+
+   /* XXX for now, just dump image for layer=0, level=0 */
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   u_surface_default_template(&surf_tmpl, texture, 0 /* no bind flag - not a surface */);
+   surface = pipe->create_surface(pipe, texture, &surf_tmpl);
+   if (surface) {
+      debug_dump_surface(pipe, prefix, surface);
+      pipe->surface_destroy(pipe, surface);
+   }
 }
 
 
@@ -715,27 +626,27 @@ struct bmp_rgb_quad {
 };
 
 void
-debug_dump_surface_bmp(const char *filename,
+debug_dump_surface_bmp(struct pipe_context *pipe,
+                       const char *filename,
                        struct pipe_surface *surface)
 {
 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
    struct pipe_transfer *transfer;
-   struct pipe_texture *texture = surface->texture;
-   struct pipe_screen *screen = texture->screen;
+   struct pipe_resource *texture = surface->texture;
 
-   transfer = screen->get_tex_transfer(screen, texture, surface->face,
-                                       surface->level, surface->zslice,
-                                       PIPE_TRANSFER_READ, 0, 0, surface->width,
-                                       surface->height);
+   transfer = pipe_get_transfer(pipe, texture, surface->u.tex.level,
+                                surface->u.tex.first_layer, PIPE_TRANSFER_READ,
+                                0, 0, surface->width, surface->height);
 
-   debug_dump_transfer_bmp(filename, transfer);
+   debug_dump_transfer_bmp(pipe, filename, transfer);
 
-   screen->tex_transfer_destroy(transfer);
+   pipe->transfer_destroy(pipe, transfer);
 #endif
 }
 
 void
-debug_dump_transfer_bmp(const char *filename,
+debug_dump_transfer_bmp(struct pipe_context *pipe,
+                        const char *filename,
                         struct pipe_transfer *transfer)
 {
 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
@@ -744,17 +655,20 @@ debug_dump_transfer_bmp(const char *filename,
    if (!transfer)
       goto error1;
 
-   rgba = MALLOC(transfer->width*transfer->height*4*sizeof(float));
+   rgba = MALLOC(transfer->box.width *
+                transfer->box.height *
+                transfer->box.depth *
+                4*sizeof(float));
    if(!rgba)
       goto error1;
 
-   pipe_get_tile_rgba(transfer, 0, 0,
-                      transfer->width, transfer->height,
+   pipe_get_tile_rgba(pipe, transfer, 0, 0,
+                      transfer->box.width, transfer->box.height,
                       rgba);
 
    debug_dump_float_rgba_bmp(filename,
-                             transfer->width, transfer->height,
-                             rgba, transfer->width);
+                             transfer->box.width, transfer->box.height,
+                             rgba, transfer->box.width);
 
    FREE(rgba);
 error1:
@@ -768,7 +682,7 @@ debug_dump_float_rgba_bmp(const char *filename,
                           float *rgba, unsigned stride)
 {
 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
-   struct util_stream *stream;
+   struct os_stream *stream;
    struct bmp_file_header bmfh;
    struct bmp_info_header bmih;
    unsigned x, y;
@@ -794,12 +708,12 @@ debug_dump_float_rgba_bmp(const char *filename,
    bmih.biClrUsed = 0;
    bmih.biClrImportant = 0;
 
-   stream = util_stream_create(filename, bmfh.bfSize);
+   stream = os_file_stream_create(filename);
    if(!stream)
       goto error1;
 
-   util_stream_write(stream, &bmfh, 14);
-   util_stream_write(stream, &bmih, 40);
+   os_stream_write(stream, &bmfh, 14);
+   os_stream_write(stream, &bmih, 40);
 
    y = height;
    while(y--) {
@@ -811,11 +725,11 @@ debug_dump_float_rgba_bmp(const char *filename,
          pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
          pixel.rgbBlue  = float_to_ubyte(ptr[x*4 + 2]);
          pixel.rgbAlpha = 255;
-         util_stream_write(stream, &pixel, 4);
+         os_stream_write(stream, &pixel, 4);
       }
    }
 
-   util_stream_close(stream);
+   os_stream_close(stream);
 error1:
    ;
 #endif