gallium/util: put image dumping functions into separate file
To try to reduce the clutter in u_debug.[ch] Reviewed-by: Marek Olšák <marek.olsak@amd.com>
This commit is contained in:
parent
6c7d4a7173
commit
3917c8f3f9
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 VMware, Inc.
|
||||
* 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 VMWARE 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "util/u_debug_image.h"
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_string.h"
|
||||
#include "util/u_surface.h"
|
||||
#include "util/u_tile.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
/**
|
||||
* Dump an image to .ppm file.
|
||||
* \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,
|
||||
enum pipe_format format, unsigned cpp,
|
||||
unsigned width, unsigned height,
|
||||
unsigned stride,
|
||||
const void *data)
|
||||
{
|
||||
/* write a ppm file */
|
||||
char filename[256];
|
||||
unsigned char *rgb8;
|
||||
FILE *f;
|
||||
|
||||
util_snprintf(filename, sizeof(filename), "%s.ppm", prefix);
|
||||
|
||||
rgb8 = MALLOC(height * width * 3);
|
||||
if (!rgb8) {
|
||||
return;
|
||||
}
|
||||
|
||||
util_format_translate(
|
||||
PIPE_FORMAT_R8G8B8_UNORM,
|
||||
rgb8, width * 3,
|
||||
0, 0,
|
||||
format,
|
||||
data, stride,
|
||||
0, 0, width, height);
|
||||
|
||||
/* Must be opened in binary mode or DOS line ending causes data
|
||||
* to be read with one byte offset.
|
||||
*/
|
||||
f = fopen(filename, "wb");
|
||||
if (f) {
|
||||
fprintf(f, "P6\n");
|
||||
fprintf(f, "# ppm-file created by gallium\n");
|
||||
fprintf(f, "%i %i\n", width, height);
|
||||
fprintf(f, "255\n");
|
||||
fwrite(rgb8, 1, height * width * 3, f);
|
||||
fclose(f);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Can't open %s for writing\n", filename);
|
||||
}
|
||||
|
||||
FREE(rgb8);
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: dump resources, not surfaces... */
|
||||
void
|
||||
debug_dump_surface(struct pipe_context *pipe,
|
||||
const char *prefix,
|
||||
struct pipe_surface *surface)
|
||||
{
|
||||
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;
|
||||
|
||||
data = pipe_transfer_map(pipe, texture, surface->u.tex.level,
|
||||
surface->u.tex.first_layer,
|
||||
PIPE_TRANSFER_READ,
|
||||
0, 0, surface->width, surface->height, &transfer);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
debug_dump_image(prefix,
|
||||
texture->format,
|
||||
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);
|
||||
|
||||
pipe->transfer_unmap(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 */
|
||||
u_surface_default_template(&surf_tmpl, texture);
|
||||
surface = pipe->create_surface(pipe, texture, &surf_tmpl);
|
||||
if (surface) {
|
||||
debug_dump_surface(pipe, prefix, surface);
|
||||
pipe->surface_destroy(pipe, surface);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#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(struct pipe_context *pipe,
|
||||
const char *filename,
|
||||
struct pipe_surface *surface)
|
||||
{
|
||||
struct pipe_transfer *transfer;
|
||||
struct pipe_resource *texture = surface->texture;
|
||||
void *ptr;
|
||||
|
||||
ptr = pipe_transfer_map(pipe, texture, surface->u.tex.level,
|
||||
surface->u.tex.first_layer, PIPE_TRANSFER_READ,
|
||||
0, 0, surface->width, surface->height, &transfer);
|
||||
|
||||
debug_dump_transfer_bmp(pipe, filename, transfer, ptr);
|
||||
|
||||
pipe->transfer_unmap(pipe, transfer);
|
||||
}
|
||||
|
||||
void
|
||||
debug_dump_transfer_bmp(struct pipe_context *pipe,
|
||||
const char *filename,
|
||||
struct pipe_transfer *transfer, void *ptr)
|
||||
{
|
||||
float *rgba;
|
||||
|
||||
if (!transfer)
|
||||
goto error1;
|
||||
|
||||
rgba = MALLOC(transfer->box.width *
|
||||
transfer->box.height *
|
||||
transfer->box.depth *
|
||||
4*sizeof(float));
|
||||
if (!rgba)
|
||||
goto error1;
|
||||
|
||||
pipe_get_tile_rgba(transfer, ptr, 0, 0,
|
||||
transfer->box.width, transfer->box.height,
|
||||
rgba);
|
||||
|
||||
debug_dump_float_rgba_bmp(filename,
|
||||
transfer->box.width, transfer->box.height,
|
||||
rgba, transfer->box.width);
|
||||
|
||||
FREE(rgba);
|
||||
error1:
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
debug_dump_float_rgba_bmp(const char *filename,
|
||||
unsigned width, unsigned height,
|
||||
float *rgba, unsigned stride)
|
||||
{
|
||||
FILE *stream;
|
||||
struct bmp_file_header bmfh;
|
||||
struct bmp_info_header bmih;
|
||||
unsigned x, y;
|
||||
|
||||
if (!rgba)
|
||||
goto error1;
|
||||
|
||||
bmfh.bfType = 0x4d42;
|
||||
bmfh.bfSize = 14 + 40 + height*width*4;
|
||||
bmfh.bfReserved1 = 0;
|
||||
bmfh.bfReserved2 = 0;
|
||||
bmfh.bfOffBits = 14 + 40;
|
||||
|
||||
bmih.biSize = 40;
|
||||
bmih.biWidth = width;
|
||||
bmih.biHeight = height;
|
||||
bmih.biPlanes = 1;
|
||||
bmih.biBitCount = 32;
|
||||
bmih.biCompression = 0;
|
||||
bmih.biSizeImage = height*width*4;
|
||||
bmih.biXPelsPerMeter = 0;
|
||||
bmih.biYPelsPerMeter = 0;
|
||||
bmih.biClrUsed = 0;
|
||||
bmih.biClrImportant = 0;
|
||||
|
||||
stream = fopen(filename, "wb");
|
||||
if (!stream)
|
||||
goto error1;
|
||||
|
||||
fwrite(&bmfh, 14, 1, stream);
|
||||
fwrite(&bmih, 40, 1, stream);
|
||||
|
||||
y = height;
|
||||
while (y--) {
|
||||
float *ptr = rgba + (stride * y * 4);
|
||||
for (x = 0; x < width; ++x) {
|
||||
struct bmp_rgb_quad pixel;
|
||||
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 = float_to_ubyte(ptr[x*4 + 3]);
|
||||
fwrite(&pixel, 1, 4, stream);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(stream);
|
||||
error1:
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
debug_dump_ubyte_rgba_bmp(const char *filename,
|
||||
unsigned width, unsigned height,
|
||||
const ubyte *rgba, unsigned stride)
|
||||
{
|
||||
FILE *stream;
|
||||
struct bmp_file_header bmfh;
|
||||
struct bmp_info_header bmih;
|
||||
unsigned x, y;
|
||||
|
||||
assert(rgba);
|
||||
if (!rgba)
|
||||
goto error1;
|
||||
|
||||
bmfh.bfType = 0x4d42;
|
||||
bmfh.bfSize = 14 + 40 + height*width*4;
|
||||
bmfh.bfReserved1 = 0;
|
||||
bmfh.bfReserved2 = 0;
|
||||
bmfh.bfOffBits = 14 + 40;
|
||||
|
||||
bmih.biSize = 40;
|
||||
bmih.biWidth = width;
|
||||
bmih.biHeight = height;
|
||||
bmih.biPlanes = 1;
|
||||
bmih.biBitCount = 32;
|
||||
bmih.biCompression = 0;
|
||||
bmih.biSizeImage = height*width*4;
|
||||
bmih.biXPelsPerMeter = 0;
|
||||
bmih.biYPelsPerMeter = 0;
|
||||
bmih.biClrUsed = 0;
|
||||
bmih.biClrImportant = 0;
|
||||
|
||||
stream = fopen(filename, "wb");
|
||||
assert(stream);
|
||||
if (!stream)
|
||||
goto error1;
|
||||
|
||||
fwrite(&bmfh, 14, 1, stream);
|
||||
fwrite(&bmih, 40, 1, stream);
|
||||
|
||||
y = height;
|
||||
while (y--) {
|
||||
const ubyte *ptr = rgba + (stride * y * 4);
|
||||
for (x = 0; x < width; ++x) {
|
||||
struct bmp_rgb_quad pixel;
|
||||
pixel.rgbRed = ptr[x*4 + 0];
|
||||
pixel.rgbGreen = ptr[x*4 + 1];
|
||||
pixel.rgbBlue = ptr[x*4 + 2];
|
||||
pixel.rgbAlpha = ptr[x*4 + 3];
|
||||
fwrite(&pixel, 1, 4, stream);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(stream);
|
||||
error1:
|
||||
;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 VMware, Inc.
|
||||
* 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 VMWARE 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef U_DEBUG_IMAGE_H
|
||||
#define U_DEBUG_IMAGE_H
|
||||
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_format.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
struct pipe_context;
|
||||
struct pipe_surface;
|
||||
struct pipe_transfer;
|
||||
struct pipe_resource;
|
||||
|
||||
void debug_dump_image(const char *prefix,
|
||||
enum pipe_format format, unsigned cpp,
|
||||
unsigned width, unsigned height,
|
||||
unsigned stride,
|
||||
const void *data);
|
||||
void debug_dump_surface(struct pipe_context *pipe,
|
||||
const char *prefix,
|
||||
struct pipe_surface *surface);
|
||||
void debug_dump_texture(struct pipe_context *pipe,
|
||||
const char *prefix,
|
||||
struct pipe_resource *texture);
|
||||
void debug_dump_surface_bmp(struct pipe_context *pipe,
|
||||
const char *filename,
|
||||
struct pipe_surface *surface);
|
||||
void debug_dump_transfer_bmp(struct pipe_context *pipe,
|
||||
const char *filename,
|
||||
struct pipe_transfer *transfer, void *ptr);
|
||||
void debug_dump_float_rgba_bmp(const char *filename,
|
||||
unsigned width, unsigned height,
|
||||
float *rgba, unsigned stride);
|
||||
void debug_dump_ubyte_rgba_bmp(const char *filename,
|
||||
unsigned width, unsigned height,
|
||||
const ubyte *rgba, unsigned stride);
|
||||
#else
|
||||
#define debug_dump_image(prefix, format, cpp, width, height, stride, data) ((void)0)
|
||||
#define debug_dump_surface(pipe, prefix, surface) ((void)0)
|
||||
#define debug_dump_surface_bmp(pipe, filename, surface) ((void)0)
|
||||
#define debug_dump_transfer_bmp(filename, transfer, ptr) ((void)0)
|
||||
#define debug_dump_float_rgba_bmp(filename, width, height, rgba, stride) ((void)0)
|
||||
#define debug_dump_ubyte_rgba_bmp(filename, width, height, rgba, stride) ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue