Path: blob/21.2-virgl/src/gallium/auxiliary/util/u_debug_image.c
4561 views
/*1* Copyright (c) 2008-2016 VMware, Inc.2* All Rights Reserved.3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the6* "Software"), to deal in the Software without restriction, including7* without limitation the rights to use, copy, modify, merge, publish,8* distribute, sub license, and/or sell copies of the Software, and to9* permit persons to whom the Software is furnished to do so, subject to10* the following conditions:11*12* The above copyright notice and this permission notice (including the13* next paragraph) shall be included in all copies or substantial portions14* of the Software.15*16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS17* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.19* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR20* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,21* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE22* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.23*/242526#include "util/u_debug_image.h"27#include "util/format/u_format.h"28#include "util/u_inlines.h"29#include "util/u_memory.h"30#include "util/u_string.h"31#include "util/u_surface.h"32#include "util/u_tile.h"3334#include <stdio.h>353637#ifdef DEBUG3839/**40* Dump an image to .ppm file.41* \param format PIPE_FORMAT_x42* \param cpp bytes per pixel43* \param width width in pixels44* \param height height in pixels45* \param stride row stride in bytes46*/47void48debug_dump_image(const char *prefix,49enum pipe_format format, UNUSED unsigned cpp,50unsigned width, unsigned height,51unsigned stride,52const void *data)53{54/* write a ppm file */55char filename[256];56unsigned char *rgb8;57FILE *f;5859snprintf(filename, sizeof(filename), "%s.ppm", prefix);6061rgb8 = MALLOC(height * width * 3);62if (!rgb8) {63return;64}6566util_format_translate(67PIPE_FORMAT_R8G8B8_UNORM,68rgb8, width * 3,690, 0,70format,71data, stride,720, 0, width, height);7374/* Must be opened in binary mode or DOS line ending causes data75* to be read with one byte offset.76*/77f = fopen(filename, "wb");78if (f) {79fprintf(f, "P6\n");80fprintf(f, "# ppm-file created by gallium\n");81fprintf(f, "%i %i\n", width, height);82fprintf(f, "255\n");83fwrite(rgb8, 1, height * width * 3, f);84fclose(f);85}86else {87fprintf(stderr, "Can't open %s for writing\n", filename);88}8990FREE(rgb8);91}929394/* FIXME: dump resources, not surfaces... */95void96debug_dump_surface(struct pipe_context *pipe,97const char *prefix,98struct pipe_surface *surface)99{100struct pipe_resource *texture;101struct pipe_transfer *transfer;102void *data;103104if (!surface)105return;106107/* XXX: this doesn't necessarily work, as the driver may be using108* temporary storage for the surface which hasn't been propagated109* back into the texture. Need to nail down the semantics of views110* and transfers a bit better before we can say if extra work needs111* to be done here:112*/113texture = surface->texture;114115data = pipe_texture_map(pipe, texture, surface->u.tex.level,116surface->u.tex.first_layer,117PIPE_MAP_READ,1180, 0, surface->width, surface->height, &transfer);119if (!data)120return;121122debug_dump_image(prefix,123texture->format,124util_format_get_blocksize(texture->format),125util_format_get_nblocksx(texture->format, surface->width),126util_format_get_nblocksy(texture->format, surface->height),127transfer->stride,128data);129130pipe->texture_unmap(pipe, transfer);131}132133134void135debug_dump_texture(struct pipe_context *pipe,136const char *prefix,137struct pipe_resource *texture)138{139struct pipe_surface *surface, surf_tmpl;140141if (!texture)142return;143144/* XXX for now, just dump image for layer=0, level=0 */145u_surface_default_template(&surf_tmpl, texture);146surface = pipe->create_surface(pipe, texture, &surf_tmpl);147if (surface) {148debug_dump_surface(pipe, prefix, surface);149pipe->surface_destroy(pipe, surface);150}151}152153154#pragma pack(push,2)155struct bmp_file_header {156uint16_t bfType;157uint32_t bfSize;158uint16_t bfReserved1;159uint16_t bfReserved2;160uint32_t bfOffBits;161};162#pragma pack(pop)163164struct bmp_info_header {165uint32_t biSize;166int32_t biWidth;167int32_t biHeight;168uint16_t biPlanes;169uint16_t biBitCount;170uint32_t biCompression;171uint32_t biSizeImage;172int32_t biXPelsPerMeter;173int32_t biYPelsPerMeter;174uint32_t biClrUsed;175uint32_t biClrImportant;176};177178struct bmp_rgb_quad {179uint8_t rgbBlue;180uint8_t rgbGreen;181uint8_t rgbRed;182uint8_t rgbAlpha;183};184185void186debug_dump_surface_bmp(struct pipe_context *pipe,187const char *filename,188struct pipe_surface *surface)189{190struct pipe_transfer *transfer;191struct pipe_resource *texture = surface->texture;192void *ptr;193194ptr = pipe_texture_map(pipe, texture, surface->u.tex.level,195surface->u.tex.first_layer, PIPE_MAP_READ,1960, 0, surface->width, surface->height, &transfer);197198debug_dump_transfer_bmp(pipe, filename, transfer, ptr);199200pipe->texture_unmap(pipe, transfer);201}202203void204debug_dump_transfer_bmp(UNUSED struct pipe_context *pipe,205const char *filename,206struct pipe_transfer *transfer, void *ptr)207{208float *rgba;209210if (!transfer)211goto error1;212213rgba = MALLOC(transfer->box.width *214transfer->box.height *215transfer->box.depth *2164*sizeof(float));217if (!rgba)218goto error1;219220pipe_get_tile_rgba(transfer, ptr, 0, 0,221transfer->box.width, transfer->box.height,222transfer->resource->format,223rgba);224225debug_dump_float_rgba_bmp(filename,226transfer->box.width, transfer->box.height,227rgba, transfer->box.width);228229FREE(rgba);230error1:231;232}233234void235debug_dump_float_rgba_bmp(const char *filename,236unsigned width, unsigned height,237float *rgba, unsigned stride)238{239FILE *stream;240struct bmp_file_header bmfh;241struct bmp_info_header bmih;242unsigned x, y;243244if (!rgba)245goto error1;246247bmfh.bfType = 0x4d42;248bmfh.bfSize = 14 + 40 + height*width*4;249bmfh.bfReserved1 = 0;250bmfh.bfReserved2 = 0;251bmfh.bfOffBits = 14 + 40;252253bmih.biSize = 40;254bmih.biWidth = width;255bmih.biHeight = height;256bmih.biPlanes = 1;257bmih.biBitCount = 32;258bmih.biCompression = 0;259bmih.biSizeImage = height*width*4;260bmih.biXPelsPerMeter = 0;261bmih.biYPelsPerMeter = 0;262bmih.biClrUsed = 0;263bmih.biClrImportant = 0;264265stream = fopen(filename, "wb");266if (!stream)267goto error1;268269fwrite(&bmfh, 14, 1, stream);270fwrite(&bmih, 40, 1, stream);271272y = height;273while (y--) {274float *ptr = rgba + (stride * y * 4);275for (x = 0; x < width; ++x) {276struct bmp_rgb_quad pixel;277pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);278pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);279pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);280pixel.rgbAlpha = float_to_ubyte(ptr[x*4 + 3]);281fwrite(&pixel, 1, 4, stream);282}283}284285fclose(stream);286error1:287;288}289290void291debug_dump_ubyte_rgba_bmp(const char *filename,292unsigned width, unsigned height,293const ubyte *rgba, unsigned stride)294{295FILE *stream;296struct bmp_file_header bmfh;297struct bmp_info_header bmih;298unsigned x, y;299300assert(rgba);301if (!rgba)302goto error1;303304bmfh.bfType = 0x4d42;305bmfh.bfSize = 14 + 40 + height*width*4;306bmfh.bfReserved1 = 0;307bmfh.bfReserved2 = 0;308bmfh.bfOffBits = 14 + 40;309310bmih.biSize = 40;311bmih.biWidth = width;312bmih.biHeight = height;313bmih.biPlanes = 1;314bmih.biBitCount = 32;315bmih.biCompression = 0;316bmih.biSizeImage = height*width*4;317bmih.biXPelsPerMeter = 0;318bmih.biYPelsPerMeter = 0;319bmih.biClrUsed = 0;320bmih.biClrImportant = 0;321322stream = fopen(filename, "wb");323assert(stream);324if (!stream)325goto error1;326327fwrite(&bmfh, 14, 1, stream);328fwrite(&bmih, 40, 1, stream);329330y = height;331while (y--) {332const ubyte *ptr = rgba + (stride * y * 4);333for (x = 0; x < width; ++x) {334struct bmp_rgb_quad pixel;335pixel.rgbRed = ptr[x*4 + 0];336pixel.rgbGreen = ptr[x*4 + 1];337pixel.rgbBlue = ptr[x*4 + 2];338pixel.rgbAlpha = ptr[x*4 + 3];339fwrite(&pixel, 1, 4, stream);340}341}342343fclose(stream);344error1:345;346}347348#endif349350351