Merge commit 'origin/gallium-0.1' into gallium-0.2
[mesa.git] / src / gallium / auxiliary / util / p_debug.c
index 8ef288019137a132b82cb31ce69e1d3ba6696611..0d019808b09638bbda97f40ef4c76d4ce7a39202 100644 (file)
 
 #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>
+
 #else
+
 #include <stdio.h>
 #include <stdlib.h>
+
 #endif
 
 #include "pipe/p_compiler.h" 
-#include "pipe/p_util.h" 
 #include "pipe/p_debug.h" 
 #include "pipe/p_format.h" 
+#include "pipe/p_state.h" 
+#include "pipe/p_inlines.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" 
 
 
 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
@@ -59,24 +83,63 @@ _EngDebugPrint(const char *format, ...)
 
 void _debug_vprintf(const char *format, va_list ap)
 {
-#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
-#ifndef WINCE
+#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 + 1] = {'\0'};
+   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) || strchr(buf + len, '\n')) {
+   if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
       _EngDebugPrint("%s", buf);
       buf[0] = '\0';
    }
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+   /* 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 + 1] = {'\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);
+      buf[0] = '\0';
+   }
+#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
-   /* TODO: Implement debug print for WINCE */
+   ret = vsprintf_s(buf, 512, format, ap);   
+   if(ret < 0){   
+       sprintf_s(buf, 512, "Cant handle debug print!");   
+       ret = 25;
+   }
 #endif
-#else
+   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 */
+#ifdef DEBUG
    vfprintf(stderr, format, ap);
 #endif
+#endif
 }
 
 
@@ -100,11 +163,11 @@ void debug_print_blob( const char *name,
 
 void _debug_break(void) 
 {
-#if (defined(__i386__) || defined(__386__)) && defined(__GNUC__)
+#if defined(PIPE_ARCH_X86) && defined(PIPE_CC_GCC)
    __asm("int3");
-#elif (defined(__i386__) || defined(__386__)) && defined(__MSC__)
+#elif defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)
    _asm {int 3};
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) && !defined(WINCE)
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
    EngDebugBreak();
 #else
    abort();
@@ -149,20 +212,19 @@ copy(char *dst, const char *start, const char *end, size_t n)
 #endif
 
 
-const char *
-debug_get_option(const char *name, const char *dfault)
+static INLINE const char *
+_debug_get_option(const char *name)
 {
-   const char *result;
-#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
+#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];
    
-   result = dfault;
-   /* XXX: this creates the file if it does not exists, so it must either be
-    * disabled on release versions, or put in a less conspicuous place.
-    */
    pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile);
    if(pMap) {
       sol = (const char *)pMap;
@@ -183,12 +245,26 @@ debug_get_option(const char *name, const char *dfault)
       }
       EngUnmapFile(iFile);
    }
+   return result;
 #else
-   
-   result = getenv(name);
+   return NULL;
+#endif
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) 
+   /* TODO: implement */
+   return NULL;
+#else
+   return getenv(name);
+#endif
+}
+
+const char *
+debug_get_option(const char *name, const char *dfault)
+{
+   const char *result;
+
+   result = _debug_get_option(name);
    if(!result)
       result = dfault;
-#endif
       
    debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
    
@@ -198,20 +274,20 @@ 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, NULL);
+   const char *str = _debug_get_option(name);
    boolean result;
    
    if(str == NULL)
       result = dfault;
-   else if(!strcmp(str, "n"))
+   else if(!util_strcmp(str, "n"))
       result = FALSE;
-   else if(!strcmp(str, "no"))
+   else if(!util_strcmp(str, "no"))
       result = FALSE;
-   else if(!strcmp(str, "0"))
+   else if(!util_strcmp(str, "0"))
       result = FALSE;
-   else if(!strcmp(str, "f"))
+   else if(!util_strcmp(str, "f"))
       result = FALSE;
-   else if(!strcmp(str, "false"))
+   else if(!util_strcmp(str, "false"))
       result = FALSE;
    else
       result = TRUE;
@@ -225,8 +301,34 @@ debug_get_bool_option(const char *name, boolean dfault)
 long
 debug_get_num_option(const char *name, long dfault)
 {
-   /* FIXME */
-   return dfault;
+   long result;
+   const char *str;
+   
+   str = _debug_get_option(name);
+   if(!str)
+      result = dfault;
+   else {
+      long sign;
+      char c;
+      c = *str++;
+      if(c == '-') {
+        sign = -1;
+        c = *str++;
+      } 
+      else {
+        sign = 1;
+      }
+      result = 0;
+      while('0' <= c && c <= '9') {
+        result = result*10 + (c - '0');
+        c = *str++;
+      }
+      result *= sign;
+   }
+   
+   debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
+
+   return result;
 }
 
 
@@ -238,19 +340,31 @@ debug_get_flags_option(const char *name,
    unsigned long result;
    const char *str;
    
-   str = debug_get_option(name, NULL);
+   str = _debug_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++;
+      }
+   }
    else {
       result = 0;
       while( flags->name ) {
-        if (!strcmp(str, "all") || strstr(str, flags->name ))
+        if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
            result |= flags->value;
         ++flags;
       }
    }
 
-   debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
+   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;
 }
@@ -262,7 +376,11 @@ void _debug_assert_fail(const char *expr,
                         const char *function) 
 {
    _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
+#if defined(PIPE_OS_WINDOWS)
+   if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", FALSE))
+#else
    if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
+#endif
       debug_break();
    else
       _debug_printf("continuing...\n");
@@ -273,7 +391,7 @@ const char *
 debug_dump_enum(const struct debug_named_value *names, 
                 unsigned long value)
 {
-   static char rest[256];
+   static char rest[64];
    
    while(names->name) {
       if(names->value == value)
@@ -299,10 +417,10 @@ debug_dump_flags(const struct debug_named_value *names,
    while(names->name) {
       if((names->value & value) == names->value) {
         if (!first)
-           strncat(output, "|", sizeof(output));
+           util_strncat(output, "|", sizeof(output));
         else
            first = 0;
-        strncat(output, names->name, sizeof(output));
+        util_strncat(output, names->name, sizeof(output));
         value &= ~names->value;
       }
       ++names;
@@ -310,12 +428,12 @@ debug_dump_flags(const struct debug_named_value *names,
    
    if (value) {
       if (!first)
-        strncat(output, "|", sizeof(output));
+        util_strncat(output, "|", sizeof(output));
       else
         first = 0;
       
       util_snprintf(rest, sizeof(rest), "0x%08lx", value);
-      strncat(output, rest, sizeof(output));
+      util_strncat(output, rest, sizeof(output));
    }
    
    if(first)
@@ -325,99 +443,305 @@ 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_A8_L8_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_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),
+#endif
+   DEBUG_NAMED_VALUE_END
+};
 
+#ifdef DEBUG
+void debug_print_format(const char *msg, unsigned fmt )
+{
+   debug_printf("%s: %s\n", msg, debug_dump_enum(pipe_format_names, fmt)); 
+}
+#endif
 
+const char *pf_name( enum pipe_format format )
+{
+   return debug_dump_enum(pipe_format_names, format);
+}
 
 
-char *pf_sprint_name( char *str, enum pipe_format format )
+#ifdef DEBUG
+void debug_dump_image(const char *prefix,
+                      unsigned format, unsigned cpp,
+                      unsigned width, unsigned height,
+                      unsigned stride,
+                      const void *data)     
 {
-   strcpy( str, "PIPE_FORMAT_" );
-   switch (pf_layout( format )) {
-   case PIPE_FORMAT_LAYOUT_RGBAZS:
-      {
-         pipe_format_rgbazs_t rgbazs = (pipe_format_rgbazs_t) format;
-         uint                 i;
-         uint                 scale = 1 << (pf_exp8( rgbazs ) * 3);
-
-         for (i = 0; i < 4; i++) {
-            uint  size = pf_size_xyzw( rgbazs, i );
-
-            if (size == 0) {
-               break;
-            }
-            switch (pf_swizzle_xyzw( rgbazs, i )) {
-            case PIPE_FORMAT_COMP_R:
-               strcat( str, "R" );
-               break;
-            case PIPE_FORMAT_COMP_G:
-               strcat( str, "G" );
-               break;
-            case PIPE_FORMAT_COMP_B:
-               strcat( str, "B" );
-               break;
-            case PIPE_FORMAT_COMP_A:
-               strcat( str, "A" );
-               break;
-            case PIPE_FORMAT_COMP_0:
-               strcat( str, "0" );
-               break;
-            case PIPE_FORMAT_COMP_1:
-               strcat( str, "1" );
-               break;
-            case PIPE_FORMAT_COMP_Z:
-               strcat( str, "Z" );
-               break;
-            case PIPE_FORMAT_COMP_S:
-               strcat( str, "S" );
-               break;
-            }
-            util_snprintf( &str[strlen( str )], 32, "%u", size * scale );
-         }
-         if (i != 0) {
-            strcat( str, "_" );
-         }
-         switch (pf_type( rgbazs )) {
-         case PIPE_FORMAT_TYPE_UNKNOWN:
-            strcat( str, "NONE" );
-            break;
-         case PIPE_FORMAT_TYPE_FLOAT:
-            strcat( str, "FLOAT" );
-            break;
-         case PIPE_FORMAT_TYPE_UNORM:
-            strcat( str, "UNORM" );
-            break;
-         case PIPE_FORMAT_TYPE_SNORM:
-            strcat( str, "SNORM" );
-            break;
-         case PIPE_FORMAT_TYPE_USCALED:
-            strcat( str, "USCALED" );
-            break;
-         case PIPE_FORMAT_TYPE_SSCALED:
-            strcat( str, "SSCALED" );
-            break;
-         }
-      }
-      break;
-   case PIPE_FORMAT_LAYOUT_YCBCR:
-      {
-         pipe_format_ycbcr_t  ycbcr = (pipe_format_ycbcr_t) format;
+#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
+   static unsigned no = 0; 
+   char filename[256];
+   WCHAR wfilename[sizeof(filename)];
+   ULONG_PTR iFile = 0;
+   struct {
+      unsigned format;
+      unsigned cpp;
+      unsigned width;
+      unsigned height;
+   } header;
+   unsigned char *pMap = NULL;
+   unsigned i;
 
-         strcat( str, "YCBCR" );
-         if (pf_rev( ycbcr )) {
-            strcat( str, "_REV" );
-         }
-      }
-      break;
+   util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix);
+   for(i = 0; i < sizeof(filename); ++i)
+      wfilename[i] = (WCHAR)filename[i];
+   
+   pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + height*width*cpp, &iFile);
+   if(!pMap)
+      return;
+   
+   header.format = format;
+   header.cpp = cpp;
+   header.width = width;
+   header.height = height;
+   memcpy(pMap, &header, sizeof(header));
+   pMap += sizeof(header);
+   
+   for(i = 0; i < height; ++i) {
+      memcpy(pMap, (unsigned char *)data + stride*i, cpp*width);
+      pMap += cpp*width;
    }
-   return str;
+      
+   EngUnmapFile(iFile);
+#endif
 }
 
+void debug_dump_surface(const char *prefix,
+                        struct pipe_surface *surface)     
+{
+   unsigned surface_usage;
+   void *data;
 
-void debug_print_format(const char *msg, unsigned fmt )
+   if (!surface)
+      goto error1;
+
+   /* XXX: force mappable surface */
+   surface_usage = surface->usage;
+   surface->usage |= PIPE_BUFFER_USAGE_CPU_READ;
+   
+   data = pipe_surface_map(surface, 
+                           PIPE_BUFFER_USAGE_CPU_READ);
+   if(!data)
+      goto error2;
+   
+   debug_dump_image(prefix, 
+                    surface->format,
+                    surface->block.size, 
+                    surface->nblocksx,
+                    surface->nblocksy,
+                    surface->stride,
+                    data);
+   
+   pipe_surface_unmap(surface);
+error2:
+   surface->usage = surface_usage;
+error1:
+   ;
+}
+
+
+#pragma pack(push,2)
+struct bmp_file_header {
+   uint16_t bfType;
+   uint32_t bfSize;
+   uint16_t bfReserved1;
+   uint16_t bfReserved2;
+   uint32_t bfOffBits;
+};
+#pragma pack(pop)
+
+struct bmp_info_header {
+   uint32_t biSize;
+   int32_t biWidth;
+   int32_t biHeight;
+   uint16_t biPlanes;
+   uint16_t biBitCount;
+   uint32_t biCompression;
+   uint32_t biSizeImage;
+   int32_t biXPelsPerMeter;
+   int32_t biYPelsPerMeter;
+   uint32_t biClrUsed;
+   uint32_t biClrImportant;
+};
+
+struct bmp_rgb_quad {
+   uint8_t rgbBlue;
+   uint8_t rgbGreen;
+   uint8_t rgbRed;
+   uint8_t rgbAlpha;
+};
+
+void 
+debug_dump_surface_bmp(const char *filename,
+                       struct pipe_surface *surface)
 {
-   char fmtstr[80];
-   pf_sprint_name(fmtstr, (enum pipe_format)fmt);
+#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
+   struct util_stream *stream;
+   unsigned surface_usage;
+   struct bmp_file_header bmfh;
+   struct bmp_info_header bmih;
+   float *rgba;
+   unsigned x, y;
+
+   if (!surface)
+      goto error1;
+
+   rgba = MALLOC(surface->width*4*sizeof(float));
+   if(!rgba)
+      goto error1;
+   
+   bmfh.bfType = 0x4d42;
+   bmfh.bfSize = 14 + 40 + surface->height*surface->width*4;
+   bmfh.bfReserved1 = 0;
+   bmfh.bfReserved2 = 0;
+   bmfh.bfOffBits = 14 + 40;
+   
+   bmih.biSize = 40;
+   bmih.biWidth = surface->width;
+   bmih.biHeight = surface->height;
+   bmih.biPlanes = 1;
+   bmih.biBitCount = 32;
+   bmih.biCompression = 0;
+   bmih.biSizeImage = surface->height*surface->width*4;
+   bmih.biXPelsPerMeter = 0;
+   bmih.biYPelsPerMeter = 0;
+   bmih.biClrUsed = 0;
+   bmih.biClrImportant = 0;
+   
+   stream = util_stream_create(filename, bmfh.bfSize);
+   if(!stream)
+      goto error2;
+   
+   util_stream_write(stream, &bmfh, 14);
+   util_stream_write(stream, &bmih, 40);
+   
+   /* XXX: force mappable surface */
+   surface_usage = surface->usage;
+   surface->usage |= PIPE_BUFFER_USAGE_CPU_READ;
+
+   y = surface->height;
+   while(y--) {
+      pipe_get_tile_rgba(surface,
+                         0, y, surface->width, 1,
+                         rgba);
+      for(x = 0; x < surface->width; ++x)
+      {
+         struct bmp_rgb_quad pixel;
+         pixel.rgbRed   = float_to_ubyte(rgba[x*4 + 0]);
+         pixel.rgbGreen = float_to_ubyte(rgba[x*4 + 1]);
+         pixel.rgbBlue  = float_to_ubyte(rgba[x*4 + 2]);
+         pixel.rgbAlpha = float_to_ubyte(rgba[x*4 + 3]);
+         util_stream_write(stream, &pixel, 4);
+      }  
+   }
+   
+   surface->usage = surface_usage;
 
-   debug_printf("%s: %s\n", msg, fmtstr); 
+   util_stream_close(stream);
+error2:
+   FREE(rgba);
+error1:
+   ;
+#endif
 }
+
+#endif