Revision 2c62f08d

b/hw/arm/musicpal.c
612 612
    sysbus_init_mmio(dev, &s->iomem);
613 613

  
614 614
    s->con = graphic_console_init(lcd_refresh, lcd_invalidate,
615
                                  NULL, NULL, s);
615
                                  NULL, s);
616 616
    qemu_console_resize(s->con, 128*3, 64*3);
617 617

  
618 618
    qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3);
b/hw/display/blizzard.c
933 933
    s->my[1] = 0;
934 934
}
935 935

  
936
static void blizzard_screen_dump(void *opaque, const char *filename,
937
                                 bool cswitch, Error **errp)
938
{
939
    BlizzardState *s = (BlizzardState *) opaque;
940
    DisplaySurface *surface = qemu_console_surface(s->con);
941

  
942
    blizzard_update_display(opaque);
943
    if (s && surface_data(surface)) {
944
        ppm_save(filename, surface, errp);
945
    }
946
}
947

  
948 936
#define DEPTH 8
949 937
#include "blizzard_template.h"
950 938
#define DEPTH 15
......
965 953

  
966 954
    s->con = graphic_console_init(blizzard_update_display,
967 955
                                  blizzard_invalidate_display,
968
                                  blizzard_screen_dump, NULL, s);
956
                                  NULL, s);
969 957
    surface = qemu_console_surface(s->con);
970 958

  
971 959
    switch (surface_bits_per_pixel(surface)) {
b/hw/display/cirrus_vga.c
2911 2911
    cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0,
2912 2912
                       isa_address_space(dev), isa_address_space_io(dev));
2913 2913
    s->con = graphic_console_init(s->update, s->invalidate,
2914
                                  s->screen_dump, s->text_update,
2914
                                  s->text_update,
2915 2915
                                  s);
2916 2916
    rom_add_vga(VGABIOS_CIRRUS_FILENAME);
2917 2917
    /* XXX ISA-LFB support */
......
2960 2960
     cirrus_init_common(s, device_id, 1, pci_address_space(dev),
2961 2961
                        pci_address_space_io(dev));
2962 2962
     s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate,
2963
                                       s->vga.screen_dump, s->vga.text_update,
2963
                                       s->vga.text_update,
2964 2964
                                       &s->vga);
2965 2965

  
2966 2966
     /* setup PCI */
b/hw/display/exynos4210_fimd.c
1901 1901
            "exynos4210.fimd", FIMD_REGS_SIZE);
1902 1902
    sysbus_init_mmio(dev, &s->iomem);
1903 1903
    s->console = graphic_console_init(exynos4210_fimd_update,
1904
                                  exynos4210_fimd_invalidate, NULL, NULL, s);
1904
                                      exynos4210_fimd_invalidate, NULL, s);
1905 1905

  
1906 1906
    return 0;
1907 1907
}
b/hw/display/g364fb.c
294 294
    g364fb_invalidate_display(s);
295 295
}
296 296

  
297
static void g364fb_screen_dump(void *opaque, const char *filename, bool cswitch,
298
                               Error **errp)
299
{
300
    G364State *s = opaque;
301
    int ret, y, x;
302
    uint8_t index;
303
    uint8_t *data_buffer;
304
    FILE *f;
305

  
306
    qemu_flush_coalesced_mmio_buffer();
307

  
308
    if (s->depth != 8) {
309
        error_setg(errp, "g364: unknown guest depth %d", s->depth);
310
        return;
311
    }
312

  
313
    f = fopen(filename, "wb");
314
    if (!f) {
315
        error_setg(errp, "failed to open file '%s': %s", filename,
316
                   strerror(errno));
317
        return;
318
    }
319

  
320
    if (s->ctla & CTLA_FORCE_BLANK) {
321
        /* blank screen */
322
        ret = fprintf(f, "P4\n%d %d\n", s->width, s->height);
323
        if (ret < 0) {
324
            goto write_err;
325
        }
326
        for (y = 0; y < s->height; y++)
327
            for (x = 0; x < s->width; x++) {
328
                ret = fputc(0, f);
329
                if (ret == EOF) {
330
                    goto write_err;
331
                }
332
            }
333
    } else {
334
        data_buffer = s->vram + s->top_of_screen;
335
        ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
336
        if (ret < 0) {
337
            goto write_err;
338
        }
339
        for (y = 0; y < s->height; y++)
340
            for (x = 0; x < s->width; x++, data_buffer++) {
341
                index = *data_buffer;
342
                ret = fputc(s->color_palette[index][0], f);
343
                if (ret == EOF) {
344
                    goto write_err;
345
                }
346
                ret = fputc(s->color_palette[index][1], f);
347
                if (ret == EOF) {
348
                    goto write_err;
349
                }
350
                ret = fputc(s->color_palette[index][2], f);
351
                if (ret == EOF) {
352
                    goto write_err;
353
                }
354
        }
355
    }
356

  
357
out:
358
    fclose(f);
359
    return;
360

  
361
write_err:
362
    error_setg(errp, "failed to write to file '%s': %s", filename,
363
               strerror(errno));
364
    unlink(filename);
365
    goto out;
366
}
367

  
368 297
/* called for accesses to io ports */
369 298
static uint64_t g364fb_ctrl_read(void *opaque,
370 299
                                 hwaddr addr,
......
552 481

  
553 482
    s->con = graphic_console_init(g364fb_update_display,
554 483
                                  g364fb_invalidate_display,
555
                                  g364fb_screen_dump, NULL, s);
484
                                  NULL, s);
556 485

  
557 486
    memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000);
558 487
    memory_region_init_ram_ptr(&s->mem_vram, "vram",
b/hw/display/jazz_led.c
263 263

  
264 264
    s->con = graphic_console_init(jazz_led_update_display,
265 265
                                  jazz_led_invalidate_display,
266
                                  NULL,
267 266
                                  jazz_led_text_update, s);
268 267

  
269 268
    return 0;
b/hw/display/milkymist-vgafb.c
280 280

  
281 281
    s->con = graphic_console_init(vgafb_update_display,
282 282
                                  vgafb_invalidate_display,
283
                                  NULL, NULL, s);
283
                                  NULL, s);
284 284

  
285 285
    return 0;
286 286
}
b/hw/display/omap_lcdc.c
227 227
    omap_lcd->invalidate = 0;
228 228
}
229 229

  
230
static void omap_ppm_save(const char *filename, uint8_t *data,
231
                    int w, int h, int linesize, Error **errp)
232
{
233
    FILE *f;
234
    uint8_t *d, *d1;
235
    unsigned int v;
236
    int ret, y, x, bpp;
237

  
238
    f = fopen(filename, "wb");
239
    if (!f) {
240
        error_setg(errp, "failed to open file '%s': %s", filename,
241
                   strerror(errno));
242
        return;
243
    }
244
    ret = fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
245
    if (ret < 0) {
246
        goto write_err;
247
    }
248
    d1 = data;
249
    bpp = linesize / w;
250
    for (y = 0; y < h; y ++) {
251
        d = d1;
252
        for (x = 0; x < w; x ++) {
253
            v = *(uint32_t *) d;
254
            switch (bpp) {
255
            case 2:
256
                ret = fputc((v >> 8) & 0xf8, f);
257
                if (ret == EOF) {
258
                    goto write_err;
259
                }
260
                ret = fputc((v >> 3) & 0xfc, f);
261
                if (ret == EOF) {
262
                    goto write_err;
263
                }
264
                ret = fputc((v << 3) & 0xf8, f);
265
                if (ret == EOF) {
266
                    goto write_err;
267
                }
268
                break;
269
            case 3:
270
            case 4:
271
            default:
272
                ret = fputc((v >> 16) & 0xff, f);
273
                if (ret == EOF) {
274
                    goto write_err;
275
                }
276
                ret = fputc((v >> 8) & 0xff, f);
277
                if (ret == EOF) {
278
                    goto write_err;
279
                }
280
                ret = fputc((v) & 0xff, f);
281
                if (ret == EOF) {
282
                    goto write_err;
283
                }
284
                break;
285
            }
286
            d += bpp;
287
        }
288
        d1 += linesize;
289
    }
290
out:
291
    fclose(f);
292
    return;
293

  
294
write_err:
295
    error_setg(errp, "failed to write to file '%s': %s", filename,
296
               strerror(errno));
297
    unlink(filename);
298
    goto out;
299
}
300

  
301
static void omap_screen_dump(void *opaque, const char *filename, bool cswitch,
302
                             Error **errp)
303
{
304
    struct omap_lcd_panel_s *omap_lcd = opaque;
305
    DisplaySurface *surface = qemu_console_surface(omap_lcd->con);
306

  
307
    omap_update_display(opaque);
308
    if (omap_lcd && surface_data(surface))
309
        omap_ppm_save(filename, surface_data(surface),
310
                    omap_lcd->width, omap_lcd->height,
311
                    surface_stride(surface), errp);
312
}
313

  
314 230
static void omap_invalidate_display(void *opaque) {
315 231
    struct omap_lcd_panel_s *omap_lcd = opaque;
316 232
    omap_lcd->invalidate = 1;
......
487 403

  
488 404
    s->con = graphic_console_init(omap_update_display,
489 405
                                  omap_invalidate_display,
490
                                  omap_screen_dump, NULL, s);
406
                                  NULL, s);
491 407

  
492 408
    return s;
493 409
}
b/hw/display/pl110.c
454 454
    qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1);
455 455
    s->con = graphic_console_init(pl110_update_display,
456 456
                                  pl110_invalidate_display,
457
                                  NULL, NULL, s);
457
                                  NULL, s);
458 458
    return 0;
459 459
}
460 460

  
b/hw/display/pxa2xx_lcd.c
1010 1010

  
1011 1011
    s->con = graphic_console_init(pxa2xx_update_display,
1012 1012
                                  pxa2xx_invalidate_display,
1013
                                  NULL, NULL, s);
1013
                                  NULL, s);
1014 1014
    surface = qemu_console_surface(s->con);
1015 1015

  
1016 1016
    switch (surface_bits_per_pixel(surface)) {
b/hw/display/qxl.c
1772 1772
    vga->invalidate(vga);
1773 1773
}
1774 1774

  
1775
static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch,
1776
                               Error **errp)
1777
{
1778
    PCIQXLDevice *qxl = opaque;
1779
    VGACommonState *vga = &qxl->vga;
1780

  
1781
    switch (qxl->mode) {
1782
    case QXL_MODE_COMPAT:
1783
    case QXL_MODE_NATIVE:
1784
        qxl_render_update(qxl);
1785
        ppm_save(filename, qxl->ssd.ds, errp);
1786
        break;
1787
    case QXL_MODE_VGA:
1788
        vga->screen_dump(vga, filename, cswitch, errp);
1789
        break;
1790
    default:
1791
        break;
1792
    }
1793
}
1794

  
1795 1775
static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
1796 1776
{
1797 1777
    PCIQXLDevice *qxl = opaque;
......
2075 2055
    portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
2076 2056

  
2077 2057
    vga->con = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
2078
                                    qxl_hw_screen_dump, qxl_hw_text_update,
2058
                                    qxl_hw_text_update,
2079 2059
                                    qxl);
2080 2060
    qxl->ssd.con = vga->con,
2081 2061
    qemu_spice_display_init_common(&qxl->ssd);
b/hw/display/sm501.c
1446 1446

  
1447 1447
    /* create qemu graphic console */
1448 1448
    s->con = graphic_console_init(sm501_update_display, NULL,
1449
                                  NULL, NULL, s);
1449
                                  NULL, s);
1450 1450
}
b/hw/display/ssd0303.c
290 290

  
291 291
    s->con = graphic_console_init(ssd0303_update_display,
292 292
                                  ssd0303_invalidate_display,
293
                                  NULL, NULL, s);
293
                                  NULL, s);
294 294
    qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY);
295 295
    return 0;
296 296
}
b/hw/display/ssd0323.c
339 339
    s->row_end = 79;
340 340
    s->con = graphic_console_init(ssd0323_update_display,
341 341
                                  ssd0323_invalidate_display,
342
                                  NULL, NULL, s);
342
                                  NULL, s);
343 343
    qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
344 344

  
345 345
    qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
b/hw/display/tc6393xb.c
585 585
    s->scr_height = 640;
586 586
    s->con = graphic_console_init(tc6393xb_update_display,
587 587
            NULL, /* invalidate */
588
            NULL, /* screen_dump */
589 588
            NULL, /* text_update */
590 589
            s);
591 590

  
b/hw/display/tcx.c
56 56
    uint8_t dac_index, dac_state;
57 57
} TCXState;
58 58

  
59
static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch,
60
                            Error **errp);
61
static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
62
                            Error **errp);
63

  
64 59
static void tcx_set_dirty(TCXState *s)
65 60
{
66 61
    memory_region_set_dirty(&s->vram_mem, 0, MAXX * MAXY);
......
569 564

  
570 565
        s->con = graphic_console_init(tcx24_update_display,
571 566
                                      tcx24_invalidate_display,
572
                                      tcx24_screen_dump, NULL, s);
567
                                      NULL, s);
573 568
    } else {
574 569
        /* THC 8 bit (dummy) */
575 570
        memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
......
578 573

  
579 574
        s->con = graphic_console_init(tcx_update_display,
580 575
                                      tcx_invalidate_display,
581
                                      tcx_screen_dump, NULL, s);
576
                                      NULL, s);
582 577
    }
583 578

  
584 579
    qemu_console_resize(s->con, s->width, s->height);
585 580
    return 0;
586 581
}
587 582

  
588
static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch,
589
                            Error **errp)
590
{
591
    TCXState *s = opaque;
592
    FILE *f;
593
    uint8_t *d, *d1, v;
594
    int ret, y, x;
595

  
596
    f = fopen(filename, "wb");
597
    if (!f) {
598
        error_setg(errp, "failed to open file '%s': %s", filename,
599
                   strerror(errno));
600
        return;
601
    }
602
    ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
603
    if (ret < 0) {
604
        goto write_err;
605
    }
606
    d1 = s->vram;
607
    for(y = 0; y < s->height; y++) {
608
        d = d1;
609
        for(x = 0; x < s->width; x++) {
610
            v = *d;
611
            ret = fputc(s->r[v], f);
612
            if (ret == EOF) {
613
                goto write_err;
614
            }
615
            ret = fputc(s->g[v], f);
616
            if (ret == EOF) {
617
                goto write_err;
618
            }
619
            ret = fputc(s->b[v], f);
620
            if (ret == EOF) {
621
                goto write_err;
622
            }
623
            d++;
624
        }
625
        d1 += MAXX;
626
    }
627

  
628
out:
629
    fclose(f);
630
    return;
631

  
632
write_err:
633
    error_setg(errp, "failed to write to file '%s': %s", filename,
634
               strerror(errno));
635
    unlink(filename);
636
    goto out;
637
}
638

  
639
static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
640
                              Error **errp)
641
{
642
    TCXState *s = opaque;
643
    FILE *f;
644
    uint8_t *d, *d1, v;
645
    uint32_t *s24, *cptr, dval;
646
    int ret, y, x;
647

  
648
    f = fopen(filename, "wb");
649
    if (!f) {
650
        error_setg(errp, "failed to open file '%s': %s", filename,
651
                   strerror(errno));
652
        return;
653
    }
654
    ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
655
    if (ret < 0) {
656
        goto write_err;
657
    }
658
    d1 = s->vram;
659
    s24 = s->vram24;
660
    cptr = s->cplane;
661
    for(y = 0; y < s->height; y++) {
662
        d = d1;
663
        for(x = 0; x < s->width; x++, d++, s24++) {
664
            if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct
665
                dval = *s24 & 0x00ffffff;
666
                ret = fputc((dval >> 16) & 0xff, f);
667
                if (ret == EOF) {
668
                    goto write_err;
669
                }
670
                ret = fputc((dval >> 8) & 0xff, f);
671
                if (ret == EOF) {
672
                    goto write_err;
673
                }
674
                ret = fputc(dval & 0xff, f);
675
                if (ret == EOF) {
676
                    goto write_err;
677
                }
678
            } else {
679
                v = *d;
680
                ret = fputc(s->r[v], f);
681
                if (ret == EOF) {
682
                    goto write_err;
683
                }
684
                ret = fputc(s->g[v], f);
685
                if (ret == EOF) {
686
                    goto write_err;
687
                }
688
                ret = fputc(s->b[v], f);
689
                if (ret == EOF) {
690
                    goto write_err;
691
                }
692
            }
693
        }
694
        d1 += MAXX;
695
    }
696

  
697
out:
698
    fclose(f);
699
    return;
700

  
701
write_err:
702
    error_setg(errp, "failed to write to file '%s': %s", filename,
703
               strerror(errno));
704
    unlink(filename);
705
    goto out;
706
}
707

  
708 583
static Property tcx_properties[] = {
709 584
    DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
710 585
    DEFINE_PROP_UINT16("width",    TCXState, width,     -1),
b/hw/display/vga-isa-mm.c
136 136
    vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
137 137

  
138 138
    s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate,
139
                                      s->vga.screen_dump, s->vga.text_update,
139
                                      s->vga.text_update,
140 140
                                      s);
141 141

  
142 142
    vga_init_vbe(&s->vga, address_space);
b/hw/display/vga-isa.c
63 63
                                        vga_io_memory, 1);
64 64
    memory_region_set_coalescing(vga_io_memory);
65 65
    s->con = graphic_console_init(s->update, s->invalidate,
66
                                  s->screen_dump, s->text_update, s);
66
                                  s->text_update, s);
67 67

  
68 68
    vga_init_vbe(s, isa_address_space(dev));
69 69
    /* ROM BIOS */
b/hw/display/vga-pci.c
151 151
    vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true);
152 152

  
153 153
    s->con = graphic_console_init(s->update, s->invalidate,
154
                                  s->screen_dump, s->text_update, s);
154
                                  s->text_update, s);
155 155

  
156 156
    /* XXX: VGA_RAM_SIZE must be a power of two */
157 157
    pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
b/hw/display/vga.c
166 166
static uint16_t expand2[256];
167 167
static uint8_t expand4to8[16];
168 168

  
169
static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
170
                            Error **errp);
171

  
172 169
static void vga_update_memory_access(VGACommonState *s)
173 170
{
174 171
    MemoryRegion *region, *old_region = s->chain4_alias;
......
2298 2295
    s->get_resolution = vga_get_resolution;
2299 2296
    s->update = vga_update_display;
2300 2297
    s->invalidate = vga_invalidate_display;
2301
    s->screen_dump = vga_screen_dump;
2302 2298
    s->text_update = vga_update_text;
2303 2299
    switch (vga_retrace_method) {
2304 2300
    case VGA_RETRACE_DUMB:
......
2393 2389
                                &s->vram_vbe);
2394 2390
    s->vbe_mapped = 1;
2395 2391
}
2396
/********************************************************/
2397
/* vga screen dump */
2398

  
2399
void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp)
2400
{
2401
    int width = pixman_image_get_width(ds->image);
2402
    int height = pixman_image_get_height(ds->image);
2403
    FILE *f;
2404
    int y;
2405
    int ret;
2406
    pixman_image_t *linebuf;
2407

  
2408
    trace_ppm_save(filename, ds);
2409
    f = fopen(filename, "wb");
2410
    if (!f) {
2411
        error_setg(errp, "failed to open file '%s': %s", filename,
2412
                   strerror(errno));
2413
        return;
2414
    }
2415
    ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255);
2416
    if (ret < 0) {
2417
        linebuf = NULL;
2418
        goto write_err;
2419
    }
2420
    linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width);
2421
    for (y = 0; y < height; y++) {
2422
        qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y);
2423
        clearerr(f);
2424
        ret = fwrite(pixman_image_get_data(linebuf), 1,
2425
                     pixman_image_get_stride(linebuf), f);
2426
        (void)ret;
2427
        if (ferror(f)) {
2428
            goto write_err;
2429
        }
2430
    }
2431

  
2432
out:
2433
    qemu_pixman_image_unref(linebuf);
2434
    fclose(f);
2435
    return;
2436

  
2437
write_err:
2438
    error_setg(errp, "failed to write to file '%s': %s", filename,
2439
               strerror(errno));
2440
    unlink(filename);
2441
    goto out;
2442
}
2443

  
2444
/* save the vga display in a PPM image even if no display is
2445
   available */
2446
static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
2447
                            Error **errp)
2448
{
2449
    VGACommonState *s = opaque;
2450
    DisplaySurface *surface = qemu_console_surface(s->con);
2451

  
2452
    if (cswitch) {
2453
        vga_invalidate_display(s);
2454
    }
2455
    graphic_hw_update(s->con);
2456
    ppm_save(filename, surface, errp);
2457
}
b/hw/display/vga_int.h
154 154
                                 unsigned int g, unsigned b);
155 155
    graphic_hw_update_ptr update;
156 156
    graphic_hw_invalidate_ptr invalidate;
157
    graphic_hw_screen_dump_ptr screen_dump;
158 157
    graphic_hw_text_update_ptr text_update;
159 158
    bool full_update_text;
160 159
    bool full_update_gfx;
......
198 197
uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr);
199 198
void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val);
200 199
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2);
201
void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp);
202 200

  
203 201
int vga_ioport_invalid(VGACommonState *s, uint32_t addr);
204 202

  
b/hw/display/vmware_vga.c
1119 1119
    s->invalidated = 1;
1120 1120
}
1121 1121

  
1122
/* save the vga display in a PPM image even if no display is
1123
   available */
1124
static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch,
1125
                               Error **errp)
1126
{
1127
    struct vmsvga_state_s *s = opaque;
1128
    DisplaySurface *surface = qemu_console_surface(s->vga.con);
1129

  
1130
    if (!s->enable) {
1131
        s->vga.screen_dump(&s->vga, filename, cswitch, errp);
1132
        return;
1133
    }
1134

  
1135
    if (surface_bits_per_pixel(surface) == 32) {
1136
        DisplaySurface *ds = qemu_create_displaysurface_from(
1137
                                 surface_width(surface),
1138
                                 surface_height(surface),
1139
                                 32,
1140
                                 surface_stride(surface),
1141
                                 s->vga.vram_ptr, false);
1142
        ppm_save(filename, ds, errp);
1143
        g_free(ds);
1144
    }
1145
}
1146

  
1147 1122
static void vmsvga_text_update(void *opaque, console_ch_t *chardata)
1148 1123
{
1149 1124
    struct vmsvga_state_s *s = opaque;
......
1212 1187

  
1213 1188
    s->vga.con = graphic_console_init(vmsvga_update_display,
1214 1189
                                      vmsvga_invalidate_display,
1215
                                      vmsvga_screen_dump,
1216 1190
                                      vmsvga_text_update, s);
1217 1191

  
1218 1192
    s->fifo_size = SVGA_FIFO_SIZE;
b/hw/display/xenfb.c
1007 1007
    fb->c.con = graphic_console_init(xenfb_update,
1008 1008
                                     xenfb_invalidate,
1009 1009
                                     NULL,
1010
                                     NULL,
1011 1010
                                     fb);
1012 1011
    fb->have_console = 1;
1013 1012

  
b/hw/unicore32/puv3.c
92 92
    }
93 93

  
94 94
    /* cheat curses that we have a graphic console, only under ocd console */
95
    graphic_console_init(NULL, NULL, NULL, NULL, NULL);
95
    graphic_console_init(NULL, NULL, NULL, NULL);
96 96
}
97 97

  
98 98
static void puv3_init(QEMUMachineInitArgs *args)
b/include/ui/console.h
279 279

  
280 280
typedef void (*graphic_hw_update_ptr)(void *);
281 281
typedef void (*graphic_hw_invalidate_ptr)(void *);
282
typedef void (*graphic_hw_screen_dump_ptr)(void *, const char *, bool cswitch,
283
                                       Error **errp);
284 282
typedef void (*graphic_hw_text_update_ptr)(void *, console_ch_t *);
285 283

  
286 284
QemuConsole *graphic_console_init(graphic_hw_update_ptr update,
287 285
                                  graphic_hw_invalidate_ptr invalidate,
288
                                  graphic_hw_screen_dump_ptr screen_dump,
289 286
                                  graphic_hw_text_update_ptr text_update,
290 287
                                  void *opaque);
291 288

  
b/ui/console.c
121 121
    /* Graphic console state.  */
122 122
    graphic_hw_update_ptr hw_update;
123 123
    graphic_hw_invalidate_ptr hw_invalidate;
124
    graphic_hw_screen_dump_ptr hw_screen_dump;
125 124
    graphic_hw_text_update_ptr hw_text_update;
126 125
    void *hw;
127 126
    int g_width, g_height;
......
188 187
    }
189 188
}
190 189

  
191
void qmp_screendump(const char *filename, Error **errp)
190
static void ppm_save(const char *filename, struct DisplaySurface *ds,
191
                     Error **errp)
192 192
{
193
    QemuConsole *previous_active_console;
194
    bool cswitch;
195

  
196
    previous_active_console = active_console;
197
    cswitch = previous_active_console && previous_active_console->index != 0;
193
    int width = pixman_image_get_width(ds->image);
194
    int height = pixman_image_get_height(ds->image);
195
    FILE *f;
196
    int y;
197
    int ret;
198
    pixman_image_t *linebuf;
198 199

  
199
    /* There is currently no way of specifying which screen we want to dump,
200
       so always dump the first one.  */
201
    if (cswitch) {
202
        console_select(0);
200
    trace_ppm_save(filename, ds);
201
    f = fopen(filename, "wb");
202
    if (!f) {
203
        error_setg(errp, "failed to open file '%s': %s", filename,
204
                   strerror(errno));
205
        return;
203 206
    }
204
    if (consoles[0] && consoles[0]->hw_screen_dump) {
205
        consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, errp);
206
    } else {
207
        error_setg(errp, "device doesn't support screendump");
207
    ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255);
208
    if (ret < 0) {
209
        linebuf = NULL;
210
        goto write_err;
211
    }
212
    linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width);
213
    for (y = 0; y < height; y++) {
214
        qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y);
215
        clearerr(f);
216
        ret = fwrite(pixman_image_get_data(linebuf), 1,
217
                     pixman_image_get_stride(linebuf), f);
218
        (void)ret;
219
        if (ferror(f)) {
220
            goto write_err;
221
        }
208 222
    }
209 223

  
210
    if (cswitch) {
211
        console_select(previous_active_console->index);
224
out:
225
    qemu_pixman_image_unref(linebuf);
226
    fclose(f);
227
    return;
228

  
229
write_err:
230
    error_setg(errp, "failed to write to file '%s': %s", filename,
231
               strerror(errno));
232
    unlink(filename);
233
    goto out;
234
}
235

  
236
void qmp_screendump(const char *filename, Error **errp)
237
{
238
    QemuConsole *con = consoles[0];
239
    DisplaySurface *surface;
240

  
241
    if (con == NULL) {
242
        error_setg(errp, "There is no QemuConsole I can screendump from.");
243
        return;
212 244
    }
245

  
246
    graphic_hw_update(con);
247
    surface = qemu_console_surface(con);
248
    ppm_save(filename, surface, errp);
213 249
}
214 250

  
215 251
void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata)
......
1411 1447

  
1412 1448
QemuConsole *graphic_console_init(graphic_hw_update_ptr update,
1413 1449
                                  graphic_hw_invalidate_ptr invalidate,
1414
                                  graphic_hw_screen_dump_ptr screen_dump,
1415 1450
                                  graphic_hw_text_update_ptr text_update,
1416 1451
                                  void *opaque)
1417 1452
{
......
1425 1460
    s = new_console(ds, GRAPHIC_CONSOLE);
1426 1461
    s->hw_update = update;
1427 1462
    s->hw_invalidate = invalidate;
1428
    s->hw_screen_dump = screen_dump;
1429 1463
    s->hw_text_update = text_update;
1430 1464
    s->hw = opaque;
1431 1465

  

Also available in: Unified diff