Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/auxiliary/util/u_debug_image.c
4561 views
1
/*
2
* Copyright (c) 2008-2016 VMware, Inc.
3
* All Rights Reserved.
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the
7
* "Software"), to deal in the Software without restriction, including
8
* without limitation the rights to use, copy, modify, merge, publish,
9
* distribute, sub license, and/or sell copies of the Software, and to
10
* permit persons to whom the Software is furnished to do so, subject to
11
* the following conditions:
12
*
13
* The above copyright notice and this permission notice (including the
14
* next paragraph) shall be included in all copies or substantial portions
15
* of the Software.
16
*
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
*/
25
26
27
#include "util/u_debug_image.h"
28
#include "util/format/u_format.h"
29
#include "util/u_inlines.h"
30
#include "util/u_memory.h"
31
#include "util/u_string.h"
32
#include "util/u_surface.h"
33
#include "util/u_tile.h"
34
35
#include <stdio.h>
36
37
38
#ifdef DEBUG
39
40
/**
41
* Dump an image to .ppm file.
42
* \param format PIPE_FORMAT_x
43
* \param cpp bytes per pixel
44
* \param width width in pixels
45
* \param height height in pixels
46
* \param stride row stride in bytes
47
*/
48
void
49
debug_dump_image(const char *prefix,
50
enum pipe_format format, UNUSED unsigned cpp,
51
unsigned width, unsigned height,
52
unsigned stride,
53
const void *data)
54
{
55
/* write a ppm file */
56
char filename[256];
57
unsigned char *rgb8;
58
FILE *f;
59
60
snprintf(filename, sizeof(filename), "%s.ppm", prefix);
61
62
rgb8 = MALLOC(height * width * 3);
63
if (!rgb8) {
64
return;
65
}
66
67
util_format_translate(
68
PIPE_FORMAT_R8G8B8_UNORM,
69
rgb8, width * 3,
70
0, 0,
71
format,
72
data, stride,
73
0, 0, width, height);
74
75
/* Must be opened in binary mode or DOS line ending causes data
76
* to be read with one byte offset.
77
*/
78
f = fopen(filename, "wb");
79
if (f) {
80
fprintf(f, "P6\n");
81
fprintf(f, "# ppm-file created by gallium\n");
82
fprintf(f, "%i %i\n", width, height);
83
fprintf(f, "255\n");
84
fwrite(rgb8, 1, height * width * 3, f);
85
fclose(f);
86
}
87
else {
88
fprintf(stderr, "Can't open %s for writing\n", filename);
89
}
90
91
FREE(rgb8);
92
}
93
94
95
/* FIXME: dump resources, not surfaces... */
96
void
97
debug_dump_surface(struct pipe_context *pipe,
98
const char *prefix,
99
struct pipe_surface *surface)
100
{
101
struct pipe_resource *texture;
102
struct pipe_transfer *transfer;
103
void *data;
104
105
if (!surface)
106
return;
107
108
/* XXX: this doesn't necessarily work, as the driver may be using
109
* temporary storage for the surface which hasn't been propagated
110
* back into the texture. Need to nail down the semantics of views
111
* and transfers a bit better before we can say if extra work needs
112
* to be done here:
113
*/
114
texture = surface->texture;
115
116
data = pipe_texture_map(pipe, texture, surface->u.tex.level,
117
surface->u.tex.first_layer,
118
PIPE_MAP_READ,
119
0, 0, surface->width, surface->height, &transfer);
120
if (!data)
121
return;
122
123
debug_dump_image(prefix,
124
texture->format,
125
util_format_get_blocksize(texture->format),
126
util_format_get_nblocksx(texture->format, surface->width),
127
util_format_get_nblocksy(texture->format, surface->height),
128
transfer->stride,
129
data);
130
131
pipe->texture_unmap(pipe, transfer);
132
}
133
134
135
void
136
debug_dump_texture(struct pipe_context *pipe,
137
const char *prefix,
138
struct pipe_resource *texture)
139
{
140
struct pipe_surface *surface, surf_tmpl;
141
142
if (!texture)
143
return;
144
145
/* XXX for now, just dump image for layer=0, level=0 */
146
u_surface_default_template(&surf_tmpl, texture);
147
surface = pipe->create_surface(pipe, texture, &surf_tmpl);
148
if (surface) {
149
debug_dump_surface(pipe, prefix, surface);
150
pipe->surface_destroy(pipe, surface);
151
}
152
}
153
154
155
#pragma pack(push,2)
156
struct bmp_file_header {
157
uint16_t bfType;
158
uint32_t bfSize;
159
uint16_t bfReserved1;
160
uint16_t bfReserved2;
161
uint32_t bfOffBits;
162
};
163
#pragma pack(pop)
164
165
struct bmp_info_header {
166
uint32_t biSize;
167
int32_t biWidth;
168
int32_t biHeight;
169
uint16_t biPlanes;
170
uint16_t biBitCount;
171
uint32_t biCompression;
172
uint32_t biSizeImage;
173
int32_t biXPelsPerMeter;
174
int32_t biYPelsPerMeter;
175
uint32_t biClrUsed;
176
uint32_t biClrImportant;
177
};
178
179
struct bmp_rgb_quad {
180
uint8_t rgbBlue;
181
uint8_t rgbGreen;
182
uint8_t rgbRed;
183
uint8_t rgbAlpha;
184
};
185
186
void
187
debug_dump_surface_bmp(struct pipe_context *pipe,
188
const char *filename,
189
struct pipe_surface *surface)
190
{
191
struct pipe_transfer *transfer;
192
struct pipe_resource *texture = surface->texture;
193
void *ptr;
194
195
ptr = pipe_texture_map(pipe, texture, surface->u.tex.level,
196
surface->u.tex.first_layer, PIPE_MAP_READ,
197
0, 0, surface->width, surface->height, &transfer);
198
199
debug_dump_transfer_bmp(pipe, filename, transfer, ptr);
200
201
pipe->texture_unmap(pipe, transfer);
202
}
203
204
void
205
debug_dump_transfer_bmp(UNUSED struct pipe_context *pipe,
206
const char *filename,
207
struct pipe_transfer *transfer, void *ptr)
208
{
209
float *rgba;
210
211
if (!transfer)
212
goto error1;
213
214
rgba = MALLOC(transfer->box.width *
215
transfer->box.height *
216
transfer->box.depth *
217
4*sizeof(float));
218
if (!rgba)
219
goto error1;
220
221
pipe_get_tile_rgba(transfer, ptr, 0, 0,
222
transfer->box.width, transfer->box.height,
223
transfer->resource->format,
224
rgba);
225
226
debug_dump_float_rgba_bmp(filename,
227
transfer->box.width, transfer->box.height,
228
rgba, transfer->box.width);
229
230
FREE(rgba);
231
error1:
232
;
233
}
234
235
void
236
debug_dump_float_rgba_bmp(const char *filename,
237
unsigned width, unsigned height,
238
float *rgba, unsigned stride)
239
{
240
FILE *stream;
241
struct bmp_file_header bmfh;
242
struct bmp_info_header bmih;
243
unsigned x, y;
244
245
if (!rgba)
246
goto error1;
247
248
bmfh.bfType = 0x4d42;
249
bmfh.bfSize = 14 + 40 + height*width*4;
250
bmfh.bfReserved1 = 0;
251
bmfh.bfReserved2 = 0;
252
bmfh.bfOffBits = 14 + 40;
253
254
bmih.biSize = 40;
255
bmih.biWidth = width;
256
bmih.biHeight = height;
257
bmih.biPlanes = 1;
258
bmih.biBitCount = 32;
259
bmih.biCompression = 0;
260
bmih.biSizeImage = height*width*4;
261
bmih.biXPelsPerMeter = 0;
262
bmih.biYPelsPerMeter = 0;
263
bmih.biClrUsed = 0;
264
bmih.biClrImportant = 0;
265
266
stream = fopen(filename, "wb");
267
if (!stream)
268
goto error1;
269
270
fwrite(&bmfh, 14, 1, stream);
271
fwrite(&bmih, 40, 1, stream);
272
273
y = height;
274
while (y--) {
275
float *ptr = rgba + (stride * y * 4);
276
for (x = 0; x < width; ++x) {
277
struct bmp_rgb_quad pixel;
278
pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);
279
pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
280
pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
281
pixel.rgbAlpha = float_to_ubyte(ptr[x*4 + 3]);
282
fwrite(&pixel, 1, 4, stream);
283
}
284
}
285
286
fclose(stream);
287
error1:
288
;
289
}
290
291
void
292
debug_dump_ubyte_rgba_bmp(const char *filename,
293
unsigned width, unsigned height,
294
const ubyte *rgba, unsigned stride)
295
{
296
FILE *stream;
297
struct bmp_file_header bmfh;
298
struct bmp_info_header bmih;
299
unsigned x, y;
300
301
assert(rgba);
302
if (!rgba)
303
goto error1;
304
305
bmfh.bfType = 0x4d42;
306
bmfh.bfSize = 14 + 40 + height*width*4;
307
bmfh.bfReserved1 = 0;
308
bmfh.bfReserved2 = 0;
309
bmfh.bfOffBits = 14 + 40;
310
311
bmih.biSize = 40;
312
bmih.biWidth = width;
313
bmih.biHeight = height;
314
bmih.biPlanes = 1;
315
bmih.biBitCount = 32;
316
bmih.biCompression = 0;
317
bmih.biSizeImage = height*width*4;
318
bmih.biXPelsPerMeter = 0;
319
bmih.biYPelsPerMeter = 0;
320
bmih.biClrUsed = 0;
321
bmih.biClrImportant = 0;
322
323
stream = fopen(filename, "wb");
324
assert(stream);
325
if (!stream)
326
goto error1;
327
328
fwrite(&bmfh, 14, 1, stream);
329
fwrite(&bmih, 40, 1, stream);
330
331
y = height;
332
while (y--) {
333
const ubyte *ptr = rgba + (stride * y * 4);
334
for (x = 0; x < width; ++x) {
335
struct bmp_rgb_quad pixel;
336
pixel.rgbRed = ptr[x*4 + 0];
337
pixel.rgbGreen = ptr[x*4 + 1];
338
pixel.rgbBlue = ptr[x*4 + 2];
339
pixel.rgbAlpha = ptr[x*4 + 3];
340
fwrite(&pixel, 1, 4, stream);
341
}
342
}
343
344
fclose(stream);
345
error1:
346
;
347
}
348
349
#endif
350
351