p_debug.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028 
00029 #include "pipe/p_config.h" 
00030 
00031 #include <stdarg.h>
00032 
00033 
00034 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
00035 
00036 #include <windows.h>
00037 #include <winddi.h>
00038 
00039 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
00040 
00041 #ifndef WIN32_LEAN_AND_MEAN
00042 #define WIN32_LEAN_AND_MEAN      // Exclude rarely-used stuff from Windows headers
00043 #endif
00044 #include <windows.h>
00045 #include <stdio.h>
00046 
00047 #else
00048 
00049 #include <stdio.h>
00050 #include <stdlib.h>
00051 
00052 #endif
00053 
00054 
00055 #include "pipe/p_compiler.h" 
00056 #include "pipe/p_debug.h" 
00057 #include "pipe/p_format.h" 
00058 #include "pipe/p_state.h" 
00059 #include "pipe/p_inlines.h" 
00060 #include "util/u_memory.h" 
00061 #include "util/u_string.h" 
00062 #include "util/u_stream.h" 
00063 #include "util/u_math.h" 
00064 #include "util/u_tile.h" 
00065 
00066 
00067 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
00068 static INLINE void 
00069 _EngDebugPrint(const char *format, ...)
00070 {
00071    va_list ap;
00072    va_start(ap, format);
00073    EngDebugPrint("", (PCHAR)format, ap);
00074    va_end(ap);
00075 }
00076 #endif
00077 
00078 
00079 void _debug_vprintf(const char *format, va_list ap)
00080 {
00081 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
00082    /* EngDebugPrint does not handle float point arguments, so we need to use
00083     * our own vsnprintf implementation. It is also very slow, so buffer until
00084     * we find a newline. */
00085    static char buf[512] = {'\0'};
00086    size_t len = strlen(buf);
00087    int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
00088    if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
00089       _EngDebugPrint("%s", buf);
00090       buf[0] = '\0';
00091    }
00092 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
00093    /* EngDebugPrint does not handle float point arguments, so we need to use
00094     * our own vsnprintf implementation. It is also very slow, so buffer until
00095     * we find a newline. */
00096    static char buf[512 + 1] = {'\0'};
00097    size_t len = strlen(buf);
00098    int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
00099    if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
00100       OutputDebugStringA(buf);
00101       buf[0] = '\0';
00102    }
00103 
00104    
00105    if(GetConsoleWindow() && !IsDebuggerPresent()) {
00106       fflush(stdout);
00107       vfprintf(stderr, format, ap);
00108       fflush(stderr);
00109    }
00110    
00111 
00112 #elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) 
00113    /* TODO */
00114 #else /* !PIPE_SUBSYSTEM_WINDOWS */
00115 #ifdef DEBUG
00116    vfprintf(stderr, format, ap);
00117 #endif
00118 #endif
00119 }
00120 
00121 
00122 #ifdef DEBUG
00123 void debug_print_blob( const char *name,
00124                        const void *blob,
00125                        unsigned size )
00126 {
00127    const unsigned *ublob = (const unsigned *)blob;
00128    unsigned i;
00129 
00130    debug_printf("%s (%d dwords%s)\n", name, size/4,
00131                 size%4 ? "... plus a few bytes" : "");
00132 
00133    for (i = 0; i < size/4; i++) {
00134       debug_printf("%d:\t%08x\n", i, ublob[i]);
00135    }
00136 }
00137 #endif
00138 
00139 
00140 void _debug_break(void) 
00141 {
00142 #if defined(PIPE_ARCH_X86) && defined(PIPE_CC_GCC)
00143    __asm("int3");
00144 #elif defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)
00145    _asm {int 3};
00146 #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
00147    EngDebugBreak();
00148 #else
00149    abort();
00150 #endif
00151 }
00152 
00153 
00154 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
00155 static const char *
00156 find(const char *start, const char *end, char c) 
00157 {
00158    const char *p;
00159    for(p = start; !end || p != end; ++p) {
00160       if(*p == c)
00161          return p;
00162       if(*p < 32)
00163          break;
00164    }
00165    return NULL;
00166 }
00167 
00168 static int 
00169 compare(const char *start, const char *end, const char *s)
00170 {
00171    const char *p, *q;
00172    for(p = start, q = s; p != end && *q != '\0'; ++p, ++q) {
00173       if(*p != *q)
00174          return 0;
00175    }
00176    return p == end && *q == '\0';
00177 }
00178 
00179 static void 
00180 copy(char *dst, const char *start, const char *end, size_t n) 
00181 {
00182    const char *p;
00183    char *q;
00184    for(p = start, q = dst, n = n - 1; p != end && n; ++p, ++q, --n)
00185       *q = *p;
00186    *q = '\0';
00187 }
00188 #endif
00189 
00190 
00191 static INLINE const char *
00192 _debug_get_option(const char *name)
00193 {
00194 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
00195    /* EngMapFile creates the file if it does not exists, so it must either be
00196     * disabled on release versions (or put in a less conspicuous place). */
00197 #ifdef DEBUG
00198    const char *result = NULL;
00199    ULONG_PTR iFile = 0;
00200    const void *pMap = NULL;
00201    const char *sol, *eol, *sep;
00202    static char output[1024];
00203    
00204    pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile);
00205    if(pMap) {
00206       sol = (const char *)pMap;
00207       while(1) {
00208          /* TODO: handle LF line endings */
00209          eol = find(sol, NULL, '\r');
00210          if(!eol || eol == sol)
00211             break;
00212          sep = find(sol, eol, '=');
00213          if(!sep)
00214             break;
00215          if(compare(sol, sep, name)) {
00216             copy(output, sep + 1, eol, sizeof(output));
00217             result = output;
00218             break;
00219          }
00220          sol = eol + 2;
00221       }
00222       EngUnmapFile(iFile);
00223    }
00224    return result;
00225 #else
00226    return NULL;
00227 #endif
00228 #elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) 
00229    /* TODO: implement */
00230    return NULL;
00231 #else
00232    return getenv(name);
00233 #endif
00234 }
00235 
00236 const char *
00237 debug_get_option(const char *name, const char *dfault)
00238 {
00239    const char *result;
00240 
00241    result = _debug_get_option(name);
00242    if(!result)
00243       result = dfault;
00244       
00245    debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
00246    
00247    return result;
00248 }
00249 
00250 boolean
00251 debug_get_bool_option(const char *name, boolean dfault)
00252 {
00253    const char *str = _debug_get_option(name);
00254    boolean result;
00255    
00256    if(str == NULL)
00257       result = dfault;
00258    else if(!util_strcmp(str, "n"))
00259       result = FALSE;
00260    else if(!util_strcmp(str, "no"))
00261       result = FALSE;
00262    else if(!util_strcmp(str, "0"))
00263       result = FALSE;
00264    else if(!util_strcmp(str, "f"))
00265       result = FALSE;
00266    else if(!util_strcmp(str, "false"))
00267       result = FALSE;
00268    else
00269       result = TRUE;
00270 
00271    debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
00272    
00273    return result;
00274 }
00275 
00276 
00277 long
00278 debug_get_num_option(const char *name, long dfault)
00279 {
00280    long result;
00281    const char *str;
00282    
00283    str = _debug_get_option(name);
00284    if(!str)
00285       result = dfault;
00286    else {
00287       long sign;
00288       char c;
00289       c = *str++;
00290       if(c == '-') {
00291          sign = -1;
00292          c = *str++;
00293       } 
00294       else {
00295          sign = 1;
00296       }
00297       result = 0;
00298       while('0' <= c && c <= '9') {
00299          result = result*10 + (c - '0');
00300          c = *str++;
00301       }
00302       result *= sign;
00303    }
00304    
00305    debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
00306 
00307    return result;
00308 }
00309 
00310 
00311 unsigned long
00312 debug_get_flags_option(const char *name, 
00313                        const struct debug_named_value *flags,
00314                        unsigned long dfault)
00315 {
00316    unsigned long result;
00317    const char *str;
00318    
00319    str = _debug_get_option(name);
00320    if(!str)
00321       result = dfault;
00322    else {
00323       result = 0;
00324       while( flags->name ) {
00325          if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
00326             result |= flags->value;
00327          ++flags;
00328       }
00329    }
00330 
00331    debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
00332 
00333    return result;
00334 }
00335 
00336 
00337 void _debug_assert_fail(const char *expr, 
00338                         const char *file, 
00339                         unsigned line, 
00340                         const char *function) 
00341 {
00342    _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
00343 #if defined(PIPE_OS_WINDOWS) && !defined(PIPE_SUBSYSTEM_WINDOWS_USER)
00344    if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", FALSE))
00345 #else
00346    if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
00347 #endif
00348       debug_break();
00349    else
00350       _debug_printf("continuing...\n");
00351 }
00352 
00353 
00354 const char *
00355 debug_dump_enum(const struct debug_named_value *names, 
00356                 unsigned long value)
00357 {
00358    static char rest[64];
00359    
00360    while(names->name) {
00361       if(names->value == value)
00362          return names->name;
00363       ++names;
00364    }
00365 
00366    util_snprintf(rest, sizeof(rest), "0x%08lx", value);
00367    return rest;
00368 }
00369 
00370 
00371 const char *
00372 debug_dump_flags(const struct debug_named_value *names, 
00373                  unsigned long value)
00374 {
00375    static char output[4096];
00376    static char rest[256];
00377    int first = 1;
00378 
00379    output[0] = '\0';
00380 
00381    while(names->name) {
00382       if((names->value & value) == names->value) {
00383          if (!first)
00384             util_strncat(output, "|", sizeof(output));
00385          else
00386             first = 0;
00387          util_strncat(output, names->name, sizeof(output));
00388          value &= ~names->value;
00389       }
00390       ++names;
00391    }
00392    
00393    if (value) {
00394       if (!first)
00395          util_strncat(output, "|", sizeof(output));
00396       else
00397          first = 0;
00398       
00399       util_snprintf(rest, sizeof(rest), "0x%08lx", value);
00400       util_strncat(output, rest, sizeof(output));
00401    }
00402    
00403    if(first)
00404       return "0";
00405    
00406    return output;
00407 }
00408 
00409 
00410 static const struct debug_named_value pipe_format_names[] = {
00411 #ifdef DEBUG
00412    DEBUG_NAMED_VALUE(PIPE_FORMAT_NONE),
00413    DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_UNORM),
00414    DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_UNORM),
00415    DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_UNORM),
00416    DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_UNORM),
00417    DEBUG_NAMED_VALUE(PIPE_FORMAT_A1R5G5B5_UNORM),
00418    DEBUG_NAMED_VALUE(PIPE_FORMAT_A4R4G4B4_UNORM),
00419    DEBUG_NAMED_VALUE(PIPE_FORMAT_R5G6B5_UNORM),
00420    DEBUG_NAMED_VALUE(PIPE_FORMAT_A2B10G10R10_UNORM),
00421    DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_UNORM),
00422    DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_UNORM),
00423    DEBUG_NAMED_VALUE(PIPE_FORMAT_I8_UNORM),
00424    DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_UNORM),
00425    DEBUG_NAMED_VALUE(PIPE_FORMAT_L16_UNORM),
00426    DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR),
00427    DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR_REV),
00428    DEBUG_NAMED_VALUE(PIPE_FORMAT_Z16_UNORM),
00429    DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_UNORM),
00430    DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_FLOAT),
00431    DEBUG_NAMED_VALUE(PIPE_FORMAT_S8Z24_UNORM),
00432    DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24S8_UNORM),
00433    DEBUG_NAMED_VALUE(PIPE_FORMAT_X8Z24_UNORM),
00434    DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24X8_UNORM),
00435    DEBUG_NAMED_VALUE(PIPE_FORMAT_S8_UNORM),
00436    DEBUG_NAMED_VALUE(PIPE_FORMAT_R64_FLOAT),
00437    DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64_FLOAT),
00438    DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64_FLOAT),
00439    DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64A64_FLOAT),
00440    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_FLOAT),
00441    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_FLOAT),
00442    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_FLOAT),
00443    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_FLOAT),
00444    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_UNORM),
00445    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_UNORM),
00446    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_UNORM),
00447    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_UNORM),
00448    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_USCALED),
00449    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_USCALED),
00450    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_USCALED),
00451    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_USCALED),
00452    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SNORM),
00453    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SNORM),
00454    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SNORM),
00455    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SNORM),
00456    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SSCALED),
00457    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SSCALED),
00458    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SSCALED),
00459    DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SSCALED),
00460    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_UNORM),
00461    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_UNORM),
00462    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_UNORM),
00463    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_UNORM),
00464    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_USCALED),
00465    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_USCALED),
00466    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_USCALED),
00467    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_USCALED),
00468    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SNORM),
00469    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SNORM),
00470    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SNORM),
00471    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SNORM),
00472    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SSCALED),
00473    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SSCALED),
00474    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SSCALED),
00475    DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SSCALED),
00476    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_UNORM),
00477    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_UNORM),
00478    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_UNORM),
00479    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_UNORM),
00480    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_UNORM),
00481    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_USCALED),
00482    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_USCALED),
00483    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_USCALED),
00484    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_USCALED),
00485    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_USCALED),
00486    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SNORM),
00487    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SNORM),
00488    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SNORM),
00489    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SNORM),
00490    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SNORM),
00491    DEBUG_NAMED_VALUE(PIPE_FORMAT_B6G5R5_SNORM),
00492    DEBUG_NAMED_VALUE(PIPE_FORMAT_A8B8G8R8_SNORM),
00493    DEBUG_NAMED_VALUE(PIPE_FORMAT_X8B8G8R8_SNORM),
00494    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SSCALED),
00495    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SSCALED),
00496    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SSCALED),
00497    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SSCALED),
00498    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SSCALED),
00499    DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_SRGB),
00500    DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_L8_SRGB),
00501    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SRGB),
00502    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SRGB),
00503    DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SRGB),
00504    DEBUG_NAMED_VALUE(PIPE_FORMAT_X8UB8UG8SR8S_NORM),
00505    DEBUG_NAMED_VALUE(PIPE_FORMAT_B6UG5SR5S_NORM),
00506    DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGB),
00507    DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGBA),
00508    DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_RGBA),
00509    DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_RGBA),
00510 #endif
00511    DEBUG_NAMED_VALUE_END
00512 };
00513 
00514 #ifdef DEBUG
00515 void debug_print_format(const char *msg, unsigned fmt )
00516 {
00517    debug_printf("%s: %s\n", msg, debug_dump_enum(pipe_format_names, fmt)); 
00518 }
00519 #endif
00520 
00521 const char *pf_name( enum pipe_format format )
00522 {
00523    return debug_dump_enum(pipe_format_names, format);
00524 }
00525 
00526 
00527 #ifdef DEBUG
00528 void debug_dump_image(const char *prefix,
00529                       unsigned format, unsigned cpp,
00530                       unsigned width, unsigned height,
00531                       unsigned stride,
00532                       const void *data)     
00533 {
00534 #ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
00535    static unsigned no = 0; 
00536    char filename[256];
00537    WCHAR wfilename[sizeof(filename)];
00538    ULONG_PTR iFile = 0;
00539    struct {
00540       unsigned format;
00541       unsigned cpp;
00542       unsigned width;
00543       unsigned height;
00544    } header;
00545    unsigned char *pMap = NULL;
00546    unsigned i;
00547 
00548    util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix);
00549    for(i = 0; i < sizeof(filename); ++i)
00550       wfilename[i] = (WCHAR)filename[i];
00551    
00552    pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + height*width*cpp, &iFile);
00553    if(!pMap)
00554       return;
00555    
00556    header.format = format;
00557    header.cpp = cpp;
00558    header.width = width;
00559    header.height = height;
00560    memcpy(pMap, &header, sizeof(header));
00561    pMap += sizeof(header);
00562    
00563    for(i = 0; i < height; ++i) {
00564       memcpy(pMap, (unsigned char *)data + stride*i, cpp*width);
00565       pMap += cpp*width;
00566    }
00567       
00568    EngUnmapFile(iFile);
00569 #endif
00570 }
00571 
00572 void debug_dump_surface(const char *prefix,
00573                         struct pipe_surface *surface)     
00574 {
00575    unsigned surface_usage;
00576    void *data;
00577 
00578    if (!surface)
00579       goto error1;
00580 
00581    /* XXX: force mappable surface */
00582    surface_usage = surface->usage;
00583    surface->usage |= PIPE_BUFFER_USAGE_CPU_READ;
00584    
00585    data = pipe_surface_map(surface, 
00586                            PIPE_BUFFER_USAGE_CPU_READ);
00587    if(!data)
00588       goto error2;
00589    
00590    debug_dump_image(prefix, 
00591                     surface->format,
00592                     surface->block.size, 
00593                     surface->nblocksx,
00594                     surface->nblocksy,
00595                     surface->stride,
00596                     data);
00597    
00598    pipe_surface_unmap(surface);
00599 error2:
00600    surface->usage = surface_usage;
00601 error1:
00602    ;
00603 }
00604 
00605 
00606 #pragma pack(push,2)
00607 struct bmp_file_header {
00608    uint16_t bfType;
00609    uint32_t bfSize;
00610    uint16_t bfReserved1;
00611    uint16_t bfReserved2;
00612    uint32_t bfOffBits;
00613 };
00614 #pragma pack(pop)
00615 
00616 struct bmp_info_header {
00617    uint32_t biSize;
00618    int32_t biWidth;
00619    int32_t biHeight;
00620    uint16_t biPlanes;
00621    uint16_t biBitCount;
00622    uint32_t biCompression;
00623    uint32_t biSizeImage;
00624    int32_t biXPelsPerMeter;
00625    int32_t biYPelsPerMeter;
00626    uint32_t biClrUsed;
00627    uint32_t biClrImportant;
00628 };
00629 
00630 struct bmp_rgb_quad {
00631    uint8_t rgbBlue;
00632    uint8_t rgbGreen;
00633    uint8_t rgbRed;
00634    uint8_t rgbAlpha;
00635 };
00636 
00637 void 
00638 debug_dump_surface_bmp(const char *filename,
00639                        struct pipe_surface *surface)
00640 {
00641    struct util_stream *stream;
00642    unsigned surface_usage;
00643    struct bmp_file_header bmfh;
00644    struct bmp_info_header bmih;
00645    float *rgba;
00646    unsigned x, y;
00647 
00648    if (!surface)
00649       goto error1;
00650 
00651    rgba = MALLOC(surface->width*4*sizeof(float));
00652    if(!rgba)
00653       goto error1;
00654    
00655    bmfh.bfType = 0x4d42;
00656    bmfh.bfSize = 14 + 40 + surface->height*surface->width*4;
00657    bmfh.bfReserved1 = 0;
00658    bmfh.bfReserved2 = 0;
00659    bmfh.bfOffBits = 14 + 40;
00660    
00661    bmih.biSize = 40;
00662    bmih.biWidth = surface->width;
00663    bmih.biHeight = surface->height;
00664    bmih.biPlanes = 1;
00665    bmih.biBitCount = 32;
00666    bmih.biCompression = 0;
00667    bmih.biSizeImage = surface->height*surface->width*4;
00668    bmih.biXPelsPerMeter = 0;
00669    bmih.biYPelsPerMeter = 0;
00670    bmih.biClrUsed = 0;
00671    bmih.biClrImportant = 0;
00672    
00673    stream = util_stream_create(filename, bmfh.bfSize);
00674    if(!stream)
00675       goto error2;
00676    
00677    util_stream_write(stream, &bmfh, 14);
00678    util_stream_write(stream, &bmih, 40);
00679    
00680    /* XXX: force mappable surface */
00681    surface_usage = surface->usage;
00682    surface->usage |= PIPE_BUFFER_USAGE_CPU_READ;
00683 
00684    y = surface->height;
00685    while(y--) {
00686       pipe_get_tile_rgba(surface,
00687                          0, y, surface->width, 1,
00688                          rgba);
00689       for(x = 0; x < surface->width; ++x)
00690       {
00691          struct bmp_rgb_quad pixel;
00692          pixel.rgbRed   = float_to_ubyte(rgba[x*4 + 0]);
00693          pixel.rgbGreen = float_to_ubyte(rgba[x*4 + 1]);
00694          pixel.rgbBlue  = float_to_ubyte(rgba[x*4 + 2]);
00695          pixel.rgbAlpha = float_to_ubyte(rgba[x*4 + 3]);
00696          util_stream_write(stream, &pixel, 4);
00697       }  
00698    }
00699    
00700    surface->usage = surface_usage;
00701 
00702    util_stream_close(stream);
00703 error2:
00704    FREE(rgba);
00705 error1:
00706    ;
00707 }
00708 
00709 #endif

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4