2008-02-06 04:27:49 +00:00
|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
2008-12-12 04:09:56 +00:00
|
|
|
* Copyright (c) 2008 VMware, Inc.
|
2008-02-06 04:27:49 +00:00
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
* distribute, sub license, and/or sell copies of the Software, and to
|
|
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
* the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the
|
|
|
|
* next paragraph) shall be included in all copies or substantial portions
|
|
|
|
* of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
|
|
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
|
|
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
2008-04-25 10:19:51 +01:00
|
|
|
#include "pipe/p_config.h"
|
|
|
|
|
2010-02-03 12:13:06 +00:00
|
|
|
#include "pipe/p_compiler.h"
|
2010-02-04 18:44:51 +00:00
|
|
|
#include "os/os_stream.h"
|
2009-02-18 12:05:26 +00:00
|
|
|
#include "util/u_debug.h"
|
2008-04-29 20:33:37 +01:00
|
|
|
#include "pipe/p_format.h"
|
2008-08-06 14:48:11 +01:00
|
|
|
#include "pipe/p_state.h"
|
2010-02-02 14:42:17 +00:00
|
|
|
#include "util/u_inlines.h"
|
2009-12-17 22:41:57 +00:00
|
|
|
#include "util/u_format.h"
|
2008-09-08 14:21:33 +01:00
|
|
|
#include "util/u_memory.h"
|
2008-04-14 15:55:36 +01:00
|
|
|
#include "util/u_string.h"
|
2008-09-08 14:21:33 +01:00
|
|
|
#include "util/u_math.h"
|
|
|
|
#include "util/u_tile.h"
|
2009-10-25 00:02:16 +01:00
|
|
|
#include "util/u_prim.h"
|
2008-02-06 04:27:49 +00:00
|
|
|
|
|
|
|
|
2008-03-24 20:18:59 +00:00
|
|
|
void _debug_vprintf(const char *format, va_list ap)
|
2008-02-06 04:27:49 +00:00
|
|
|
{
|
2010-02-03 12:13:06 +00:00
|
|
|
/* We buffer until we find a newline. */
|
2009-07-01 19:09:44 +01:00
|
|
|
static char buf[4096] = {'\0'};
|
2008-06-23 23:24:58 +01:00
|
|
|
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')) {
|
2010-02-03 12:13:06 +00:00
|
|
|
os_log_message(buf);
|
2008-06-23 23:24:58 +01:00
|
|
|
buf[0] = '\0';
|
|
|
|
}
|
2008-02-06 16:07:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-24 20:18:59 +00:00
|
|
|
#ifdef DEBUG
|
2008-03-20 13:10:32 +00:00
|
|
|
void debug_print_blob( const char *name,
|
|
|
|
const void *blob,
|
|
|
|
unsigned size )
|
|
|
|
{
|
|
|
|
const unsigned *ublob = (const unsigned *)blob;
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
debug_printf("%s (%d dwords%s)\n", name, size/4,
|
|
|
|
size%4 ? "... plus a few bytes" : "");
|
|
|
|
|
|
|
|
for (i = 0; i < size/4; i++) {
|
|
|
|
debug_printf("%d:\t%08x\n", i, ublob[i]);
|
|
|
|
}
|
|
|
|
}
|
2008-03-24 20:18:59 +00:00
|
|
|
#endif
|
2008-03-20 13:10:32 +00:00
|
|
|
|
|
|
|
|
2008-07-17 03:26:53 +01:00
|
|
|
const char *
|
|
|
|
debug_get_option(const char *name, const char *dfault)
|
|
|
|
{
|
|
|
|
const char *result;
|
2008-05-29 11:24:53 +01:00
|
|
|
|
2010-02-03 12:13:06 +00:00
|
|
|
result = os_get_option(name);
|
2008-07-17 03:26:53 +01:00
|
|
|
if(!result)
|
|
|
|
result = dfault;
|
|
|
|
|
2008-03-25 11:37:24 +00:00
|
|
|
debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
|
2008-03-24 22:30:33 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean
|
|
|
|
debug_get_bool_option(const char *name, boolean dfault)
|
|
|
|
{
|
2010-02-03 12:13:06 +00:00
|
|
|
const char *str = os_get_option(name);
|
2008-03-24 22:30:33 +00:00
|
|
|
boolean result;
|
|
|
|
|
|
|
|
if(str == NULL)
|
|
|
|
result = dfault;
|
2008-05-07 11:39:34 +01:00
|
|
|
else if(!util_strcmp(str, "n"))
|
2008-04-16 14:32:10 +01:00
|
|
|
result = FALSE;
|
2008-05-07 11:39:34 +01:00
|
|
|
else if(!util_strcmp(str, "no"))
|
2008-03-24 22:30:33 +00:00
|
|
|
result = FALSE;
|
2008-05-07 11:39:34 +01:00
|
|
|
else if(!util_strcmp(str, "0"))
|
2008-03-24 22:30:33 +00:00
|
|
|
result = FALSE;
|
2008-05-07 11:39:34 +01:00
|
|
|
else if(!util_strcmp(str, "f"))
|
2008-03-24 22:30:33 +00:00
|
|
|
result = FALSE;
|
2008-05-07 11:39:34 +01:00
|
|
|
else if(!util_strcmp(str, "false"))
|
2008-03-24 22:30:33 +00:00
|
|
|
result = FALSE;
|
|
|
|
else
|
|
|
|
result = TRUE;
|
|
|
|
|
|
|
|
debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
long
|
|
|
|
debug_get_num_option(const char *name, long dfault)
|
|
|
|
{
|
2008-06-10 15:22:12 +01:00
|
|
|
long result;
|
|
|
|
const char *str;
|
|
|
|
|
2010-02-03 12:13:06 +00:00
|
|
|
str = os_get_option(name);
|
2008-06-10 15:22:12 +01:00
|
|
|
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;
|
2008-03-24 22:30:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
unsigned long
|
|
|
|
debug_get_flags_option(const char *name,
|
|
|
|
const struct debug_named_value *flags,
|
|
|
|
unsigned long dfault)
|
|
|
|
{
|
|
|
|
unsigned long result;
|
|
|
|
const char *str;
|
|
|
|
|
2010-02-03 12:13:06 +00:00
|
|
|
str = os_get_option(name);
|
2008-03-24 22:30:33 +00:00
|
|
|
if(!str)
|
|
|
|
result = dfault;
|
2008-09-23 17:09:36 +01:00
|
|
|
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++;
|
|
|
|
}
|
|
|
|
}
|
2008-03-24 22:30:33 +00:00
|
|
|
else {
|
|
|
|
result = 0;
|
|
|
|
while( flags->name ) {
|
2008-05-07 11:39:34 +01:00
|
|
|
if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
|
2008-03-24 22:30:33 +00:00
|
|
|
result |= flags->value;
|
|
|
|
++flags;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-23 17:09:36 +01:00
|
|
|
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);
|
|
|
|
}
|
2008-03-24 22:30:33 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-24 20:18:59 +00:00
|
|
|
void _debug_assert_fail(const char *expr,
|
|
|
|
const char *file,
|
|
|
|
unsigned line,
|
|
|
|
const char *function)
|
2008-02-06 04:27:49 +00:00
|
|
|
{
|
2008-03-24 20:18:59 +00:00
|
|
|
_debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
|
2008-12-09 10:35:52 +00:00
|
|
|
#if defined(PIPE_OS_WINDOWS) && !defined(PIPE_SUBSYSTEM_WINDOWS_USER)
|
2008-08-07 09:15:32 +01:00
|
|
|
if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", FALSE))
|
|
|
|
#else
|
2008-04-16 14:32:10 +01:00
|
|
|
if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
|
2008-08-07 09:15:32 +01:00
|
|
|
#endif
|
2010-02-03 12:13:06 +00:00
|
|
|
os_abort();
|
2008-04-16 14:32:10 +01:00
|
|
|
else
|
2008-03-24 20:18:59 +00:00
|
|
|
_debug_printf("continuing...\n");
|
2008-02-06 04:27:49 +00:00
|
|
|
}
|
2008-03-11 12:03:11 +00:00
|
|
|
|
|
|
|
|
2008-03-19 16:41:07 +00:00
|
|
|
const char *
|
|
|
|
debug_dump_enum(const struct debug_named_value *names,
|
|
|
|
unsigned long value)
|
|
|
|
{
|
2008-08-07 19:25:28 +01:00
|
|
|
static char rest[64];
|
2008-03-19 16:41:07 +00:00
|
|
|
|
|
|
|
while(names->name) {
|
|
|
|
if(names->value == value)
|
|
|
|
return names->name;
|
|
|
|
++names;
|
|
|
|
}
|
|
|
|
|
2008-04-14 15:55:36 +01:00
|
|
|
util_snprintf(rest, sizeof(rest), "0x%08lx", value);
|
2008-03-19 16:41:07 +00:00
|
|
|
return rest;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-17 18:45:20 +00:00
|
|
|
const char *
|
|
|
|
debug_dump_enum_noprefix(const struct debug_named_value *names,
|
|
|
|
const char *prefix,
|
|
|
|
unsigned long value)
|
|
|
|
{
|
|
|
|
static char rest[64];
|
|
|
|
|
|
|
|
while(names->name) {
|
|
|
|
if(names->value == value) {
|
|
|
|
const char *name = names->name;
|
|
|
|
while (*name == *prefix) {
|
|
|
|
name++;
|
|
|
|
prefix++;
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
++names;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
util_snprintf(rest, sizeof(rest), "0x%08lx", value);
|
|
|
|
return rest;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-19 16:41:07 +00:00
|
|
|
const char *
|
|
|
|
debug_dump_flags(const struct debug_named_value *names,
|
|
|
|
unsigned long value)
|
|
|
|
{
|
|
|
|
static char output[4096];
|
|
|
|
static char rest[256];
|
|
|
|
int first = 1;
|
|
|
|
|
|
|
|
output[0] = '\0';
|
|
|
|
|
|
|
|
while(names->name) {
|
|
|
|
if((names->value & value) == names->value) {
|
|
|
|
if (!first)
|
2008-05-07 11:39:34 +01:00
|
|
|
util_strncat(output, "|", sizeof(output));
|
2008-03-19 16:41:07 +00:00
|
|
|
else
|
|
|
|
first = 0;
|
2009-12-23 23:19:45 +00:00
|
|
|
util_strncat(output, names->name, sizeof(output) - 1);
|
|
|
|
output[sizeof(output) - 1] = '\0';
|
2008-03-19 16:41:07 +00:00
|
|
|
value &= ~names->value;
|
|
|
|
}
|
|
|
|
++names;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value) {
|
|
|
|
if (!first)
|
2008-05-07 11:39:34 +01:00
|
|
|
util_strncat(output, "|", sizeof(output));
|
2008-03-19 16:41:07 +00:00
|
|
|
else
|
|
|
|
first = 0;
|
|
|
|
|
2008-04-14 15:55:36 +01:00
|
|
|
util_snprintf(rest, sizeof(rest), "0x%08lx", value);
|
2009-12-23 23:19:45 +00:00
|
|
|
util_strncat(output, rest, sizeof(output) - 1);
|
|
|
|
output[sizeof(output) - 1] = '\0';
|
2008-03-19 16:41:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(first)
|
|
|
|
return "0";
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
2008-03-20 13:10:32 +00:00
|
|
|
|
|
|
|
|
2008-05-07 13:37:32 +01:00
|
|
|
#ifdef DEBUG
|
2008-04-29 22:21:10 +01:00
|
|
|
void debug_print_format(const char *msg, unsigned fmt )
|
2008-04-29 20:33:37 +01:00
|
|
|
{
|
2010-02-14 13:26:51 +00:00
|
|
|
debug_printf("%s: %s\n", msg, util_format_name(fmt));
|
2008-04-29 20:33:37 +01:00
|
|
|
}
|
2008-05-07 13:37:32 +01:00
|
|
|
#endif
|
2008-05-07 13:24:14 +01:00
|
|
|
|
2008-05-06 18:51:49 +01:00
|
|
|
|
2009-10-25 00:02:16 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-05-06 18:51:49 +01:00
|
|
|
#ifdef DEBUG
|
2010-01-15 02:04:40 +00:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2008-05-06 18:51:49 +01:00
|
|
|
void debug_dump_image(const char *prefix,
|
|
|
|
unsigned format, unsigned cpp,
|
|
|
|
unsigned width, unsigned height,
|
2008-08-06 14:48:11 +01:00
|
|
|
unsigned stride,
|
2008-05-06 18:51:49 +01:00
|
|
|
const void *data)
|
|
|
|
{
|
|
|
|
#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;
|
|
|
|
|
|
|
|
util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix);
|
|
|
|
for(i = 0; i < sizeof(filename); ++i)
|
|
|
|
wfilename[i] = (WCHAR)filename[i];
|
|
|
|
|
2008-08-06 14:48:11 +01:00
|
|
|
pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + height*width*cpp, &iFile);
|
2008-05-06 18:51:49 +01:00
|
|
|
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) {
|
2008-08-06 14:48:11 +01:00
|
|
|
memcpy(pMap, (unsigned char *)data + stride*i, cpp*width);
|
2008-05-06 18:51:49 +01:00
|
|
|
pMap += cpp*width;
|
|
|
|
}
|
|
|
|
|
|
|
|
EngUnmapFile(iFile);
|
2010-01-15 02:04:40 +00:00
|
|
|
#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) {
|
2010-03-01 18:09:40 +00:00
|
|
|
case PIPE_FORMAT_B8G8R8A8_UNORM:
|
2010-01-15 02:04:40 +00:00
|
|
|
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);
|
|
|
|
}
|
2008-05-06 18:51:49 +01:00
|
|
|
#endif
|
|
|
|
}
|
2008-08-06 14:48:11 +01:00
|
|
|
|
2010-03-11 15:23:16 +00:00
|
|
|
void debug_dump_surface(struct pipe_context *pipe,
|
|
|
|
const char *prefix,
|
2008-08-06 14:48:11 +01:00
|
|
|
struct pipe_surface *surface)
|
|
|
|
{
|
2009-02-05 18:41:18 +00:00
|
|
|
struct pipe_texture *texture;
|
|
|
|
struct pipe_transfer *transfer;
|
2008-08-06 14:48:11 +01:00
|
|
|
void *data;
|
|
|
|
|
|
|
|
if (!surface)
|
2009-02-05 18:41:18 +00:00
|
|
|
return;
|
|
|
|
|
2010-03-11 15:23:16 +00:00
|
|
|
/* 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:
|
|
|
|
*/
|
2009-02-05 18:41:18 +00:00
|
|
|
texture = surface->texture;
|
2008-08-06 14:48:11 +01:00
|
|
|
|
2010-03-11 15:23:16 +00:00
|
|
|
transfer = pipe->get_tex_transfer(pipe, texture, surface->face,
|
|
|
|
surface->level, surface->zslice,
|
|
|
|
PIPE_TRANSFER_READ, 0, 0, surface->width,
|
|
|
|
surface->height);
|
2008-08-06 14:48:11 +01:00
|
|
|
|
2010-03-11 15:23:16 +00:00
|
|
|
data = pipe->transfer_map(pipe, transfer);
|
2008-08-06 14:48:11 +01:00
|
|
|
if(!data)
|
2009-02-05 18:41:18 +00:00
|
|
|
goto error;
|
2008-08-06 14:48:11 +01:00
|
|
|
|
|
|
|
debug_dump_image(prefix,
|
2009-11-30 19:29:18 +00:00
|
|
|
texture->format,
|
2009-12-17 22:41:57 +00:00
|
|
|
util_format_get_blocksize(texture->format),
|
|
|
|
util_format_get_nblocksx(texture->format, transfer->width),
|
|
|
|
util_format_get_nblocksy(texture->format, transfer->height),
|
2009-02-05 18:41:18 +00:00
|
|
|
transfer->stride,
|
2008-08-06 14:48:11 +01:00
|
|
|
data);
|
|
|
|
|
2010-03-11 15:23:16 +00:00
|
|
|
pipe->transfer_unmap(pipe, transfer);
|
2009-02-05 18:41:18 +00:00
|
|
|
error:
|
2010-03-11 15:23:16 +00:00
|
|
|
pipe->tex_transfer_destroy(transfer);
|
2008-08-06 14:48:11 +01:00
|
|
|
}
|
2008-09-08 14:21:33 +01:00
|
|
|
|
|
|
|
|
2010-03-11 15:23:16 +00:00
|
|
|
void debug_dump_texture(struct pipe_context *pipe,
|
|
|
|
const char *prefix,
|
2010-01-15 02:04:40 +00:00
|
|
|
struct pipe_texture *texture)
|
|
|
|
{
|
|
|
|
struct pipe_surface *surface;
|
|
|
|
struct pipe_screen *screen;
|
|
|
|
|
|
|
|
if (!texture)
|
|
|
|
return;
|
|
|
|
|
|
|
|
screen = texture->screen;
|
|
|
|
|
|
|
|
/* XXX for now, just dump image for face=0, level=0 */
|
|
|
|
surface = screen->get_tex_surface(screen, texture, 0, 0, 0,
|
|
|
|
PIPE_TEXTURE_USAGE_SAMPLER);
|
|
|
|
if (surface) {
|
2010-03-11 15:23:16 +00:00
|
|
|
debug_dump_surface(pipe, prefix, surface);
|
2010-01-15 02:04:40 +00:00
|
|
|
screen->tex_surface_destroy(surface);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-08 14:21:33 +01:00
|
|
|
#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;
|
|
|
|
};
|
|
|
|
|
2009-03-21 13:23:04 +00:00
|
|
|
void
|
2010-03-11 15:23:16 +00:00
|
|
|
debug_dump_surface_bmp(struct pipe_context *pipe,
|
|
|
|
const char *filename,
|
2008-09-08 14:21:33 +01:00
|
|
|
struct pipe_surface *surface)
|
|
|
|
{
|
2009-04-23 04:42:26 +01:00
|
|
|
#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
|
2009-03-21 13:23:04 +00:00
|
|
|
struct pipe_transfer *transfer;
|
2009-04-03 13:58:39 +01:00
|
|
|
struct pipe_texture *texture = surface->texture;
|
2009-03-21 13:23:04 +00:00
|
|
|
|
2010-03-11 15:23:16 +00:00
|
|
|
transfer = pipe->get_tex_transfer(pipe, texture, surface->face,
|
|
|
|
surface->level, surface->zslice,
|
|
|
|
PIPE_TRANSFER_READ, 0, 0, surface->width,
|
|
|
|
surface->height);
|
2009-03-21 13:23:04 +00:00
|
|
|
|
|
|
|
debug_dump_transfer_bmp(filename, transfer);
|
|
|
|
|
2010-03-11 15:23:16 +00:00
|
|
|
pipe->tex_transfer_destroy(transfer);
|
2009-04-23 04:42:26 +01:00
|
|
|
#endif
|
2009-03-21 13:23:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
debug_dump_transfer_bmp(const char *filename,
|
|
|
|
struct pipe_transfer *transfer)
|
|
|
|
{
|
|
|
|
#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
|
2008-09-08 14:21:33 +01:00
|
|
|
float *rgba;
|
|
|
|
|
2009-03-21 13:23:04 +00:00
|
|
|
if (!transfer)
|
2008-09-08 14:21:33 +01:00
|
|
|
goto error1;
|
|
|
|
|
2009-03-21 13:23:04 +00:00
|
|
|
rgba = MALLOC(transfer->width*transfer->height*4*sizeof(float));
|
2009-04-23 04:42:26 +01:00
|
|
|
if(!rgba)
|
|
|
|
goto error1;
|
|
|
|
|
|
|
|
pipe_get_tile_rgba(transfer, 0, 0,
|
|
|
|
transfer->width, transfer->height,
|
|
|
|
rgba);
|
|
|
|
|
|
|
|
debug_dump_float_rgba_bmp(filename,
|
|
|
|
transfer->width, transfer->height,
|
|
|
|
rgba, transfer->width);
|
|
|
|
|
|
|
|
FREE(rgba);
|
|
|
|
error1:
|
|
|
|
;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
debug_dump_float_rgba_bmp(const char *filename,
|
|
|
|
unsigned width, unsigned height,
|
|
|
|
float *rgba, unsigned stride)
|
|
|
|
{
|
|
|
|
#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
|
2010-02-04 18:44:51 +00:00
|
|
|
struct os_stream *stream;
|
2009-04-23 04:42:26 +01:00
|
|
|
struct bmp_file_header bmfh;
|
|
|
|
struct bmp_info_header bmih;
|
|
|
|
unsigned x, y;
|
|
|
|
|
2008-09-08 14:21:33 +01:00
|
|
|
if(!rgba)
|
|
|
|
goto error1;
|
2009-03-21 13:23:04 +00:00
|
|
|
|
2008-09-08 14:21:33 +01:00
|
|
|
bmfh.bfType = 0x4d42;
|
2009-04-23 04:42:26 +01:00
|
|
|
bmfh.bfSize = 14 + 40 + height*width*4;
|
2008-09-08 14:21:33 +01:00
|
|
|
bmfh.bfReserved1 = 0;
|
|
|
|
bmfh.bfReserved2 = 0;
|
|
|
|
bmfh.bfOffBits = 14 + 40;
|
2009-03-21 13:23:04 +00:00
|
|
|
|
2008-09-08 14:21:33 +01:00
|
|
|
bmih.biSize = 40;
|
2009-04-23 04:42:26 +01:00
|
|
|
bmih.biWidth = width;
|
|
|
|
bmih.biHeight = height;
|
2008-09-08 14:21:33 +01:00
|
|
|
bmih.biPlanes = 1;
|
|
|
|
bmih.biBitCount = 32;
|
|
|
|
bmih.biCompression = 0;
|
2009-04-23 04:42:26 +01:00
|
|
|
bmih.biSizeImage = height*width*4;
|
2008-09-08 14:21:33 +01:00
|
|
|
bmih.biXPelsPerMeter = 0;
|
|
|
|
bmih.biYPelsPerMeter = 0;
|
|
|
|
bmih.biClrUsed = 0;
|
|
|
|
bmih.biClrImportant = 0;
|
2009-03-21 13:23:04 +00:00
|
|
|
|
2010-02-14 16:55:25 +00:00
|
|
|
stream = os_file_stream_create(filename);
|
2008-09-08 14:21:33 +01:00
|
|
|
if(!stream)
|
2009-04-23 04:42:26 +01:00
|
|
|
goto error1;
|
2009-03-21 13:23:04 +00:00
|
|
|
|
2010-02-04 18:44:51 +00:00
|
|
|
os_stream_write(stream, &bmfh, 14);
|
|
|
|
os_stream_write(stream, &bmih, 40);
|
2009-02-05 18:41:18 +00:00
|
|
|
|
2009-04-23 04:42:26 +01:00
|
|
|
y = height;
|
2008-09-08 14:21:33 +01:00
|
|
|
while(y--) {
|
2009-04-23 04:42:26 +01:00
|
|
|
float *ptr = rgba + (stride * y * 4);
|
|
|
|
for(x = 0; x < width; ++x)
|
2008-09-08 14:21:33 +01:00
|
|
|
{
|
|
|
|
struct bmp_rgb_quad pixel;
|
2009-03-21 13:23:04 +00:00
|
|
|
pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);
|
|
|
|
pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
|
|
|
|
pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
|
|
|
|
pixel.rgbAlpha = 255;
|
2010-02-04 18:44:51 +00:00
|
|
|
os_stream_write(stream, &pixel, 4);
|
2009-03-21 13:23:04 +00:00
|
|
|
}
|
2008-09-08 14:21:33 +01:00
|
|
|
}
|
|
|
|
|
2010-02-04 18:44:51 +00:00
|
|
|
os_stream_close(stream);
|
2008-09-08 14:21:33 +01:00
|
|
|
error1:
|
|
|
|
;
|
2008-11-03 11:50:14 +00:00
|
|
|
#endif
|
2008-09-08 14:21:33 +01:00
|
|
|
}
|
|
|
|
|
2008-05-07 11:39:34 +01:00
|
|
|
#endif
|