@@ -2422,32 +2422,37 @@ QEMUFile *qemu_fopen_uri(const char *uri, const char *mode)
return f;
}
-int ppm_save(const char *uri, struct DisplaySurface *ds)
+static int ppm_line_handler(void *opaque, uint8_t *line, size_t length)
{
- QEMUFile *f;
+ QEMUFile *f = opaque;
+
+ qemu_put_buffer(f, line, length);
+
+ return length;
+}
+
+static int screen_dump_lines(struct DisplaySurface *ds,
+ int (*line_handler) (void *opaque, uint8_t *data, size_t length),
+ void *opaque)
+{
+ char *linebuf, *pbuf;
uint8_t *d, *d1;
uint32_t v;
int y, x;
uint8_t r, g, b;
- char *linebuf, *pbuf;
- gchar *header;
-
- f = qemu_fopen_uri(uri, "wb");
- g_return_val_if_fail(f != NULL, -1);
-
- header = g_strdup_printf("P6\n%d %d\n%d\n", ds->width, ds->height, 255);
- qemu_put_buffer(f, (uint8_t*)header, strlen(header));
+ int ret = -1;
linebuf = g_malloc(ds->width * 3);
d1 = ds->data;
- for(y = 0; y < ds->height; y++) {
+ for (y = 0; y < ds->height; y++) {
d = d1;
pbuf = linebuf;
- for(x = 0; x < ds->width; x++) {
- if (ds->pf.bits_per_pixel == 32)
+ for (x = 0; x < ds->width; x++) {
+ if (ds->pf.bits_per_pixel == 32) {
v = *(uint32_t *)d;
- else
+ } else {
v = (uint32_t) (*(uint16_t *)d);
+ }
/* Limited to 8 or fewer bits per channel: */
r = ((v >> ds->pf.rshift) & ds->pf.rmax) << (8 - ds->pf.rbits);
g = ((v >> ds->pf.gshift) & ds->pf.gmax) << (8 - ds->pf.gbits);
@@ -2458,13 +2463,36 @@ int ppm_save(const char *uri, struct DisplaySurface *ds)
d += ds->pf.bytes_per_pixel;
}
d1 += ds->linesize;
- qemu_put_buffer(f, (uint8_t*)linebuf, pbuf - linebuf);
+
+ if (line_handler(opaque, (uint8_t*)linebuf, pbuf - linebuf) < 0)
+ goto out;
}
+ ret = 0;
+out:
g_free(linebuf);
- g_free(header);
+ return ret;
+}
+
+int ppm_save(const char *uri, struct DisplaySurface *ds)
+{
+ QEMUFile *f;
+ int ret = -1;
+
+ f = qemu_fopen_uri(uri, "wb");
+ g_return_val_if_fail(f != NULL, -1);
+
+ {
+ gchar *header;
+ header = g_strdup_printf("P6\n%d %d\n%d\n", ds->width, ds->height, 255);
+ qemu_put_buffer(f, (uint8_t*)header, strlen(header));
+ screen_dump_lines(ds, ppm_line_handler, f);
+ g_free(header);
+ }
+
+ ret = 0;
qemu_fclose(f);
- return 0;
+ return ret;
}
/* save the vga display in a PPM image even if no display is