From 522fccbe71e35efc96f66cb475f778c2ce02e9fc Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Tue, 19 Mar 2013 23:44:55 +0400 Subject: exynos4210_fimd.c: fix display resize bug introduced after console revamp In exynos4210 display update function, we were acquiring DisplaySurface pointer before calling screen resize function, not paying attention that resize procedure can replace current DisplaySurface with newly allocated one. Right thing to do is to initialize DisplaySurface AFTER a call to resize function. Signed-off-by: Igor Mitsyanko Signed-off-by: Gerd Hoffmann --- hw/display/exynos4210_fimd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c index 49cca4bf94..7e1cbb63c9 100644 --- a/hw/display/exynos4210_fimd.c +++ b/hw/display/exynos4210_fimd.c @@ -1242,7 +1242,7 @@ static void exynos4210_update_resolution(Exynos4210fimdState *s) static void exynos4210_fimd_update(void *opaque) { Exynos4210fimdState *s = (Exynos4210fimdState *)opaque; - DisplaySurface *surface = qemu_console_surface(s->console); + DisplaySurface *surface; Exynos4210fimdWindow *w; int i, line; hwaddr fb_line_addr, inc_size; @@ -1255,11 +1255,12 @@ static void exynos4210_fimd_update(void *opaque) const int global_height = ((s->vidtcon[2] >> FIMD_VIDTCON2_VER_SHIFT) & FIMD_VIDTCON2_SIZE_MASK) + 1; - if (!s || !s->console || !surface_bits_per_pixel(surface) || - !s->enabled) { + if (!s || !s->console || !s->enabled || + surface_bits_per_pixel(qemu_console_surface(s->console)) == 0) { return; } exynos4210_update_resolution(s); + surface = qemu_console_surface(s->console); for (i = 0; i < NUM_OF_WINDOWS; i++) { w = &s->window[i]; -- cgit v1.2.3 From 17866fc888445ec7d2568645df45bb47e6be01de Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Tue, 19 Mar 2013 23:44:56 +0400 Subject: hw/vmware_vga.c: fix screen resize bug introduced after console revamp In vmsvga display update function, a pointer to DisplaySurface must be acquired after a call to vmsvga_check_size since this function might replace current DisplaySurface with a new one. Signed-off-by: Igor Mitsyanko Signed-off-by: Gerd Hoffmann --- hw/display/vmware_vga.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index bcad47a68d..2233a8bede 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -995,7 +995,7 @@ static inline void vmsvga_check_size(struct vmsvga_state_s *s) static void vmsvga_update_display(void *opaque) { struct vmsvga_state_s *s = opaque; - DisplaySurface *surface = qemu_console_surface(s->vga.con); + DisplaySurface *surface; bool dirty = false; if (!s->enable) { @@ -1004,6 +1004,7 @@ static void vmsvga_update_display(void *opaque) } vmsvga_check_size(s); + surface = qemu_console_surface(s->vga.con); vmsvga_fifo_run(s); vmsvga_update_rect_flush(s); -- cgit v1.2.3 From 7a6404cd8be97d73d1fc272dda82445c19f05aa1 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 25 Mar 2013 09:53:35 +0100 Subject: hw/vmware_vga.c: add tracepoints for mmio reads+writes Signed-off-by: Gerd Hoffmann --- hw/display/vmware_vga.c | 112 ++++++++++++++++++++++++++++++++++-------------- trace-events | 6 +++ 2 files changed, 86 insertions(+), 32 deletions(-) diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 2233a8bede..20e3a28c51 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -721,61 +721,79 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) uint32_t caps; struct vmsvga_state_s *s = opaque; DisplaySurface *surface = qemu_console_surface(s->vga.con); + uint32_t ret; switch (s->index) { case SVGA_REG_ID: - return s->svgaid; + ret = s->svgaid; + break; case SVGA_REG_ENABLE: - return s->enable; + ret = s->enable; + break; case SVGA_REG_WIDTH: - return surface_width(surface); + ret = surface_width(surface); + break; case SVGA_REG_HEIGHT: - return surface_height(surface); + ret = surface_height(surface); + break; case SVGA_REG_MAX_WIDTH: - return SVGA_MAX_WIDTH; + ret = SVGA_MAX_WIDTH; + break; case SVGA_REG_MAX_HEIGHT: - return SVGA_MAX_HEIGHT; + ret = SVGA_MAX_HEIGHT; + break; case SVGA_REG_DEPTH: - return s->depth; + ret = s->depth; + break; case SVGA_REG_BITS_PER_PIXEL: - return (s->depth + 7) & ~7; + ret = (s->depth + 7) & ~7; + break; case SVGA_REG_PSEUDOCOLOR: - return 0x0; + ret = 0x0; + break; case SVGA_REG_RED_MASK: - return surface->pf.rmask; + ret = surface->pf.rmask; + break; case SVGA_REG_GREEN_MASK: - return surface->pf.gmask; + ret = surface->pf.gmask; + break; case SVGA_REG_BLUE_MASK: - return surface->pf.bmask; + ret = surface->pf.bmask; + break; case SVGA_REG_BYTES_PER_LINE: - return s->bypp * s->new_width; + ret = s->bypp * s->new_width; + break; case SVGA_REG_FB_START: { struct pci_vmsvga_state_s *pci_vmsvga = container_of(s, struct pci_vmsvga_state_s, chip); - return pci_get_bar_addr(&pci_vmsvga->card, 1); + ret = pci_get_bar_addr(&pci_vmsvga->card, 1); + break; } case SVGA_REG_FB_OFFSET: - return 0x0; + ret = 0x0; + break; case SVGA_REG_VRAM_SIZE: - return s->vga.vram_size; /* No physical VRAM besides the framebuffer */ + ret = s->vga.vram_size; /* No physical VRAM besides the framebuffer */ + break; case SVGA_REG_FB_SIZE: - return s->vga.vram_size; + ret = s->vga.vram_size; + break; case SVGA_REG_CAPABILITIES: caps = SVGA_CAP_NONE; @@ -791,66 +809,96 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) SVGA_CAP_CURSOR_BYPASS; } #endif - return caps; + ret = caps; + break; case SVGA_REG_MEM_START: { struct pci_vmsvga_state_s *pci_vmsvga = container_of(s, struct pci_vmsvga_state_s, chip); - return pci_get_bar_addr(&pci_vmsvga->card, 2); + ret = pci_get_bar_addr(&pci_vmsvga->card, 2); + break; } case SVGA_REG_MEM_SIZE: - return s->fifo_size; + ret = s->fifo_size; + break; case SVGA_REG_CONFIG_DONE: - return s->config; + ret = s->config; + break; case SVGA_REG_SYNC: case SVGA_REG_BUSY: - return s->syncing; + ret = s->syncing; + break; case SVGA_REG_GUEST_ID: - return s->guest; + ret = s->guest; + break; case SVGA_REG_CURSOR_ID: - return s->cursor.id; + ret = s->cursor.id; + break; case SVGA_REG_CURSOR_X: - return s->cursor.x; + ret = s->cursor.x; + break; case SVGA_REG_CURSOR_Y: - return s->cursor.x; + ret = s->cursor.x; + break; case SVGA_REG_CURSOR_ON: - return s->cursor.on; + ret = s->cursor.on; + break; case SVGA_REG_HOST_BITS_PER_PIXEL: - return (s->depth + 7) & ~7; + ret = (s->depth + 7) & ~7; + break; case SVGA_REG_SCRATCH_SIZE: - return s->scratch_size; + ret = s->scratch_size; + break; case SVGA_REG_MEM_REGS: case SVGA_REG_NUM_DISPLAYS: case SVGA_REG_PITCHLOCK: case SVGA_PALETTE_BASE ... SVGA_PALETTE_END: - return 0; + ret = 0; + break; default: if (s->index >= SVGA_SCRATCH_BASE && s->index < SVGA_SCRATCH_BASE + s->scratch_size) { - return s->scratch[s->index - SVGA_SCRATCH_BASE]; + ret = s->scratch[s->index - SVGA_SCRATCH_BASE]; + break; } printf("%s: Bad register %02x\n", __func__, s->index); + ret = 0; + break; } - return 0; + if (s->index >= SVGA_SCRATCH_BASE) { + trace_vmware_scratch_read(s->index, ret); + } else if (s->index >= SVGA_PALETTE_BASE) { + trace_vmware_palette_read(s->index, ret); + } else { + trace_vmware_value_read(s->index, ret); + } + return ret; } static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) { struct vmsvga_state_s *s = opaque; + if (s->index >= SVGA_SCRATCH_BASE) { + trace_vmware_scratch_write(s->index, value); + } else if (s->index >= SVGA_PALETTE_BASE) { + trace_vmware_palette_write(s->index, value); + } else { + trace_vmware_value_write(s->index, value); + } switch (s->index) { case SVGA_REG_ID: if (value == SVGA_ID_2 || value == SVGA_ID_1 || value == SVGA_ID_0) { diff --git a/trace-events b/trace-events index 412f7e40f8..6c795dc7ff 100644 --- a/trace-events +++ b/trace-events @@ -970,6 +970,12 @@ displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]" # vga.c ppm_save(const char *filename, void *display_surface) "%s surface=%p" +vmware_value_read(uint32_t index, uint32_t value) "index %d, value 0x%x" +vmware_value_write(uint32_t index, uint32_t value) "index %d, value 0x%x" +vmware_palette_read(uint32_t index, uint32_t value) "index %d, value 0x%x" +vmware_palette_write(uint32_t index, uint32_t value) "index %d, value 0x%x" +vmware_scratch_read(uint32_t index, uint32_t value) "index %d, value 0x%x" +vmware_scratch_write(uint32_t index, uint32_t value) "index %d, value 0x%x" # savevm.c -- cgit v1.2.3 From eb2f9b024d68884a3b25e63e4dbf90b67f8da236 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 25 Mar 2013 11:44:21 +0100 Subject: hw/vmware_vga.c: various vmware vga fixes. Hardcode depth to 32 bpp. It effectively was that way before because that is the default surface depth, this just makes it explicit in the code. Rename depth to new_depth to make it consistent with the new_width + new_height names. In theory we can make new_depth changeable (i.e. allow the guest to fill in -- say -- 16 there). In practice the guests don't try, the X-Server refuses to start if you ask it to use 16bpp depth (via DefaultDepth in the Screen section). Always return the correct rmask+gmask+bmask values for the given new_depth. Fix mode setting to also verify at new_depth to make sure we have a correct DisplaySurface, even if the current video mode happes to be 16bpp (set by vgabios via bochs vbe interface). While being at it switch over to use qemu_create_displaysurface_from, so the surface is backed by guest-visible video memory and we save a memcpy. Signed-off-by: Gerd Hoffmann --- hw/display/vmware_vga.c | 57 ++++++++++++++++++++++++++----------------------- trace-events | 1 + 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 20e3a28c51..05befe44c7 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -39,8 +39,6 @@ struct vmsvga_state_s { VGACommonState vga; int invalidated; - int depth; - int bypp; int enable; int config; struct { @@ -55,6 +53,7 @@ struct vmsvga_state_s { uint32_t *scratch; int new_width; int new_height; + int new_depth; uint32_t guest; uint32_t svgaid; int syncing; @@ -721,6 +720,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) uint32_t caps; struct vmsvga_state_s *s = opaque; DisplaySurface *surface = qemu_console_surface(s->vga.con); + PixelFormat pf; uint32_t ret; switch (s->index) { @@ -733,11 +733,11 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) break; case SVGA_REG_WIDTH: - ret = surface_width(surface); + ret = s->new_width ? s->new_width : surface_width(surface); break; case SVGA_REG_HEIGHT: - ret = surface_height(surface); + ret = s->new_height ? s->new_height : surface_height(surface); break; case SVGA_REG_MAX_WIDTH: @@ -749,11 +749,12 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) break; case SVGA_REG_DEPTH: - ret = s->depth; + ret = (s->new_depth == 32) ? 24 : s->new_depth; break; case SVGA_REG_BITS_PER_PIXEL: - ret = (s->depth + 7) & ~7; + case SVGA_REG_HOST_BITS_PER_PIXEL: + ret = s->new_depth; break; case SVGA_REG_PSEUDOCOLOR: @@ -761,19 +762,26 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) break; case SVGA_REG_RED_MASK: - ret = surface->pf.rmask; + pf = qemu_default_pixelformat(s->new_depth); + ret = pf.rmask; break; case SVGA_REG_GREEN_MASK: - ret = surface->pf.gmask; + pf = qemu_default_pixelformat(s->new_depth); + ret = pf.gmask; break; case SVGA_REG_BLUE_MASK: - ret = surface->pf.bmask; + pf = qemu_default_pixelformat(s->new_depth); + ret = pf.bmask; break; case SVGA_REG_BYTES_PER_LINE: - ret = s->bypp * s->new_width; + if (s->new_width) { + ret = (s->new_depth * s->new_width) / 8; + } else { + ret = surface_stride(surface); + } break; case SVGA_REG_FB_START: { @@ -852,10 +860,6 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) ret = s->cursor.on; break; - case SVGA_REG_HOST_BITS_PER_PIXEL: - ret = (s->depth + 7) & ~7; - break; - case SVGA_REG_SCRATCH_SIZE: ret = s->scratch_size; break; @@ -936,9 +940,10 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) break; case SVGA_REG_BITS_PER_PIXEL: - if (value != s->depth) { + if (value != 32) { printf("%s: Bad bits per pixel: %i bits\n", __func__, value); s->config = 0; + s->invalidated = 1; } break; @@ -1034,8 +1039,14 @@ static inline void vmsvga_check_size(struct vmsvga_state_s *s) DisplaySurface *surface = qemu_console_surface(s->vga.con); if (s->new_width != surface_width(surface) || - s->new_height != surface_height(surface)) { - qemu_console_resize(s->vga.con, s->new_width, s->new_height); + s->new_height != surface_height(surface) || + s->new_depth != surface_bits_per_pixel(surface)) { + int stride = (s->new_depth * s->new_width) / 8; + trace_vmware_setmode(s->new_width, s->new_height, s->new_depth); + surface = qemu_create_displaysurface_from(s->new_width, s->new_height, + s->new_depth, stride, + s->vga.vram_ptr, false); + dpy_gfx_replace_surface(s->vga.con, surface); s->invalidated = 1; } } @@ -1069,8 +1080,6 @@ static void vmsvga_update_display(void *opaque) } if (s->invalidated || dirty) { s->invalidated = 0; - memcpy(surface_data(surface), s->vga.vram_ptr, - surface_stride(surface) * surface_height(surface)); dpy_gfx_update(s->vga.con, 0, 0, surface_width(surface), surface_height(surface)); } @@ -1162,7 +1171,7 @@ static const VMStateDescription vmstate_vmware_vga_internal = { .minimum_version_id_old = 0, .post_load = vmsvga_post_load, .fields = (VMStateField[]) { - VMSTATE_INT32_EQUAL(depth, struct vmsvga_state_s), + VMSTATE_INT32_EQUAL(new_depth, struct vmsvga_state_s), VMSTATE_INT32(enable, struct vmsvga_state_s), VMSTATE_INT32(config, struct vmsvga_state_s), VMSTATE_INT32(cursor.id, struct vmsvga_state_s), @@ -1198,8 +1207,6 @@ static const VMStateDescription vmstate_vmware_vga = { static void vmsvga_init(struct vmsvga_state_s *s, MemoryRegion *address_space, MemoryRegion *io) { - DisplaySurface *surface; - s->scratch_size = SVGA_SCRATCH_SIZE; s->scratch = g_malloc(s->scratch_size * 4); @@ -1207,7 +1214,6 @@ static void vmsvga_init(struct vmsvga_state_s *s, vmsvga_invalidate_display, vmsvga_screen_dump, vmsvga_text_update, s); - surface = qemu_console_surface(s->vga.con); s->fifo_size = SVGA_FIFO_SIZE; memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size); @@ -1217,10 +1223,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, vga_common_init(&s->vga); vga_init(&s->vga, address_space, io, true); vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga); - /* Save some values here in case they are changed later. - * This is suspicious and needs more though why it is needed. */ - s->depth = surface_bits_per_pixel(surface); - s->bypp = surface_bytes_per_pixel(surface); + s->new_depth = 32; } static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, unsigned size) diff --git a/trace-events b/trace-events index 6c795dc7ff..b4d69d657c 100644 --- a/trace-events +++ b/trace-events @@ -976,6 +976,7 @@ vmware_palette_read(uint32_t index, uint32_t value) "index %d, value 0x%x" vmware_palette_write(uint32_t index, uint32_t value) "index %d, value 0x%x" vmware_scratch_read(uint32_t index, uint32_t value) "index %d, value 0x%x" vmware_scratch_write(uint32_t index, uint32_t value) "index %d, value 0x%x" +vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) "%dx%d @ %d bpp" # savevm.c -- cgit v1.2.3 From 867c538f988d326f6b447acde867e5de5a5014a0 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 6 Mar 2013 14:14:17 +0100 Subject: pixman: add qemu_pixman_color() Helper function to map qemu colors (32bit integer + matching PixelFormat) into pixman_color_t. Signed-off-by: Gerd Hoffmann --- include/ui/qemu-pixman.h | 2 ++ ui/qemu-pixman.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h index b032f529aa..b0f09b587f 100644 --- a/include/ui/qemu-pixman.h +++ b/include/ui/qemu-pixman.h @@ -43,4 +43,6 @@ pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format, pixman_image_t *image); void qemu_pixman_image_unref(pixman_image_t *image); +pixman_color_t qemu_pixman_color(PixelFormat *pf, uint32_t color); + #endif /* QEMU_PIXMAN_H */ diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c index 6dcbe90546..be551e09ed 100644 --- a/ui/qemu-pixman.c +++ b/ui/qemu-pixman.c @@ -79,3 +79,14 @@ void qemu_pixman_image_unref(pixman_image_t *image) } pixman_image_unref(image); } + +pixman_color_t qemu_pixman_color(PixelFormat *pf, uint32_t color) +{ + pixman_color_t c; + + c.red = ((color & pf->rmask) >> pf->rshift) << (16 - pf->rbits); + c.green = ((color & pf->gmask) >> pf->gshift) << (16 - pf->gbits); + c.blue = ((color & pf->bmask) >> pf->bshift) << (16 - pf->bbits); + c.alpha = ((color & pf->amask) >> pf->ashift) << (16 - pf->abits); + return c; +} -- cgit v1.2.3 From b762795257353760e8c69e144188ef7ab2b84c37 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 7 Mar 2013 15:23:48 +0100 Subject: pixman: render vgafont glyphs into pixman images Add helper functions to create pixman mask images for glyphs and to render these glyphs into a pixman image. Signed-off-by: Gerd Hoffmann --- include/ui/qemu-pixman.h | 7 +++++++ ui/qemu-pixman.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h index b0f09b587f..f012ec5fc3 100644 --- a/include/ui/qemu-pixman.h +++ b/include/ui/qemu-pixman.h @@ -44,5 +44,12 @@ pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format, void qemu_pixman_image_unref(pixman_image_t *image); pixman_color_t qemu_pixman_color(PixelFormat *pf, uint32_t color); +pixman_image_t *qemu_pixman_glyph_from_vgafont(int height, const uint8_t *font, + unsigned int ch); +void qemu_pixman_glyph_render(pixman_image_t *glyph, + pixman_image_t *surface, + pixman_color_t *fgcol, + pixman_color_t *bgcol, + int x, int y, int cw, int ch); #endif /* QEMU_PIXMAN_H */ diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c index be551e09ed..254bd8ce10 100644 --- a/ui/qemu-pixman.c +++ b/ui/qemu-pixman.c @@ -90,3 +90,46 @@ pixman_color_t qemu_pixman_color(PixelFormat *pf, uint32_t color) c.alpha = ((color & pf->amask) >> pf->ashift) << (16 - pf->abits); return c; } + +pixman_image_t *qemu_pixman_glyph_from_vgafont(int height, const uint8_t *font, + unsigned int ch) +{ + pixman_image_t *glyph; + uint8_t *data; + bool bit; + int x, y; + + glyph = pixman_image_create_bits(PIXMAN_a8, 8, height, + NULL, 0); + data = (uint8_t *)pixman_image_get_data(glyph); + + font += height * ch; + for (y = 0; y < height; y++, font++) { + for (x = 0; x < 8; x++, data++) { + bit = (*font) & (1 << (7-x)); + *data = bit ? 0xff : 0x00; + } + } + return glyph; +} + +void qemu_pixman_glyph_render(pixman_image_t *glyph, + pixman_image_t *surface, + pixman_color_t *fgcol, + pixman_color_t *bgcol, + int x, int y, int cw, int ch) +{ + pixman_image_t *ifg = pixman_image_create_solid_fill(fgcol); + pixman_image_t *ibg = pixman_image_create_solid_fill(bgcol); + + pixman_image_composite(PIXMAN_OP_SRC, ibg, NULL, surface, + 0, 0, 0, 0, + cw * x, ch * y, + cw, ch); + pixman_image_composite(PIXMAN_OP_OVER, ifg, glyph, surface, + 0, 0, 0, 0, + cw * x, ch * y, + cw, ch); + pixman_image_unref(ifg); + pixman_image_unref(ibg); +} -- cgit v1.2.3 From 68db6dc5310df9bb0d8d4ed8f5138b0c5c6415be Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 6 Mar 2013 15:43:23 +0100 Subject: console: use pixman for fill+blit Zap homegrown pixel shuffeling code, use pixman calls instead. Signed-off-by: Gerd Hoffmann --- ui/console.c | 65 ++++++++++-------------------------------------------------- 1 file changed, 10 insertions(+), 55 deletions(-) diff --git a/ui/console.c b/ui/console.c index 0ed4211986..be7f4f1a25 100644 --- a/ui/console.c +++ b/ui/console.c @@ -213,36 +213,14 @@ static void vga_fill_rect(QemuConsole *con, uint32_t color) { DisplaySurface *surface = qemu_console_surface(con); - uint8_t *d, *d1; - int x, y, bpp; + pixman_rectangle16_t rect = { + .x = posx, .y = posy, .width = width, .height = height + }; + pixman_color_t pcolor; - bpp = surface_bytes_per_pixel(surface); - d1 = surface_data(surface) + - surface_stride(surface) * posy + bpp * posx; - for (y = 0; y < height; y++) { - d = d1; - switch(bpp) { - case 1: - for (x = 0; x < width; x++) { - *((uint8_t *)d) = color; - d++; - } - break; - case 2: - for (x = 0; x < width; x++) { - *((uint16_t *)d) = color; - d += 2; - } - break; - case 4: - for (x = 0; x < width; x++) { - *((uint32_t *)d) = color; - d += 4; - } - break; - } - d1 += surface_stride(surface); - } + pcolor = qemu_pixman_color(&surface->pf, color); + pixman_image_fill_rectangles(PIXMAN_OP_SRC, surface->image, + &pcolor, 1, &rect); } /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */ @@ -250,33 +228,10 @@ static void vga_bitblt(QemuConsole *con, int xs, int ys, int xd, int yd, int w, int h) { DisplaySurface *surface = qemu_console_surface(con); - const uint8_t *s; - uint8_t *d; - int wb, y, bpp; - bpp = surface_bytes_per_pixel(surface); - wb = w * bpp; - if (yd <= ys) { - s = surface_data(surface) + - surface_stride(surface) * ys + bpp * xs; - d = surface_data(surface) + - surface_stride(surface) * yd + bpp * xd; - for (y = 0; y < h; y++) { - memmove(d, s, wb); - d += surface_stride(surface); - s += surface_stride(surface); - } - } else { - s = surface_data(surface) + - surface_stride(surface) * (ys + h - 1) + bpp * xs; - d = surface_data(surface) + - surface_stride(surface) * (yd + h - 1) + bpp * xd; - for (y = 0; y < h; y++) { - memmove(d, s, wb); - d -= surface_stride(surface); - s -= surface_stride(surface); - } - } + pixman_image_composite(PIXMAN_OP_SRC, + surface->image, NULL, surface->image, + xs, ys, 0, 0, xd, yd, w, h); } /***********************************************************/ -- cgit v1.2.3 From 7d6ba01c3741bc32ae252bf64a5fd3f930c2df4f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 6 Mar 2013 15:44:10 +0100 Subject: console: use pixman for font rendering Zap homegrown font rendering code, use pixman calls instead. Signed-off-by: Gerd Hoffmann --- ui/console.c | 110 ++++++----------------------------------------------------- 1 file changed, 11 insertions(+), 99 deletions(-) diff --git a/ui/console.c b/ui/console.c index be7f4f1a25..584f069c58 100644 --- a/ui/console.c +++ b/ui/console.c @@ -242,45 +242,6 @@ static void vga_bitblt(QemuConsole *con, #include "vgafont.h" -#define cbswap_32(__x) \ -((uint32_t)( \ - (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ - (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ - (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ - (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )) - -#ifdef HOST_WORDS_BIGENDIAN -#define PAT(x) x -#else -#define PAT(x) cbswap_32(x) -#endif - -static const uint32_t dmask16[16] = { - PAT(0x00000000), - PAT(0x000000ff), - PAT(0x0000ff00), - PAT(0x0000ffff), - PAT(0x00ff0000), - PAT(0x00ff00ff), - PAT(0x00ffff00), - PAT(0x00ffffff), - PAT(0xff000000), - PAT(0xff0000ff), - PAT(0xff00ff00), - PAT(0xff00ffff), - PAT(0xffff0000), - PAT(0xffff00ff), - PAT(0xffffff00), - PAT(0xffffffff), -}; - -static const uint32_t dmask4[4] = { - PAT(0x00000000), - PAT(0x0000ffff), - PAT(0xffff0000), - PAT(0xffffffff), -}; - #ifndef CONFIG_CURSES enum color_names { COLOR_BLACK = 0, @@ -353,17 +314,11 @@ static void console_print_text_attributes(TextAttributes *t_attrib, char ch) static void vga_putcharxy(QemuConsole *s, int x, int y, int ch, TextAttributes *t_attrib) { + static pixman_image_t *glyphs[256]; DisplaySurface *surface = qemu_console_surface(s); - uint8_t *d; - const uint8_t *font_ptr; - unsigned int font_data, linesize, xorcol, bpp; - int i; unsigned int fgcol, bgcol; - -#ifdef DEBUG_CONSOLE - printf("x: %2i y: %2i", x, y); - console_print_text_attributes(t_attrib, ch); -#endif + pixman_image_t *ifg, *ibg; + pixman_color_t cfg, cbg; if (t_attrib->invers) { bgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol]; @@ -372,59 +327,16 @@ static void vga_putcharxy(QemuConsole *s, int x, int y, int ch, fgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol]; bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol]; } + cfg = qemu_pixman_color(&surface->pf, fgcol); + cbg = qemu_pixman_color(&surface->pf, bgcol); + ifg = pixman_image_create_solid_fill(&cfg); + ibg = pixman_image_create_solid_fill(&cbg); - bpp = surface_bytes_per_pixel(surface); - d = surface_data(surface) + - surface_stride(surface) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH; - linesize = surface_stride(surface); - font_ptr = vgafont16 + FONT_HEIGHT * ch; - xorcol = bgcol ^ fgcol; - switch (surface_bits_per_pixel(surface)) { - case 8: - for(i = 0; i < FONT_HEIGHT; i++) { - font_data = *font_ptr++; - if (t_attrib->uline - && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) { - font_data = 0xFF; - } - ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol; - ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; - d += linesize; - } - break; - case 16: - case 15: - for(i = 0; i < FONT_HEIGHT; i++) { - font_data = *font_ptr++; - if (t_attrib->uline - && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) { - font_data = 0xFF; - } - ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol; - ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol; - ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol; - ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; - d += linesize; - } - break; - case 32: - for(i = 0; i < FONT_HEIGHT; i++) { - font_data = *font_ptr++; - if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) { - font_data = 0xFF; - } - ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; - ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; - ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; - d += linesize; - } - break; + if (!glyphs[ch]) { + glyphs[ch] = qemu_pixman_glyph_from_vgafont(FONT_HEIGHT, vgafont16, ch); } + qemu_pixman_glyph_render(glyphs[ch], surface->image, + &cfg, &cbg, x, y, FONT_WIDTH, FONT_HEIGHT); } static void text_console_resize(QemuConsole *s) -- cgit v1.2.3 From e27bd65a72dece59e93914d3ffa8653ce0c70511 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 8 Mar 2013 08:43:24 +0100 Subject: console: switch color_table_rgb to pixman_color_t Now that all text console rendering uses pixman we can easily switch the color tables to use pixman_color_t directly. Signed-off-by: Gerd Hoffmann --- ui/console.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/ui/console.c b/ui/console.c index 584f069c58..1935996c26 100644 --- a/ui/console.c +++ b/ui/console.c @@ -32,9 +32,6 @@ #define MAX_CONSOLES 12 #define CONSOLE_CURSOR_PERIOD 500 -#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) -#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff) - typedef struct TextAttributes { uint8_t fgcol:4; uint8_t bgcol:4; @@ -210,17 +207,15 @@ void vga_hw_text_update(console_ch_t *chardata) static void vga_fill_rect(QemuConsole *con, int posx, int posy, int width, int height, - uint32_t color) + pixman_color_t color) { DisplaySurface *surface = qemu_console_surface(con); pixman_rectangle16_t rect = { .x = posx, .y = posy, .width = width, .height = height }; - pixman_color_t pcolor; - pcolor = qemu_pixman_color(&surface->pf, color); pixman_image_fill_rectangles(PIXMAN_OP_SRC, surface->image, - &pcolor, 1, &rect); + &color, 1, &rect); } /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */ @@ -255,7 +250,10 @@ enum color_names { }; #endif -static const uint32_t color_table_rgb[2][8] = { +#define QEMU_RGB(r, g, b) \ + { .red = r << 8, .green = g << 8, .blue = b << 8, .alpha = 0xffff } + +static const pixman_color_t color_table_rgb[2][8] = { { /* dark */ QEMU_RGB(0x00, 0x00, 0x00), /* black */ QEMU_RGB(0xaa, 0x00, 0x00), /* red */ @@ -316,9 +314,7 @@ static void vga_putcharxy(QemuConsole *s, int x, int y, int ch, { static pixman_image_t *glyphs[256]; DisplaySurface *surface = qemu_console_surface(s); - unsigned int fgcol, bgcol; - pixman_image_t *ifg, *ibg; - pixman_color_t cfg, cbg; + pixman_color_t fgcol, bgcol; if (t_attrib->invers) { bgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol]; @@ -327,16 +323,12 @@ static void vga_putcharxy(QemuConsole *s, int x, int y, int ch, fgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol]; bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol]; } - cfg = qemu_pixman_color(&surface->pf, fgcol); - cbg = qemu_pixman_color(&surface->pf, bgcol); - ifg = pixman_image_create_solid_fill(&cfg); - ibg = pixman_image_create_solid_fill(&cbg); if (!glyphs[ch]) { glyphs[ch] = qemu_pixman_glyph_from_vgafont(FONT_HEIGHT, vgafont16, ch); } qemu_pixman_glyph_render(glyphs[ch], surface->image, - &cfg, &cbg, x, y, FONT_WIDTH, FONT_HEIGHT); + &fgcol, &bgcol, x, y, FONT_WIDTH, FONT_HEIGHT); } static void text_console_resize(QemuConsole *s) -- cgit v1.2.3 From 437fe1061be3da49b0b05ed2f0c9c50e2255c3fe Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 7 Mar 2013 16:04:52 +0100 Subject: console: add trace events Signed-off-by: Gerd Hoffmann --- trace-events | 3 +++ ui/console.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/trace-events b/trace-events index b4d69d657c..b08627b192 100644 --- a/trace-events +++ b/trace-events @@ -962,6 +962,9 @@ dma_bdrv_cb(void *dbs, int ret) "dbs=%p ret=%d" dma_map_wait(void *dbs) "dbs=%p" # console.h +console_gfx_new(void) "" +console_txt_new(int w, int h) "%dx%d" +console_select(int nr) "%d" displaysurface_create(void *display_surface, int w, int h) "surface=%p, %dx%d" displaysurface_create_from(void *display_surface, int w, int h, int bpp, int swap) "surface=%p, %dx%d, bpp %d, bswap %d" displaysurface_free(void *display_surface) "surface=%p" diff --git a/ui/console.c b/ui/console.c index 1935996c26..3834e39f34 100644 --- a/ui/console.c +++ b/ui/console.c @@ -904,6 +904,8 @@ void console_select(unsigned int index) if (index >= MAX_CONSOLES) return; + + trace_console_select(index); if (active_console) { surface = qemu_console_surface(active_console); active_console->g_width = surface_width(surface); @@ -1367,6 +1369,7 @@ QemuConsole *graphic_console_init(vga_hw_update_ptr update, DisplayState *ds; ds = (DisplayState *) g_malloc0(sizeof(DisplayState)); + trace_console_gfx_new(); s = new_console(ds, GRAPHIC_CONSOLE); s->hw_update = update; s->hw_invalidate = invalidate; @@ -1485,6 +1488,7 @@ static CharDriverState *text_console_init(ChardevVC *vc) height = vc->rows * FONT_HEIGHT; } + trace_console_txt_new(width, height); if (width == 0 || height == 0) { s = new_console(NULL, TEXT_CONSOLE); } else { -- cgit v1.2.3 From 64840c66b702cc4c809c72d8ad5d26861dd7fd8d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 7 Mar 2013 17:08:29 +0100 Subject: console: displaystate init revamp We have only one DisplayState, so there is no need for the "next" linking, rip it. Also consolidate all displaystate initialization into init_displaystate(). This function is called by vl.c after creating the devices (and thus all QemuConsoles) and before initializing DisplayChangeListensers (aka gtk/sdl/vnc/spice ui). Signed-off-by: Gerd Hoffmann --- include/ui/console.h | 5 +--- ui/console.c | 73 ++++++++++++++++++++++++---------------------------- vl.c | 6 +---- 3 files changed, 36 insertions(+), 48 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index a234c72d2e..3725daef5d 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -189,12 +189,9 @@ struct DisplayState { bool have_text; QLIST_HEAD(, DisplayChangeListener) listeners; - - struct DisplayState *next; }; -void register_displaystate(DisplayState *ds); -DisplayState *get_displaystate(void); +DisplayState *init_displaystate(void); DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, int linesize, uint8_t *data, bool byteswap); diff --git a/ui/console.c b/ui/console.c index 3834e39f34..e100593ffd 100644 --- a/ui/console.c +++ b/ui/console.c @@ -163,6 +163,8 @@ static QemuConsole *active_console; static QemuConsole *consoles[MAX_CONSOLES]; static int nb_consoles = 0; +static void text_console_do_init(CharDriverState *chr, DisplayState *ds); + void vga_hw_update(void) { if (active_console && active_console->hw_update) @@ -1323,39 +1325,37 @@ bool dpy_cursor_define_supported(QemuConsole *con) return false; } -static void dumb_display_init(void) -{ - DisplayState *ds = g_malloc0(sizeof(DisplayState)); - int width = 640; - int height = 480; - - if (is_fixedsize_console()) { - width = active_console->g_width; - height = active_console->g_height; - } - ds->surface = qemu_create_displaysurface(width, height); - - register_displaystate(ds); -} - /***********************************************************/ /* register display */ -void register_displaystate(DisplayState *ds) +/* console.c internal use only */ +static DisplayState *get_alloc_displaystate(void) { - DisplayState **s; - s = &display_state; - while (*s != NULL) - s = &(*s)->next; - ds->next = NULL; - *s = ds; + if (!display_state) { + display_state = g_new0(DisplayState, 1); + } + return display_state; } -DisplayState *get_displaystate(void) +/* + * Called by main(), after creating QemuConsoles + * and before initializing ui (sdl/vnc/...). + */ +DisplayState *init_displaystate(void) { + int i; + if (!display_state) { - dumb_display_init (); + display_state = g_new0(DisplayState, 1); } + + for (i = 0; i < nb_consoles; i++) { + if (consoles[i]->console_type != GRAPHIC_CONSOLE && + consoles[i]->ds == NULL) { + text_console_do_init(consoles[i]->chr, display_state); + } + } + return display_state; } @@ -1365,10 +1365,12 @@ QemuConsole *graphic_console_init(vga_hw_update_ptr update, vga_hw_text_update_ptr text_update, void *opaque) { + int width = 640; + int height = 480; QemuConsole *s; DisplayState *ds; - ds = (DisplayState *) g_malloc0(sizeof(DisplayState)); + ds = get_alloc_displaystate(); trace_console_gfx_new(); s = new_console(ds, GRAPHIC_CONSOLE); s->hw_update = update; @@ -1377,9 +1379,9 @@ QemuConsole *graphic_console_init(vga_hw_update_ptr update, s->hw_text_update = text_update; s->hw = opaque; - ds->surface = qemu_create_displaysurface(640, 480); - - register_displaystate(ds); + if (!ds->surface) { + ds->surface = qemu_create_displaysurface(width, height); + } return s; } @@ -1505,6 +1507,10 @@ static CharDriverState *text_console_init(ChardevVC *vc) s->g_height = height; chr->opaque = s; chr->chr_set_echo = text_console_set_echo; + + if (display_state) { + text_console_do_init(chr, display_state); + } return chr; } @@ -1520,17 +1526,6 @@ void register_vc_handler(VcHandler *handler) vc_handler = handler; } -void text_consoles_set_display(DisplayState *ds) -{ - int i; - - for (i = 0; i < nb_consoles; i++) { - if (consoles[i]->console_type != GRAPHIC_CONSOLE) { - text_console_do_init(consoles[i]->chr, ds); - } - } -} - void qemu_console_resize(QemuConsole *s, int width, int height) { s->g_width = width; diff --git a/vl.c b/vl.c index 05989986f3..63fe9a44a8 100644 --- a/vl.c +++ b/vl.c @@ -4331,8 +4331,7 @@ int main(int argc, char **argv, char **envp) net_check_clients(); - /* just use the first displaystate for the moment */ - ds = get_displaystate(); + ds = init_displaystate(); /* init local displays */ switch (display_type) { @@ -4388,9 +4387,6 @@ int main(int argc, char **argv, char **envp) } #endif - /* display setup */ - text_consoles_set_display(ds); - if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { exit(1); } -- cgit v1.2.3 From 1dbfa005032d4fa5d7a5242da856d3487c907431 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 12 Mar 2013 13:44:38 +0100 Subject: console: rename vga_hw_*, add QemuConsole param Add QemuConsole parameter to vga_hw_*, so the interface allows to update non-active consoles (the actual code can't handle this yet, see next patch). Passing NULL is allowed and updates the active console, like the functions do today. While touching all vga_hw_* calls anyway rename that to the functions to hardware-neutral graphics_hw_* Signed-off-by: Gerd Hoffmann --- hw/display/cirrus_vga.c | 2 +- hw/display/qxl.c | 2 +- hw/display/vga.c | 2 +- hw/display/vga_int.h | 8 ++++---- include/ui/console.h | 22 +++++++++++----------- ui/console.c | 49 ++++++++++++++++++++++++++++++------------------- ui/curses.c | 4 ++-- ui/gtk.c | 2 +- ui/sdl.c | 18 +++++++++--------- ui/spice-display.c | 2 +- ui/vnc.c | 12 ++++++------ 11 files changed, 67 insertions(+), 56 deletions(-) diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index bf2181afd8..514bc33caa 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -720,7 +720,7 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) /* we have to flush all pending changes so that the copy is generated at the appropriate moment in time */ if (notify) - vga_hw_update(); + graphic_hw_update(s->vga.con); (*s->cirrus_rop) (s, s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 930b7cf2ad..247209d6d2 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1074,7 +1074,7 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d) qemu_spice_create_host_primary(&d->ssd); d->mode = QXL_MODE_VGA; vga_dirty_log_start(&d->vga); - vga_hw_update(); + graphic_hw_update(d->vga.con); } static void qxl_exit_vga_mode(PCIQXLDevice *d) diff --git a/hw/display/vga.c b/hw/display/vga.c index c1b67bbbf8..e37e8984bc 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -2452,6 +2452,6 @@ static void vga_screen_dump(void *opaque, const char *filename, bool cswitch, if (cswitch) { vga_invalidate_display(s); } - vga_hw_update(); + graphic_hw_update(s->con); ppm_save(filename, surface, errp); } diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index 260f7d6948..1b8f670868 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -152,10 +152,10 @@ typedef struct VGACommonState { uint32_t cursor_offset; unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b); - vga_hw_update_ptr update; - vga_hw_invalidate_ptr invalidate; - vga_hw_screen_dump_ptr screen_dump; - vga_hw_text_update_ptr text_update; + graphic_hw_update_ptr update; + graphic_hw_invalidate_ptr invalidate; + graphic_hw_screen_dump_ptr screen_dump; + graphic_hw_text_update_ptr text_update; bool full_update_text; bool full_update_gfx; /* hardware mouse cursor support */ diff --git a/include/ui/console.h b/include/ui/console.h index 3725daef5d..9c585c0d49 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -278,21 +278,21 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch) *dest = ch; } -typedef void (*vga_hw_update_ptr)(void *); -typedef void (*vga_hw_invalidate_ptr)(void *); -typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch, +typedef void (*graphic_hw_update_ptr)(void *); +typedef void (*graphic_hw_invalidate_ptr)(void *); +typedef void (*graphic_hw_screen_dump_ptr)(void *, const char *, bool cswitch, Error **errp); -typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *); +typedef void (*graphic_hw_text_update_ptr)(void *, console_ch_t *); -QemuConsole *graphic_console_init(vga_hw_update_ptr update, - vga_hw_invalidate_ptr invalidate, - vga_hw_screen_dump_ptr screen_dump, - vga_hw_text_update_ptr text_update, +QemuConsole *graphic_console_init(graphic_hw_update_ptr update, + graphic_hw_invalidate_ptr invalidate, + graphic_hw_screen_dump_ptr screen_dump, + graphic_hw_text_update_ptr text_update, void *opaque); -void vga_hw_update(void); -void vga_hw_invalidate(void); -void vga_hw_text_update(console_ch_t *chardata); +void graphic_hw_update(QemuConsole *con); +void graphic_hw_invalidate(QemuConsole *con); +void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata); int is_graphic_console(void); int is_fixedsize_console(void); diff --git a/ui/console.c b/ui/console.c index e100593ffd..dccc61850b 100644 --- a/ui/console.c +++ b/ui/console.c @@ -118,10 +118,10 @@ struct QemuConsole { DisplayState *ds; /* Graphic console state. */ - vga_hw_update_ptr hw_update; - vga_hw_invalidate_ptr hw_invalidate; - vga_hw_screen_dump_ptr hw_screen_dump; - vga_hw_text_update_ptr hw_text_update; + graphic_hw_update_ptr hw_update; + graphic_hw_invalidate_ptr hw_invalidate; + graphic_hw_screen_dump_ptr hw_screen_dump; + graphic_hw_text_update_ptr hw_text_update; void *hw; int g_width, g_height; @@ -165,16 +165,24 @@ static int nb_consoles = 0; static void text_console_do_init(CharDriverState *chr, DisplayState *ds); -void vga_hw_update(void) +void graphic_hw_update(QemuConsole *con) { - if (active_console && active_console->hw_update) - active_console->hw_update(active_console->hw); + if (!con) { + con = active_console; + } + if (con && con->hw_update) { + con->hw_update(con->hw); + } } -void vga_hw_invalidate(void) +void graphic_hw_invalidate(QemuConsole *con) { - if (active_console && active_console->hw_invalidate) - active_console->hw_invalidate(active_console->hw); + if (!con) { + con = active_console; + } + if (con && con->hw_invalidate) { + con->hw_invalidate(con->hw); + } } void qmp_screendump(const char *filename, Error **errp) @@ -201,10 +209,13 @@ void qmp_screendump(const char *filename, Error **errp) } } -void vga_hw_text_update(console_ch_t *chardata) +void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata) { - if (active_console && active_console->hw_text_update) - active_console->hw_text_update(active_console->hw, chardata); + if (!con) { + con = active_console; + } + if (con && con->hw_text_update) + con->hw_text_update(con->hw, chardata); } static void vga_fill_rect(QemuConsole *con, @@ -932,7 +943,7 @@ void console_select(unsigned int index) qemu_mod_timer(s->cursor_timer, qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2); } - vga_hw_invalidate(); + graphic_hw_invalidate(s); } } @@ -1359,10 +1370,10 @@ DisplayState *init_displaystate(void) return display_state; } -QemuConsole *graphic_console_init(vga_hw_update_ptr update, - vga_hw_invalidate_ptr invalidate, - vga_hw_screen_dump_ptr screen_dump, - vga_hw_text_update_ptr text_update, +QemuConsole *graphic_console_init(graphic_hw_update_ptr update, + graphic_hw_invalidate_ptr invalidate, + graphic_hw_screen_dump_ptr screen_dump, + graphic_hw_text_update_ptr text_update, void *opaque) { int width = 640; @@ -1407,7 +1418,7 @@ static void text_console_update_cursor(void *opaque) QemuConsole *s = opaque; s->cursor_visible_phase = !s->cursor_visible_phase; - vga_hw_invalidate(); + graphic_hw_invalidate(s); qemu_mod_timer(s->cursor_timer, qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2); } diff --git a/ui/curses.c b/ui/curses.c index ff82307361..ed9e65c7f0 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -166,11 +166,11 @@ static void curses_refresh(DisplayChangeListener *dcl) clear(); refresh(); curses_calc_pad(); - vga_hw_invalidate(); + graphic_hw_invalidate(NULL); invalidate = 0; } - vga_hw_text_update(screen); + graphic_hw_text_update(NULL, screen); nextchr = ERR; while (1) { diff --git a/ui/gtk.c b/ui/gtk.c index 1e105e2fc7..d0e444cece 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -327,7 +327,7 @@ static void gd_update(DisplayChangeListener *dcl, static void gd_refresh(DisplayChangeListener *dcl) { - vga_hw_update(); + graphic_hw_update(NULL); } static void gd_switch(DisplayChangeListener *dcl, diff --git a/ui/sdl.c b/ui/sdl.c index 8da05341bb..ede31dc794 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -492,8 +492,8 @@ static void toggle_full_screen(void) sdl_grab_end(); } } - vga_hw_invalidate(); - vga_hw_update(); + graphic_hw_invalidate(NULL); + graphic_hw_update(NULL); } static void handle_keydown(SDL_Event *ev) @@ -522,8 +522,8 @@ static void handle_keydown(SDL_Event *ev) if (scaling_active) { scaling_active = 0; sdl_switch(dcl, NULL); - vga_hw_invalidate(); - vga_hw_update(); + graphic_hw_invalidate(NULL); + graphic_hw_update(NULL); } gui_keysym = 1; break; @@ -556,8 +556,8 @@ static void handle_keydown(SDL_Event *ev) surface_width(surface); sdl_scale(width, height); - vga_hw_invalidate(); - vga_hw_update(); + graphic_hw_invalidate(NULL); + graphic_hw_update(NULL); gui_keysym = 1; } default: @@ -770,7 +770,7 @@ static void sdl_refresh(DisplayChangeListener *dcl) sdl_update_caption(); } - vga_hw_update(); + graphic_hw_update(NULL); SDL_EnableUNICODE(!is_graphic_console()); while (SDL_PollEvent(ev)) { @@ -802,8 +802,8 @@ static void sdl_refresh(DisplayChangeListener *dcl) break; case SDL_VIDEORESIZE: sdl_scale(ev->resize.w, ev->resize.h); - vga_hw_invalidate(); - vga_hw_update(); + graphic_hw_invalidate(NULL); + graphic_hw_update(NULL); break; default: break; diff --git a/ui/spice-display.c b/ui/spice-display.c index eaab19d9bd..2c0167488b 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -414,7 +414,7 @@ void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd) void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) { dprint(3, "%s:\n", __func__); - vga_hw_update(); + graphic_hw_update(ssd->con); qemu_mutex_lock(&ssd->lock); if (QTAILQ_EMPTY(&ssd->updates) && ssd->ds) { diff --git a/ui/vnc.c b/ui/vnc.c index 5ddb696625..bc787ccb77 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1956,8 +1956,8 @@ static void set_pixel_format(VncState *vs, set_pixel_conversion(vs); - vga_hw_invalidate(); - vga_hw_update(); + graphic_hw_invalidate(NULL); + graphic_hw_update(NULL); } static void pixel_format_message (VncState *vs) { @@ -2653,7 +2653,7 @@ static void vnc_refresh(void *opaque) VncState *vs, *vn; int has_dirty, rects = 0; - vga_hw_update(); + graphic_hw_update(NULL); if (vnc_trylock_display(vd)) { vd->timer_interval = VNC_REFRESH_INTERVAL_BASE; @@ -2692,7 +2692,7 @@ static void vnc_init_timer(VncDisplay *vd) vd->timer_interval = VNC_REFRESH_INTERVAL_BASE; if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) { vd->timer = qemu_new_timer_ms(rt_clock, vnc_refresh, vd); - vga_hw_update(); + graphic_hw_update(NULL); vnc_refresh(vd); } } @@ -2775,7 +2775,7 @@ void vnc_init_state(VncState *vs) QTAILQ_INSERT_HEAD(&vd->clients, vs, next); - vga_hw_update(); + graphic_hw_update(NULL); vnc_write(vs, "RFB 003.008\n", 12); vnc_flush(vs); @@ -2800,7 +2800,7 @@ static void vnc_listen_read(void *opaque, bool websocket) int csock; /* Catch-up */ - vga_hw_update(); + graphic_hw_update(NULL); #ifdef CONFIG_VNC_WS if (websocket) { csock = qemu_accept(vs->lwebsock, (struct sockaddr *)&addr, &addrlen); -- cgit v1.2.3 From 321f048d248472f1e90559976bb917d869981c68 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 12 Mar 2013 14:39:22 +0100 Subject: console: give each QemuConsole its own DisplaySurface Go away from the global DisplaySurface, give one to each QemuConsole instead. With this patch applied it is possible to call graphics_hw_* functions with qemu consoles which are not the current foreground console. Signed-off-by: Gerd Hoffmann --- include/ui/console.h | 1 - ui/console.c | 96 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 69 insertions(+), 28 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 9c585c0d49..0dd66fd91f 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -183,7 +183,6 @@ struct DisplayChangeListener { }; struct DisplayState { - struct DisplaySurface *surface; struct QEMUTimer *gui_timer; bool have_gfx; bool have_text; diff --git a/ui/console.c b/ui/console.c index dccc61850b..e8e548e4c0 100644 --- a/ui/console.c +++ b/ui/console.c @@ -116,6 +116,7 @@ struct QemuConsole { int index; console_type_t console_type; DisplayState *ds; + DisplaySurface *surface; /* Graphic console state. */ graphic_hw_update_ptr hw_update; @@ -164,6 +165,8 @@ static QemuConsole *consoles[MAX_CONSOLES]; static int nb_consoles = 0; static void text_console_do_init(CharDriverState *chr, DisplayState *ds); +static void dpy_gfx_switch_surface(DisplayState *ds, + DisplaySurface *surface); void graphic_hw_update(QemuConsole *con) { @@ -933,8 +936,9 @@ void console_select(unsigned int index) } active_console = s; if (ds->have_gfx) { - surface = qemu_create_displaysurface(s->g_width, s->g_height); - dpy_gfx_replace_surface(s, surface); + dpy_gfx_switch_surface(ds, s->surface); + dpy_gfx_update(s, 0, 0, surface_width(s->surface), + surface_height(s->surface)); } if (ds->have_text) { dpy_text_resize(s, s->width, s->height); @@ -943,7 +947,6 @@ void console_select(unsigned int index) qemu_mod_timer(s->cursor_timer, qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2); } - graphic_hw_invalidate(s); } } @@ -1195,8 +1198,8 @@ void register_displaychangelistener(DisplayState *ds, dcl->ds = ds; QLIST_INSERT_HEAD(&ds->listeners, dcl, next); gui_setup_refresh(ds); - if (dcl->ops->dpy_gfx_switch) { - dcl->ops->dpy_gfx_switch(dcl, ds->surface); + if (dcl->ops->dpy_gfx_switch && active_console) { + dcl->ops->dpy_gfx_switch(dcl, active_console->surface); } } @@ -1212,8 +1215,8 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h) { DisplayState *s = con->ds; struct DisplayChangeListener *dcl; - int width = pixman_image_get_width(s->surface->image); - int height = pixman_image_get_height(s->surface->image); + int width = surface_width(con->surface); + int height = surface_height(con->surface); x = MAX(x, 0); y = MAX(y, 0); @@ -1222,6 +1225,9 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h) w = MIN(w, width - x); h = MIN(h, height - y); + if (con != active_console) { + return; + } QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_gfx_update) { dcl->ops->dpy_gfx_update(dcl, x, y, w, h); @@ -1229,19 +1235,28 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h) } } -void dpy_gfx_replace_surface(QemuConsole *con, - DisplaySurface *surface) +static void dpy_gfx_switch_surface(DisplayState *ds, + DisplaySurface *surface) { - DisplayState *s = con->ds; - DisplaySurface *old_surface = s->surface; struct DisplayChangeListener *dcl; - s->surface = surface; - QLIST_FOREACH(dcl, &s->listeners, next) { + QLIST_FOREACH(dcl, &ds->listeners, next) { if (dcl->ops->dpy_gfx_switch) { dcl->ops->dpy_gfx_switch(dcl, surface); } } +} + +void dpy_gfx_replace_surface(QemuConsole *con, + DisplaySurface *surface) +{ + DisplayState *s = con->ds; + DisplaySurface *old_surface = con->surface; + + con->surface = surface; + if (con == active_console) { + dpy_gfx_switch_surface(s, surface); + } qemu_free_displaysurface(old_surface); } @@ -1260,6 +1275,10 @@ void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y, { DisplayState *s = con->ds; struct DisplayChangeListener *dcl; + + if (con != active_console) { + return; + } QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_gfx_copy) { dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h); @@ -1273,6 +1292,10 @@ void dpy_text_cursor(QemuConsole *con, int x, int y) { DisplayState *s = con->ds; struct DisplayChangeListener *dcl; + + if (con != active_console) { + return; + } QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_text_cursor) { dcl->ops->dpy_text_cursor(dcl, x, y); @@ -1284,6 +1307,10 @@ void dpy_text_update(QemuConsole *con, int x, int y, int w, int h) { DisplayState *s = con->ds; struct DisplayChangeListener *dcl; + + if (con != active_console) { + return; + } QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_text_update) { dcl->ops->dpy_text_update(dcl, x, y, w, h); @@ -1295,6 +1322,10 @@ void dpy_text_resize(QemuConsole *con, int w, int h) { DisplayState *s = con->ds; struct DisplayChangeListener *dcl; + + if (con != active_console) { + return; + } QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_text_resize) { dcl->ops->dpy_text_resize(dcl, w, h); @@ -1306,6 +1337,10 @@ void dpy_mouse_set(QemuConsole *con, int x, int y, int on) { DisplayState *s = con->ds; struct DisplayChangeListener *dcl; + + if (con != active_console) { + return; + } QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_mouse_set) { dcl->ops->dpy_mouse_set(dcl, x, y, on); @@ -1317,6 +1352,10 @@ void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor) { DisplayState *s = con->ds; struct DisplayChangeListener *dcl; + + if (con != active_console) { + return; + } QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_cursor_define) { dcl->ops->dpy_cursor_define(dcl, cursor); @@ -1390,9 +1429,7 @@ QemuConsole *graphic_console_init(graphic_hw_update_ptr update, s->hw_text_update = text_update; s->hw = opaque; - if (!ds->surface) { - ds->surface = qemu_create_displaysurface(width, height); - } + s->surface = qemu_create_displaysurface(width, height); return s; } @@ -1442,9 +1479,15 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds) s->x = 0; s->y = 0; if (s->console_type == TEXT_CONSOLE) { - s->g_width = surface_width(s->ds->surface); - s->g_height = surface_height(s->ds->surface); + if (active_console && active_console->surface) { + s->g_width = surface_width(active_console->surface); + s->g_height = surface_height(active_console->surface); + } else { + s->g_width = 80 * FONT_WIDTH; + s->g_height = 24 * FONT_HEIGHT; + } } + s->surface = qemu_create_displaysurface(s->g_width, s->g_height); s->cursor_timer = qemu_new_timer_ms(rt_clock, text_console_update_cursor, s); @@ -1539,26 +1582,25 @@ void register_vc_handler(VcHandler *handler) void qemu_console_resize(QemuConsole *s, int width, int height) { + DisplaySurface *surface; + + assert(s->console_type == GRAPHIC_CONSOLE); s->g_width = width; s->g_height = height; - if (is_graphic_console()) { - DisplaySurface *surface; - surface = qemu_create_displaysurface(width, height); - dpy_gfx_replace_surface(s, surface); - } + surface = qemu_create_displaysurface(width, height); + dpy_gfx_replace_surface(s, surface); } void qemu_console_copy(QemuConsole *con, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { - if (is_graphic_console()) { - dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h); - } + assert(con->console_type == GRAPHIC_CONSOLE); + dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h); } DisplaySurface *qemu_console_surface(QemuConsole *console) { - return console->ds->surface; + return console->surface; } DisplayState *qemu_console_displaystate(QemuConsole *console) -- cgit v1.2.3 From 2c62f08ddbf3fa80dc7202eb9a2ea60ae44e2cc5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 12 Mar 2013 14:48:31 +0100 Subject: console: simplify screendump Screendumps are alot simpler as we can update non-active QemuConsoles now. So we only need to update the QemuConsole we want write out, then dump the DisplaySurface content into a ppm file. Done. No console switching needed. No special support code in the gfx card emulation needed. Zap it all. Also move ppm_save out of the vga code and next to the qmp_screendump function. For now screen dumping is limited to console #0 (like it used to be), even though it is dead simple to extend it to other consoles. I wanna finish the console cleanup before setting new qapi interfaces into stone. Signed-off-by: Gerd Hoffmann Tested-by: Igor Mitsyanko --- hw/arm/musicpal.c | 2 +- hw/display/blizzard.c | 14 +---- hw/display/cirrus_vga.c | 4 +- hw/display/exynos4210_fimd.c | 2 +- hw/display/g364fb.c | 73 +----------------------- hw/display/jazz_led.c | 1 - hw/display/milkymist-vgafb.c | 2 +- hw/display/omap_lcdc.c | 86 +---------------------------- hw/display/pl110.c | 2 +- hw/display/pxa2xx_lcd.c | 2 +- hw/display/qxl.c | 22 +------- hw/display/sm501.c | 2 +- hw/display/ssd0303.c | 2 +- hw/display/ssd0323.c | 2 +- hw/display/tc6393xb.c | 1 - hw/display/tcx.c | 129 +------------------------------------------ hw/display/vga-isa-mm.c | 2 +- hw/display/vga-isa.c | 2 +- hw/display/vga-pci.c | 2 +- hw/display/vga.c | 66 ---------------------- hw/display/vga_int.h | 2 - hw/display/vmware_vga.c | 26 --------- hw/display/xenfb.c | 1 - hw/unicore32/puv3.c | 2 +- include/ui/console.h | 3 - ui/console.c | 72 +++++++++++++++++------- 26 files changed, 73 insertions(+), 451 deletions(-) diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index d2247fa1b9..6e77447e45 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -612,7 +612,7 @@ static int musicpal_lcd_init(SysBusDevice *dev) sysbus_init_mmio(dev, &s->iomem); s->con = graphic_console_init(lcd_refresh, lcd_invalidate, - NULL, NULL, s); + NULL, s); qemu_console_resize(s->con, 128*3, 64*3); qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3); diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c index de7ccf87dc..70b68227fe 100644 --- a/hw/display/blizzard.c +++ b/hw/display/blizzard.c @@ -933,18 +933,6 @@ static void blizzard_update_display(void *opaque) s->my[1] = 0; } -static void blizzard_screen_dump(void *opaque, const char *filename, - bool cswitch, Error **errp) -{ - BlizzardState *s = (BlizzardState *) opaque; - DisplaySurface *surface = qemu_console_surface(s->con); - - blizzard_update_display(opaque); - if (s && surface_data(surface)) { - ppm_save(filename, surface, errp); - } -} - #define DEPTH 8 #include "blizzard_template.h" #define DEPTH 15 @@ -965,7 +953,7 @@ void *s1d13745_init(qemu_irq gpio_int) s->con = graphic_console_init(blizzard_update_display, blizzard_invalidate_display, - blizzard_screen_dump, NULL, s); + NULL, s); surface = qemu_console_surface(s->con); switch (surface_bits_per_pixel(surface)) { diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index 514bc33caa..c31b021eca 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -2911,7 +2911,7 @@ static int vga_initfn(ISADevice *dev) cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0, isa_address_space(dev), isa_address_space_io(dev)); s->con = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, + s->text_update, s); rom_add_vga(VGABIOS_CIRRUS_FILENAME); /* XXX ISA-LFB support */ @@ -2960,7 +2960,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) cirrus_init_common(s, device_id, 1, pci_address_space(dev), pci_address_space_io(dev)); s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate, - s->vga.screen_dump, s->vga.text_update, + s->vga.text_update, &s->vga); /* setup PCI */ diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c index 7e1cbb63c9..d651ddb0c1 100644 --- a/hw/display/exynos4210_fimd.c +++ b/hw/display/exynos4210_fimd.c @@ -1901,7 +1901,7 @@ static int exynos4210_fimd_init(SysBusDevice *dev) "exynos4210.fimd", FIMD_REGS_SIZE); sysbus_init_mmio(dev, &s->iomem); s->console = graphic_console_init(exynos4210_fimd_update, - exynos4210_fimd_invalidate, NULL, NULL, s); + exynos4210_fimd_invalidate, NULL, s); return 0; } diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index f7014e9dd8..b70fe8afa4 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -294,77 +294,6 @@ static void g364fb_reset(G364State *s) g364fb_invalidate_display(s); } -static void g364fb_screen_dump(void *opaque, const char *filename, bool cswitch, - Error **errp) -{ - G364State *s = opaque; - int ret, y, x; - uint8_t index; - uint8_t *data_buffer; - FILE *f; - - qemu_flush_coalesced_mmio_buffer(); - - if (s->depth != 8) { - error_setg(errp, "g364: unknown guest depth %d", s->depth); - return; - } - - f = fopen(filename, "wb"); - if (!f) { - error_setg(errp, "failed to open file '%s': %s", filename, - strerror(errno)); - return; - } - - if (s->ctla & CTLA_FORCE_BLANK) { - /* blank screen */ - ret = fprintf(f, "P4\n%d %d\n", s->width, s->height); - if (ret < 0) { - goto write_err; - } - for (y = 0; y < s->height; y++) - for (x = 0; x < s->width; x++) { - ret = fputc(0, f); - if (ret == EOF) { - goto write_err; - } - } - } else { - data_buffer = s->vram + s->top_of_screen; - ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255); - if (ret < 0) { - goto write_err; - } - for (y = 0; y < s->height; y++) - for (x = 0; x < s->width; x++, data_buffer++) { - index = *data_buffer; - ret = fputc(s->color_palette[index][0], f); - if (ret == EOF) { - goto write_err; - } - ret = fputc(s->color_palette[index][1], f); - if (ret == EOF) { - goto write_err; - } - ret = fputc(s->color_palette[index][2], f); - if (ret == EOF) { - goto write_err; - } - } - } - -out: - fclose(f); - return; - -write_err: - error_setg(errp, "failed to write to file '%s': %s", filename, - strerror(errno)); - unlink(filename); - goto out; -} - /* called for accesses to io ports */ static uint64_t g364fb_ctrl_read(void *opaque, hwaddr addr, @@ -552,7 +481,7 @@ static void g364fb_init(DeviceState *dev, G364State *s) s->con = graphic_console_init(g364fb_update_display, g364fb_invalidate_display, - g364fb_screen_dump, NULL, s); + NULL, s); memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000); memory_region_init_ram_ptr(&s->mem_vram, "vram", diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c index 05528c7c81..c027f76625 100644 --- a/hw/display/jazz_led.c +++ b/hw/display/jazz_led.c @@ -263,7 +263,6 @@ static int jazz_led_init(SysBusDevice *dev) s->con = graphic_console_init(jazz_led_update_display, jazz_led_invalidate_display, - NULL, jazz_led_text_update, s); return 0; diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c index 3219041c81..9bdb5c7e99 100644 --- a/hw/display/milkymist-vgafb.c +++ b/hw/display/milkymist-vgafb.c @@ -280,7 +280,7 @@ static int milkymist_vgafb_init(SysBusDevice *dev) s->con = graphic_console_init(vgafb_update_display, vgafb_invalidate_display, - NULL, NULL, s); + NULL, s); return 0; } diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c index be7e9c0d74..f76f6135d6 100644 --- a/hw/display/omap_lcdc.c +++ b/hw/display/omap_lcdc.c @@ -227,90 +227,6 @@ static void omap_update_display(void *opaque) omap_lcd->invalidate = 0; } -static void omap_ppm_save(const char *filename, uint8_t *data, - int w, int h, int linesize, Error **errp) -{ - FILE *f; - uint8_t *d, *d1; - unsigned int v; - int ret, y, x, bpp; - - f = fopen(filename, "wb"); - if (!f) { - error_setg(errp, "failed to open file '%s': %s", filename, - strerror(errno)); - return; - } - ret = fprintf(f, "P6\n%d %d\n%d\n", w, h, 255); - if (ret < 0) { - goto write_err; - } - d1 = data; - bpp = linesize / w; - for (y = 0; y < h; y ++) { - d = d1; - for (x = 0; x < w; x ++) { - v = *(uint32_t *) d; - switch (bpp) { - case 2: - ret = fputc((v >> 8) & 0xf8, f); - if (ret == EOF) { - goto write_err; - } - ret = fputc((v >> 3) & 0xfc, f); - if (ret == EOF) { - goto write_err; - } - ret = fputc((v << 3) & 0xf8, f); - if (ret == EOF) { - goto write_err; - } - break; - case 3: - case 4: - default: - ret = fputc((v >> 16) & 0xff, f); - if (ret == EOF) { - goto write_err; - } - ret = fputc((v >> 8) & 0xff, f); - if (ret == EOF) { - goto write_err; - } - ret = fputc((v) & 0xff, f); - if (ret == EOF) { - goto write_err; - } - break; - } - d += bpp; - } - d1 += linesize; - } -out: - fclose(f); - return; - -write_err: - error_setg(errp, "failed to write to file '%s': %s", filename, - strerror(errno)); - unlink(filename); - goto out; -} - -static void omap_screen_dump(void *opaque, const char *filename, bool cswitch, - Error **errp) -{ - struct omap_lcd_panel_s *omap_lcd = opaque; - DisplaySurface *surface = qemu_console_surface(omap_lcd->con); - - omap_update_display(opaque); - if (omap_lcd && surface_data(surface)) - omap_ppm_save(filename, surface_data(surface), - omap_lcd->width, omap_lcd->height, - surface_stride(surface), errp); -} - static void omap_invalidate_display(void *opaque) { struct omap_lcd_panel_s *omap_lcd = opaque; omap_lcd->invalidate = 1; @@ -487,7 +403,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem, s->con = graphic_console_init(omap_update_display, omap_invalidate_display, - omap_screen_dump, NULL, s); + NULL, s); return s; } diff --git a/hw/display/pl110.c b/hw/display/pl110.c index 295434eded..5599755f11 100644 --- a/hw/display/pl110.c +++ b/hw/display/pl110.c @@ -454,7 +454,7 @@ static int pl110_init(SysBusDevice *dev) qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1); s->con = graphic_console_init(pl110_update_display, pl110_invalidate_display, - NULL, NULL, s); + NULL, s); return 0; } diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c index c9bd42e023..d38479df1a 100644 --- a/hw/display/pxa2xx_lcd.c +++ b/hw/display/pxa2xx_lcd.c @@ -1010,7 +1010,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, s->con = graphic_console_init(pxa2xx_update_display, pxa2xx_invalidate_display, - NULL, NULL, s); + NULL, s); surface = qemu_console_surface(s->con); switch (surface_bits_per_pixel(surface)) { diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 247209d6d2..3b09d208fd 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1772,26 +1772,6 @@ static void qxl_hw_invalidate(void *opaque) vga->invalidate(vga); } -static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch, - Error **errp) -{ - PCIQXLDevice *qxl = opaque; - VGACommonState *vga = &qxl->vga; - - switch (qxl->mode) { - case QXL_MODE_COMPAT: - case QXL_MODE_NATIVE: - qxl_render_update(qxl); - ppm_save(filename, qxl->ssd.ds, errp); - break; - case QXL_MODE_VGA: - vga->screen_dump(vga, filename, cswitch, errp); - break; - default: - break; - } -} - static void qxl_hw_text_update(void *opaque, console_ch_t *chardata) { PCIQXLDevice *qxl = opaque; @@ -2075,7 +2055,7 @@ static int qxl_init_primary(PCIDevice *dev) portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0); vga->con = graphic_console_init(qxl_hw_update, qxl_hw_invalidate, - qxl_hw_screen_dump, qxl_hw_text_update, + qxl_hw_text_update, qxl); qxl->ssd.con = vga->con, qemu_spice_display_init_common(&qxl->ssd); diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 9878df4af6..e57ff223be 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1446,5 +1446,5 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base, /* create qemu graphic console */ s->con = graphic_console_init(sm501_update_display, NULL, - NULL, NULL, s); + NULL, s); } diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c index 183a87835c..9b6810f2c5 100644 --- a/hw/display/ssd0303.c +++ b/hw/display/ssd0303.c @@ -290,7 +290,7 @@ static int ssd0303_init(I2CSlave *i2c) s->con = graphic_console_init(ssd0303_update_display, ssd0303_invalidate_display, - NULL, NULL, s); + NULL, s); qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY); return 0; } diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c index 5cf2f7058f..301cb20972 100644 --- a/hw/display/ssd0323.c +++ b/hw/display/ssd0323.c @@ -339,7 +339,7 @@ static int ssd0323_init(SSISlave *dev) s->row_end = 79; s->con = graphic_console_init(ssd0323_update_display, ssd0323_invalidate_display, - NULL, NULL, s); + NULL, s); qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY); qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1); diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c index 178a21fd8d..01beba4751 100644 --- a/hw/display/tc6393xb.c +++ b/hw/display/tc6393xb.c @@ -585,7 +585,6 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq) s->scr_height = 640; s->con = graphic_console_init(tc6393xb_update_display, NULL, /* invalidate */ - NULL, /* screen_dump */ NULL, /* text_update */ s); diff --git a/hw/display/tcx.c b/hw/display/tcx.c index c44068e7c9..ba3857a25b 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -56,11 +56,6 @@ typedef struct TCXState { uint8_t dac_index, dac_state; } TCXState; -static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch, - Error **errp); -static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch, - Error **errp); - static void tcx_set_dirty(TCXState *s) { memory_region_set_dirty(&s->vram_mem, 0, MAXX * MAXY); @@ -569,7 +564,7 @@ static int tcx_init1(SysBusDevice *dev) s->con = graphic_console_init(tcx24_update_display, tcx24_invalidate_display, - tcx24_screen_dump, NULL, s); + NULL, s); } else { /* THC 8 bit (dummy) */ memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8", @@ -578,133 +573,13 @@ static int tcx_init1(SysBusDevice *dev) s->con = graphic_console_init(tcx_update_display, tcx_invalidate_display, - tcx_screen_dump, NULL, s); + NULL, s); } qemu_console_resize(s->con, s->width, s->height); return 0; } -static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch, - Error **errp) -{ - TCXState *s = opaque; - FILE *f; - uint8_t *d, *d1, v; - int ret, y, x; - - f = fopen(filename, "wb"); - if (!f) { - error_setg(errp, "failed to open file '%s': %s", filename, - strerror(errno)); - return; - } - ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255); - if (ret < 0) { - goto write_err; - } - d1 = s->vram; - for(y = 0; y < s->height; y++) { - d = d1; - for(x = 0; x < s->width; x++) { - v = *d; - ret = fputc(s->r[v], f); - if (ret == EOF) { - goto write_err; - } - ret = fputc(s->g[v], f); - if (ret == EOF) { - goto write_err; - } - ret = fputc(s->b[v], f); - if (ret == EOF) { - goto write_err; - } - d++; - } - d1 += MAXX; - } - -out: - fclose(f); - return; - -write_err: - error_setg(errp, "failed to write to file '%s': %s", filename, - strerror(errno)); - unlink(filename); - goto out; -} - -static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch, - Error **errp) -{ - TCXState *s = opaque; - FILE *f; - uint8_t *d, *d1, v; - uint32_t *s24, *cptr, dval; - int ret, y, x; - - f = fopen(filename, "wb"); - if (!f) { - error_setg(errp, "failed to open file '%s': %s", filename, - strerror(errno)); - return; - } - ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255); - if (ret < 0) { - goto write_err; - } - d1 = s->vram; - s24 = s->vram24; - cptr = s->cplane; - for(y = 0; y < s->height; y++) { - d = d1; - for(x = 0; x < s->width; x++, d++, s24++) { - if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct - dval = *s24 & 0x00ffffff; - ret = fputc((dval >> 16) & 0xff, f); - if (ret == EOF) { - goto write_err; - } - ret = fputc((dval >> 8) & 0xff, f); - if (ret == EOF) { - goto write_err; - } - ret = fputc(dval & 0xff, f); - if (ret == EOF) { - goto write_err; - } - } else { - v = *d; - ret = fputc(s->r[v], f); - if (ret == EOF) { - goto write_err; - } - ret = fputc(s->g[v], f); - if (ret == EOF) { - goto write_err; - } - ret = fputc(s->b[v], f); - if (ret == EOF) { - goto write_err; - } - } - } - d1 += MAXX; - } - -out: - fclose(f); - return; - -write_err: - error_setg(errp, "failed to write to file '%s': %s", filename, - strerror(errno)); - unlink(filename); - goto out; -} - static Property tcx_properties[] = { DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1), DEFINE_PROP_UINT16("width", TCXState, width, -1), diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c index 1c50070216..e177197f15 100644 --- a/hw/display/vga-isa-mm.c +++ b/hw/display/vga-isa-mm.c @@ -136,7 +136,7 @@ int isa_vga_mm_init(hwaddr vram_base, vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space); s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate, - s->vga.screen_dump, s->vga.text_update, + s->vga.text_update, s); vga_init_vbe(&s->vga, address_space); diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c index 90959ebc2c..228657e6b8 100644 --- a/hw/display/vga-isa.c +++ b/hw/display/vga-isa.c @@ -63,7 +63,7 @@ static int vga_initfn(ISADevice *dev) vga_io_memory, 1); memory_region_set_coalescing(vga_io_memory); s->con = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); + s->text_update, s); vga_init_vbe(s, isa_address_space(dev)); /* ROM BIOS */ diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index a9c69b6ac7..a6245b4f7d 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -151,7 +151,7 @@ static int pci_std_vga_initfn(PCIDevice *dev) vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true); s->con = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); + s->text_update, s); /* XXX: VGA_RAM_SIZE must be a power of two */ pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); diff --git a/hw/display/vga.c b/hw/display/vga.c index e37e8984bc..5d7684a94c 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -166,9 +166,6 @@ static uint32_t expand4[256]; static uint16_t expand2[256]; static uint8_t expand4to8[16]; -static void vga_screen_dump(void *opaque, const char *filename, bool cswitch, - Error **errp); - static void vga_update_memory_access(VGACommonState *s) { MemoryRegion *region, *old_region = s->chain4_alias; @@ -2298,7 +2295,6 @@ void vga_common_init(VGACommonState *s) s->get_resolution = vga_get_resolution; s->update = vga_update_display; s->invalidate = vga_invalidate_display; - s->screen_dump = vga_screen_dump; s->text_update = vga_update_text; switch (vga_retrace_method) { case VGA_RETRACE_DUMB: @@ -2393,65 +2389,3 @@ void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory) &s->vram_vbe); s->vbe_mapped = 1; } -/********************************************************/ -/* vga screen dump */ - -void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp) -{ - int width = pixman_image_get_width(ds->image); - int height = pixman_image_get_height(ds->image); - FILE *f; - int y; - int ret; - pixman_image_t *linebuf; - - trace_ppm_save(filename, ds); - f = fopen(filename, "wb"); - if (!f) { - error_setg(errp, "failed to open file '%s': %s", filename, - strerror(errno)); - return; - } - ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255); - if (ret < 0) { - linebuf = NULL; - goto write_err; - } - linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width); - for (y = 0; y < height; y++) { - qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y); - clearerr(f); - ret = fwrite(pixman_image_get_data(linebuf), 1, - pixman_image_get_stride(linebuf), f); - (void)ret; - if (ferror(f)) { - goto write_err; - } - } - -out: - qemu_pixman_image_unref(linebuf); - fclose(f); - return; - -write_err: - error_setg(errp, "failed to write to file '%s': %s", filename, - strerror(errno)); - unlink(filename); - goto out; -} - -/* save the vga display in a PPM image even if no display is - available */ -static void vga_screen_dump(void *opaque, const char *filename, bool cswitch, - Error **errp) -{ - VGACommonState *s = opaque; - DisplaySurface *surface = qemu_console_surface(s->con); - - if (cswitch) { - vga_invalidate_display(s); - } - graphic_hw_update(s->con); - ppm_save(filename, surface, errp); -} diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index 1b8f670868..e4bb4a03c3 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -154,7 +154,6 @@ typedef struct VGACommonState { unsigned int g, unsigned b); graphic_hw_update_ptr update; graphic_hw_invalidate_ptr invalidate; - graphic_hw_screen_dump_ptr screen_dump; graphic_hw_text_update_ptr text_update; bool full_update_text; bool full_update_gfx; @@ -198,7 +197,6 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val); uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr); void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val); void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2); -void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp); int vga_ioport_invalid(VGACommonState *s, uint32_t addr); diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 05befe44c7..61d8c15367 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -1119,31 +1119,6 @@ static void vmsvga_invalidate_display(void *opaque) s->invalidated = 1; } -/* save the vga display in a PPM image even if no display is - available */ -static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch, - Error **errp) -{ - struct vmsvga_state_s *s = opaque; - DisplaySurface *surface = qemu_console_surface(s->vga.con); - - if (!s->enable) { - s->vga.screen_dump(&s->vga, filename, cswitch, errp); - return; - } - - if (surface_bits_per_pixel(surface) == 32) { - DisplaySurface *ds = qemu_create_displaysurface_from( - surface_width(surface), - surface_height(surface), - 32, - surface_stride(surface), - s->vga.vram_ptr, false); - ppm_save(filename, ds, errp); - g_free(ds); - } -} - static void vmsvga_text_update(void *opaque, console_ch_t *chardata) { struct vmsvga_state_s *s = opaque; @@ -1212,7 +1187,6 @@ static void vmsvga_init(struct vmsvga_state_s *s, s->vga.con = graphic_console_init(vmsvga_update_display, vmsvga_invalidate_display, - vmsvga_screen_dump, vmsvga_text_update, s); s->fifo_size = SVGA_FIFO_SIZE; diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c index e371569585..80cc9e8320 100644 --- a/hw/display/xenfb.c +++ b/hw/display/xenfb.c @@ -1007,7 +1007,6 @@ wait_more: fb->c.con = graphic_console_init(xenfb_update, xenfb_invalidate, NULL, - NULL, fb); fb->have_console = 1; diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c index 7c8fc364c8..7488547eef 100644 --- a/hw/unicore32/puv3.c +++ b/hw/unicore32/puv3.c @@ -92,7 +92,7 @@ static void puv3_load_kernel(const char *kernel_filename) } /* cheat curses that we have a graphic console, only under ocd console */ - graphic_console_init(NULL, NULL, NULL, NULL, NULL); + graphic_console_init(NULL, NULL, NULL, NULL); } static void puv3_init(QEMUMachineInitArgs *args) diff --git a/include/ui/console.h b/include/ui/console.h index 0dd66fd91f..d6e3e929b7 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -279,13 +279,10 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch) typedef void (*graphic_hw_update_ptr)(void *); typedef void (*graphic_hw_invalidate_ptr)(void *); -typedef void (*graphic_hw_screen_dump_ptr)(void *, const char *, bool cswitch, - Error **errp); typedef void (*graphic_hw_text_update_ptr)(void *, console_ch_t *); QemuConsole *graphic_console_init(graphic_hw_update_ptr update, graphic_hw_invalidate_ptr invalidate, - graphic_hw_screen_dump_ptr screen_dump, graphic_hw_text_update_ptr text_update, void *opaque); diff --git a/ui/console.c b/ui/console.c index e8e548e4c0..537b2fc52f 100644 --- a/ui/console.c +++ b/ui/console.c @@ -121,7 +121,6 @@ struct QemuConsole { /* Graphic console state. */ graphic_hw_update_ptr hw_update; graphic_hw_invalidate_ptr hw_invalidate; - graphic_hw_screen_dump_ptr hw_screen_dump; graphic_hw_text_update_ptr hw_text_update; void *hw; int g_width, g_height; @@ -188,28 +187,65 @@ void graphic_hw_invalidate(QemuConsole *con) } } -void qmp_screendump(const char *filename, Error **errp) +static void ppm_save(const char *filename, struct DisplaySurface *ds, + Error **errp) { - QemuConsole *previous_active_console; - bool cswitch; - - previous_active_console = active_console; - cswitch = previous_active_console && previous_active_console->index != 0; + int width = pixman_image_get_width(ds->image); + int height = pixman_image_get_height(ds->image); + FILE *f; + int y; + int ret; + pixman_image_t *linebuf; - /* There is currently no way of specifying which screen we want to dump, - so always dump the first one. */ - if (cswitch) { - console_select(0); + trace_ppm_save(filename, ds); + f = fopen(filename, "wb"); + if (!f) { + error_setg(errp, "failed to open file '%s': %s", filename, + strerror(errno)); + return; } - if (consoles[0] && consoles[0]->hw_screen_dump) { - consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, errp); - } else { - error_setg(errp, "device doesn't support screendump"); + ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255); + if (ret < 0) { + linebuf = NULL; + goto write_err; + } + linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width); + for (y = 0; y < height; y++) { + qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y); + clearerr(f); + ret = fwrite(pixman_image_get_data(linebuf), 1, + pixman_image_get_stride(linebuf), f); + (void)ret; + if (ferror(f)) { + goto write_err; + } } - if (cswitch) { - console_select(previous_active_console->index); +out: + qemu_pixman_image_unref(linebuf); + fclose(f); + return; + +write_err: + error_setg(errp, "failed to write to file '%s': %s", filename, + strerror(errno)); + unlink(filename); + goto out; +} + +void qmp_screendump(const char *filename, Error **errp) +{ + QemuConsole *con = consoles[0]; + DisplaySurface *surface; + + if (con == NULL) { + error_setg(errp, "There is no QemuConsole I can screendump from."); + return; } + + graphic_hw_update(con); + surface = qemu_console_surface(con); + ppm_save(filename, surface, errp); } void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata) @@ -1411,7 +1447,6 @@ DisplayState *init_displaystate(void) QemuConsole *graphic_console_init(graphic_hw_update_ptr update, graphic_hw_invalidate_ptr invalidate, - graphic_hw_screen_dump_ptr screen_dump, graphic_hw_text_update_ptr text_update, void *opaque) { @@ -1425,7 +1460,6 @@ QemuConsole *graphic_console_init(graphic_hw_update_ptr update, s = new_console(ds, GRAPHIC_CONSOLE); s->hw_update = update; s->hw_invalidate = invalidate; - s->hw_screen_dump = screen_dump; s->hw_text_update = text_update; s->hw = opaque; -- cgit v1.2.3 From 36671fbd06f31efc592c37acda3f8a75599e48e0 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 13 Mar 2013 10:14:52 +0100 Subject: console: zap g_width + g_height We have a surface per QemuConsole now, so there is no need to keep track of the QemuConsole size any more as we can query the surface size directly at any time. Signed-off-by: Gerd Hoffmann --- ui/console.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/ui/console.c b/ui/console.c index 537b2fc52f..dd1a0fcfc7 100644 --- a/ui/console.c +++ b/ui/console.c @@ -123,7 +123,6 @@ struct QemuConsole { graphic_hw_invalidate_ptr hw_invalidate; graphic_hw_text_update_ptr hw_text_update; void *hw; - int g_width, g_height; /* Text console state */ int width; @@ -389,8 +388,8 @@ static void text_console_resize(QemuConsole *s) int w1, x, y, last_width; last_width = s->width; - s->width = s->g_width / FONT_WIDTH; - s->height = s->g_height / FONT_HEIGHT; + s->width = surface_width(s->surface) / FONT_WIDTH; + s->height = surface_height(s->surface) / FONT_HEIGHT; w1 = last_width; if (s->width < w1) @@ -951,18 +950,12 @@ static void console_putchar(QemuConsole *s, int ch) void console_select(unsigned int index) { - DisplaySurface *surface; QemuConsole *s; if (index >= MAX_CONSOLES) return; trace_console_select(index); - if (active_console) { - surface = qemu_console_surface(active_console); - active_console->g_width = surface_width(surface); - active_console->g_height = surface_height(surface); - } s = consoles[index]; if (s) { DisplayState *ds = s->ds; @@ -1089,11 +1082,8 @@ void kbd_put_keysym(int keysym) static void text_console_invalidate(void *opaque) { QemuConsole *s = (QemuConsole *) opaque; - DisplaySurface *surface = qemu_console_surface(s); if (s->ds->have_text && s->console_type == TEXT_CONSOLE) { - s->g_width = surface_width(surface); - s->g_height = surface_height(surface); text_console_resize(s); } console_refresh(s); @@ -1497,6 +1487,8 @@ static void text_console_update_cursor(void *opaque) static void text_console_do_init(CharDriverState *chr, DisplayState *ds) { QemuConsole *s; + int g_width = 80 * FONT_WIDTH; + int g_height = 24 * FONT_HEIGHT; s = chr->opaque; @@ -1512,16 +1504,13 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds) s->total_height = DEFAULT_BACKSCROLL; s->x = 0; s->y = 0; - if (s->console_type == TEXT_CONSOLE) { + if (!s->surface) { if (active_console && active_console->surface) { - s->g_width = surface_width(active_console->surface); - s->g_height = surface_height(active_console->surface); - } else { - s->g_width = 80 * FONT_WIDTH; - s->g_height = 24 * FONT_HEIGHT; + g_width = surface_width(active_console->surface); + g_height = surface_height(active_console->surface); } + s->surface = qemu_create_displaysurface(g_width, g_height); } - s->surface = qemu_create_displaysurface(s->g_width, s->g_height); s->cursor_timer = qemu_new_timer_ms(rt_clock, text_console_update_cursor, s); @@ -1583,6 +1572,7 @@ static CharDriverState *text_console_init(ChardevVC *vc) s = new_console(NULL, TEXT_CONSOLE); } else { s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE); + s->surface = qemu_create_displaysurface(width, height); } if (!s) { @@ -1591,8 +1581,6 @@ static CharDriverState *text_console_init(ChardevVC *vc) } s->chr = chr; - s->g_width = width; - s->g_height = height; chr->opaque = s; chr->chr_set_echo = text_console_set_echo; @@ -1619,8 +1607,6 @@ void qemu_console_resize(QemuConsole *s, int width, int height) DisplaySurface *surface; assert(s->console_type == GRAPHIC_CONSOLE); - s->g_width = width; - s->g_height = height; surface = qemu_create_displaysurface(width, height); dpy_gfx_replace_surface(s, surface); } -- cgit v1.2.3 From 98a9ad9082284df62fb5b9355dd1901639de8268 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 13 Mar 2013 12:17:13 +0100 Subject: console: move gui_update+gui_setup_refresh from vl.c into console.c Pure code motion, no functional changes. Signed-off-by: Gerd Hoffmann --- include/ui/console.h | 2 -- ui/console.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ vl.c | 49 ------------------------------------------------- 3 files changed, 50 insertions(+), 51 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index d6e3e929b7..d92626b650 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -213,8 +213,6 @@ static inline int is_buffer_shared(DisplaySurface *surface) return !(surface->flags & QEMU_ALLOCATED_FLAG); } -void gui_setup_refresh(DisplayState *ds); - void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl); void unregister_displaychangelistener(DisplayChangeListener *dcl); diff --git a/ui/console.c b/ui/console.c index dd1a0fcfc7..b618221151 100644 --- a/ui/console.c +++ b/ui/console.c @@ -166,6 +166,56 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds); static void dpy_gfx_switch_surface(DisplayState *ds, DisplaySurface *surface); +static void gui_update(void *opaque) +{ + uint64_t interval = GUI_REFRESH_INTERVAL; + DisplayState *ds = opaque; + DisplayChangeListener *dcl; + + dpy_refresh(ds); + + QLIST_FOREACH(dcl, &ds->listeners, next) { + if (dcl->gui_timer_interval && + dcl->gui_timer_interval < interval) { + interval = dcl->gui_timer_interval; + } + } + qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock)); +} + +static void gui_setup_refresh(DisplayState *ds) +{ + DisplayChangeListener *dcl; + bool need_timer = false; + bool have_gfx = false; + bool have_text = false; + + QLIST_FOREACH(dcl, &ds->listeners, next) { + if (dcl->ops->dpy_refresh != NULL) { + need_timer = true; + } + if (dcl->ops->dpy_gfx_update != NULL) { + have_gfx = true; + } + if (dcl->ops->dpy_text_update != NULL) { + have_text = true; + } + } + + if (need_timer && ds->gui_timer == NULL) { + ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds); + qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock)); + } + if (!need_timer && ds->gui_timer != NULL) { + qemu_del_timer(ds->gui_timer); + qemu_free_timer(ds->gui_timer); + ds->gui_timer = NULL; + } + + ds->have_gfx = have_gfx; + ds->have_text = have_text; +} + void graphic_hw_update(QemuConsole *con) { if (!con) { diff --git a/vl.c b/vl.c index 63fe9a44a8..2ef00d893a 100644 --- a/vl.c +++ b/vl.c @@ -1626,55 +1626,6 @@ MachineInfoList *qmp_query_machines(Error **errp) /***********************************************************/ /* main execution loop */ -static void gui_update(void *opaque) -{ - uint64_t interval = GUI_REFRESH_INTERVAL; - DisplayState *ds = opaque; - DisplayChangeListener *dcl; - - dpy_refresh(ds); - - QLIST_FOREACH(dcl, &ds->listeners, next) { - if (dcl->gui_timer_interval && - dcl->gui_timer_interval < interval) - interval = dcl->gui_timer_interval; - } - qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock)); -} - -void gui_setup_refresh(DisplayState *ds) -{ - DisplayChangeListener *dcl; - bool need_timer = false; - bool have_gfx = false; - bool have_text = false; - - QLIST_FOREACH(dcl, &ds->listeners, next) { - if (dcl->ops->dpy_refresh != NULL) { - need_timer = true; - } - if (dcl->ops->dpy_gfx_update != NULL) { - have_gfx = true; - } - if (dcl->ops->dpy_text_update != NULL) { - have_text = true; - } - } - - if (need_timer && ds->gui_timer == NULL) { - ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds); - qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock)); - } - if (!need_timer && ds->gui_timer != NULL) { - qemu_del_timer(ds->gui_timer); - qemu_free_timer(ds->gui_timer); - ds->gui_timer = NULL; - } - - ds->have_gfx = have_gfx; - ds->have_text = have_text; -} - struct vm_change_state_entry { VMChangeStateHandler *cb; void *opaque; -- cgit v1.2.3 From 27be55872dd747c733a42a3d90864d9f59272d26 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 13 Mar 2013 12:25:25 +0100 Subject: console: make DisplayState private to console.c With gui_* being moved to console.c nobody outside console.c needs access to DisplayState fields any more. Make the struct private. Signed-off-by: Gerd Hoffmann --- include/ui/console.h | 8 -------- ui/console.c | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index d92626b650..50cd7b0560 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -182,14 +182,6 @@ struct DisplayChangeListener { QLIST_ENTRY(DisplayChangeListener) next; }; -struct DisplayState { - struct QEMUTimer *gui_timer; - bool have_gfx; - bool have_text; - - QLIST_HEAD(, DisplayChangeListener) listeners; -}; - DisplayState *init_displaystate(void); DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, int linesize, uint8_t *data, diff --git a/ui/console.c b/ui/console.c index b618221151..07fba67f79 100644 --- a/ui/console.c +++ b/ui/console.c @@ -157,6 +157,14 @@ struct QemuConsole { QEMUTimer *kbd_timer; }; +struct DisplayState { + struct QEMUTimer *gui_timer; + bool have_gfx; + bool have_text; + + QLIST_HEAD(, DisplayChangeListener) listeners; +}; + static DisplayState *display_state; static QemuConsole *active_console; static QemuConsole *consoles[MAX_CONSOLES]; -- cgit v1.2.3 From 380cd056ec0e7fc8bbd553cdcb061d3ca612bb82 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 13 Mar 2013 14:04:18 +0100 Subject: console: add GraphicHwOps Pass a single GraphicHwOps struct pointer to graphic_console_init, instead of a bunch of function pointers. Signed-off-by: Gerd Hoffmann --- hw/arm/musicpal.c | 8 ++++++-- hw/display/blizzard.c | 9 ++++++--- hw/display/cirrus_vga.c | 8 ++------ hw/display/exynos4210_fimd.c | 8 ++++++-- hw/display/g364fb.c | 9 ++++++--- hw/display/jazz_led.c | 10 +++++++--- hw/display/milkymist-vgafb.c | 9 ++++++--- hw/display/omap_lcdc.c | 9 ++++++--- hw/display/pl110.c | 9 ++++++--- hw/display/pxa2xx_lcd.c | 9 ++++++--- hw/display/qxl.c | 16 ++++++++++------ hw/display/sm501.c | 7 +++++-- hw/display/ssd0303.c | 9 ++++++--- hw/display/ssd0323.c | 9 ++++++--- hw/display/tc6393xb.c | 9 +++++---- hw/display/tcx.c | 18 ++++++++++++------ hw/display/vga-isa-mm.c | 4 +--- hw/display/vga-isa.c | 3 +-- hw/display/vga-pci.c | 3 +-- hw/display/vga.c | 10 +++++++--- hw/display/vga_int.h | 4 +--- hw/display/vmware_vga.c | 20 ++++++++++++-------- hw/display/xenfb.c | 10 ++++++---- hw/unicore32/puv3.c | 4 +++- include/ui/console.h | 12 ++++++------ ui/console.c | 33 ++++++++++++++++----------------- 26 files changed, 155 insertions(+), 104 deletions(-) diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index 6e77447e45..31586c652e 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -601,6 +601,11 @@ static const MemoryRegionOps musicpal_lcd_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static const GraphicHwOps musicpal_gfx_ops = { + .invalidate = lcd_invalidate, + .gfx_update = lcd_refresh, +}; + static int musicpal_lcd_init(SysBusDevice *dev) { musicpal_lcd_state *s = FROM_SYSBUS(musicpal_lcd_state, dev); @@ -611,8 +616,7 @@ static int musicpal_lcd_init(SysBusDevice *dev) "musicpal-lcd", MP_LCD_SIZE); sysbus_init_mmio(dev, &s->iomem); - s->con = graphic_console_init(lcd_refresh, lcd_invalidate, - NULL, s); + s->con = graphic_console_init(&musicpal_gfx_ops, s); qemu_console_resize(s->con, 128*3, 64*3); qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3); diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c index 70b68227fe..1ca3355e5d 100644 --- a/hw/display/blizzard.c +++ b/hw/display/blizzard.c @@ -944,6 +944,11 @@ static void blizzard_update_display(void *opaque) #define DEPTH 32 #include "blizzard_template.h" +static const GraphicHwOps blizzard_ops = { + .invalidate = blizzard_invalidate_display, + .gfx_update = blizzard_update_display, +}; + void *s1d13745_init(qemu_irq gpio_int) { BlizzardState *s = (BlizzardState *) g_malloc0(sizeof(*s)); @@ -951,9 +956,7 @@ void *s1d13745_init(qemu_irq gpio_int) s->fb = g_malloc(0x180000); - s->con = graphic_console_init(blizzard_update_display, - blizzard_invalidate_display, - NULL, s); + s->con = graphic_console_init(&blizzard_ops, s); surface = qemu_console_surface(s->con); switch (surface_bits_per_pixel(surface)) { diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index c31b021eca..db232af258 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -2910,9 +2910,7 @@ static int vga_initfn(ISADevice *dev) vga_common_init(s); cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0, isa_address_space(dev), isa_address_space_io(dev)); - s->con = graphic_console_init(s->update, s->invalidate, - s->text_update, - s); + s->con = graphic_console_init(s->hw_ops, s); rom_add_vga(VGABIOS_CIRRUS_FILENAME); /* XXX ISA-LFB support */ /* FIXME not qdev yet */ @@ -2959,9 +2957,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) vga_common_init(&s->vga); cirrus_init_common(s, device_id, 1, pci_address_space(dev), pci_address_space_io(dev)); - s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate, - s->vga.text_update, - &s->vga); + s->vga.con = graphic_console_init(s->vga.hw_ops, &s->vga); /* setup PCI */ diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c index d651ddb0c1..e6e7b27d13 100644 --- a/hw/display/exynos4210_fimd.c +++ b/hw/display/exynos4210_fimd.c @@ -1887,6 +1887,11 @@ static const VMStateDescription exynos4210_fimd_vmstate = { } }; +static const GraphicHwOps exynos4210_fimd_ops = { + .invalidate = exynos4210_fimd_invalidate, + .gfx_update = exynos4210_fimd_update, +}; + static int exynos4210_fimd_init(SysBusDevice *dev) { Exynos4210fimdState *s = FROM_SYSBUS(Exynos4210fimdState, dev); @@ -1900,8 +1905,7 @@ static int exynos4210_fimd_init(SysBusDevice *dev) memory_region_init_io(&s->iomem, &exynos4210_fimd_mmio_ops, s, "exynos4210.fimd", FIMD_REGS_SIZE); sysbus_init_mmio(dev, &s->iomem); - s->console = graphic_console_init(exynos4210_fimd_update, - exynos4210_fimd_invalidate, NULL, s); + s->console = graphic_console_init(&exynos4210_fimd_ops, s); return 0; } diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index b70fe8afa4..03810e9717 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -475,13 +475,16 @@ static const VMStateDescription vmstate_g364fb = { } }; +static const GraphicHwOps g364fb_ops = { + .invalidate = g364fb_invalidate_display, + .gfx_update = g364fb_update_display, +}; + static void g364fb_init(DeviceState *dev, G364State *s) { s->vram = g_malloc0(s->vram_size); - s->con = graphic_console_init(g364fb_update_display, - g364fb_invalidate_display, - NULL, s); + s->con = graphic_console_init(&g364fb_ops, s); memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000); memory_region_init_ram_ptr(&s->mem_vram, "vram", diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c index c027f76625..6306d8c12c 100644 --- a/hw/display/jazz_led.c +++ b/hw/display/jazz_led.c @@ -254,6 +254,12 @@ static const VMStateDescription vmstate_jazz_led = { } }; +static const GraphicHwOps jazz_led_ops = { + .invalidate = jazz_led_invalidate_display, + .gfx_update = jazz_led_update_display, + .text_update = jazz_led_text_update, +}; + static int jazz_led_init(SysBusDevice *dev) { LedState *s = FROM_SYSBUS(LedState, dev); @@ -261,9 +267,7 @@ static int jazz_led_init(SysBusDevice *dev) memory_region_init_io(&s->iomem, &led_ops, s, "led", 1); sysbus_init_mmio(dev, &s->iomem); - s->con = graphic_console_init(jazz_led_update_display, - jazz_led_invalidate_display, - jazz_led_text_update, s); + s->con = graphic_console_init(&jazz_led_ops, s); return 0; } diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c index 9bdb5c7e99..716997caa2 100644 --- a/hw/display/milkymist-vgafb.c +++ b/hw/display/milkymist-vgafb.c @@ -270,6 +270,11 @@ static void milkymist_vgafb_reset(DeviceState *d) s->regs[R_BASEADDRESS] = 0; } +static const GraphicHwOps vgafb_ops = { + .invalidate = vgafb_invalidate_display, + .gfx_update = vgafb_update_display, +}; + static int milkymist_vgafb_init(SysBusDevice *dev) { MilkymistVgafbState *s = FROM_SYSBUS(typeof(*s), dev); @@ -278,9 +283,7 @@ static int milkymist_vgafb_init(SysBusDevice *dev) "milkymist-vgafb", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); - s->con = graphic_console_init(vgafb_update_display, - vgafb_invalidate_display, - NULL, s); + s->con = graphic_console_init(&vgafb_ops, s); return 0; } diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c index f76f6135d6..e4a55958fa 100644 --- a/hw/display/omap_lcdc.c +++ b/hw/display/omap_lcdc.c @@ -384,6 +384,11 @@ void omap_lcdc_reset(struct omap_lcd_panel_s *s) s->ctrl = 0; } +static const GraphicHwOps omap_ops = { + .invalidate = omap_invalidate_display, + .gfx_update = omap_update_display, +}; + struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem, hwaddr base, qemu_irq irq, @@ -401,9 +406,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem, memory_region_init_io(&s->iomem, &omap_lcdc_ops, s, "omap.lcdc", 0x100); memory_region_add_subregion(sysmem, base, &s->iomem); - s->con = graphic_console_init(omap_update_display, - omap_invalidate_display, - NULL, s); + s->con = graphic_console_init(&omap_ops, s); return s; } diff --git a/hw/display/pl110.c b/hw/display/pl110.c index 5599755f11..d23243199c 100644 --- a/hw/display/pl110.c +++ b/hw/display/pl110.c @@ -444,6 +444,11 @@ static int vmstate_pl110_post_load(void *opaque, int version_id) return 0; } +static const GraphicHwOps pl110_gfx_ops = { + .invalidate = pl110_invalidate_display, + .gfx_update = pl110_update_display, +}; + static int pl110_init(SysBusDevice *dev) { pl110_state *s = FROM_SYSBUS(pl110_state, dev); @@ -452,9 +457,7 @@ static int pl110_init(SysBusDevice *dev) sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1); - s->con = graphic_console_init(pl110_update_display, - pl110_invalidate_display, - NULL, s); + s->con = graphic_console_init(&pl110_gfx_ops, s); return 0; } diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c index d38479df1a..12d9cd2808 100644 --- a/hw/display/pxa2xx_lcd.c +++ b/hw/display/pxa2xx_lcd.c @@ -991,6 +991,11 @@ static const VMStateDescription vmstate_pxa2xx_lcdc = { #define BITS 32 #include "pxa2xx_template.h" +static const GraphicHwOps pxa2xx_ops = { + .invalidate = pxa2xx_invalidate_display, + .gfx_update = pxa2xx_update_display, +}; + PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, hwaddr base, qemu_irq irq) { @@ -1008,9 +1013,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, "pxa2xx-lcd-controller", 0x00100000); memory_region_add_subregion(sysmem, base, &s->iomem); - s->con = graphic_console_init(pxa2xx_update_display, - pxa2xx_invalidate_display, - NULL, s); + s->con = graphic_console_init(&pxa2xx_ops, s); surface = qemu_console_surface(s->con); switch (surface_bits_per_pixel(surface)) { diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 3b09d208fd..8721d44d74 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1753,7 +1753,7 @@ static void qxl_hw_update(void *opaque) switch (qxl->mode) { case QXL_MODE_VGA: - vga->update(vga); + vga->hw_ops->gfx_update(vga); break; case QXL_MODE_COMPAT: case QXL_MODE_NATIVE: @@ -1769,7 +1769,7 @@ static void qxl_hw_invalidate(void *opaque) PCIQXLDevice *qxl = opaque; VGACommonState *vga = &qxl->vga; - vga->invalidate(vga); + vga->hw_ops->invalidate(vga); } static void qxl_hw_text_update(void *opaque, console_ch_t *chardata) @@ -1778,7 +1778,7 @@ static void qxl_hw_text_update(void *opaque, console_ch_t *chardata) VGACommonState *vga = &qxl->vga; if (qxl->mode == QXL_MODE_VGA) { - vga->text_update(vga, chardata); + vga->hw_ops->text_update(vga, chardata); return; } } @@ -2038,6 +2038,12 @@ static int qxl_init_common(PCIQXLDevice *qxl) return 0; } +static const GraphicHwOps qxl_ops = { + .invalidate = qxl_hw_invalidate, + .gfx_update = qxl_hw_update, + .text_update = qxl_hw_text_update, +}; + static int qxl_init_primary(PCIDevice *dev) { PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev); @@ -2054,9 +2060,7 @@ static int qxl_init_primary(PCIDevice *dev) portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga"); portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0); - vga->con = graphic_console_init(qxl_hw_update, qxl_hw_invalidate, - qxl_hw_text_update, - qxl); + vga->con = graphic_console_init(&qxl_ops, qxl); qxl->ssd.con = vga->con, qemu_spice_display_init_common(&qxl->ssd); diff --git a/hw/display/sm501.c b/hw/display/sm501.c index e57ff223be..f0e6d7022f 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1383,6 +1383,10 @@ static void sm501_update_display(void *opaque) sm501_draw_crt(s); } +static const GraphicHwOps sm501_ops = { + .gfx_update = sm501_update_display, +}; + void sm501_init(MemoryRegion *address_space_mem, uint32_t base, uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr) { @@ -1445,6 +1449,5 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base, } /* create qemu graphic console */ - s->con = graphic_console_init(sm501_update_display, NULL, - NULL, s); + s->con = graphic_console_init(&sm501_ops, s); } diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c index 9b6810f2c5..3d7ebbe6e2 100644 --- a/hw/display/ssd0303.c +++ b/hw/display/ssd0303.c @@ -284,13 +284,16 @@ static const VMStateDescription vmstate_ssd0303 = { } }; +static const GraphicHwOps ssd0303_ops = { + .invalidate = ssd0303_invalidate_display, + .gfx_update = ssd0303_update_display, +}; + static int ssd0303_init(I2CSlave *i2c) { ssd0303_state *s = FROM_I2C_SLAVE(ssd0303_state, i2c); - s->con = graphic_console_init(ssd0303_update_display, - ssd0303_invalidate_display, - NULL, s); + s->con = graphic_console_init(&ssd0303_ops, s); qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY); return 0; } diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c index 301cb20972..45e8dc1125 100644 --- a/hw/display/ssd0323.c +++ b/hw/display/ssd0323.c @@ -331,15 +331,18 @@ static int ssd0323_load(QEMUFile *f, void *opaque, int version_id) return 0; } +static const GraphicHwOps ssd0323_ops = { + .invalidate = ssd0323_invalidate_display, + .gfx_update = ssd0323_update_display, +}; + static int ssd0323_init(SSISlave *dev) { ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev); s->col_end = 63; s->row_end = 79; - s->con = graphic_console_init(ssd0323_update_display, - ssd0323_invalidate_display, - NULL, s); + s->con = graphic_console_init(&ssd0323_ops, s); qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY); qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1); diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c index 01beba4751..b5b255c31a 100644 --- a/hw/display/tc6393xb.c +++ b/hw/display/tc6393xb.c @@ -548,6 +548,10 @@ static void tc6393xb_writeb(void *opaque, hwaddr addr, (uint32_t) addr, (int)value & 0xff); } +static const GraphicHwOps tc6393xb_gfx_ops = { + .gfx_update = tc6393xb_update_display, +}; + TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq) { TC6393xbState *s; @@ -583,10 +587,7 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq) memory_region_add_subregion(sysmem, base + 0x100000, &s->vram); s->scr_width = 480; s->scr_height = 640; - s->con = graphic_console_init(tc6393xb_update_display, - NULL, /* invalidate */ - NULL, /* text_update */ - s); + s->con = graphic_console_init(&tc6393xb_gfx_ops, s); return s; } diff --git a/hw/display/tcx.c b/hw/display/tcx.c index ba3857a25b..77c7191c76 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -510,6 +510,16 @@ static const MemoryRegionOps dummy_ops = { }, }; +static const GraphicHwOps tcx_ops = { + .invalidate = tcx_invalidate_display, + .gfx_update = tcx_update_display, +}; + +static const GraphicHwOps tcx24_ops = { + .invalidate = tcx24_invalidate_display, + .gfx_update = tcx24_update_display, +}; + static int tcx_init1(SysBusDevice *dev) { TCXState *s = FROM_SYSBUS(TCXState, dev); @@ -562,18 +572,14 @@ static int tcx_init1(SysBusDevice *dev) &s->vram_mem, vram_offset, size); sysbus_init_mmio(dev, &s->vram_cplane); - s->con = graphic_console_init(tcx24_update_display, - tcx24_invalidate_display, - NULL, s); + s->con = graphic_console_init(&tcx24_ops, s); } else { /* THC 8 bit (dummy) */ memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8", TCX_THC_NREGS_8); sysbus_init_mmio(dev, &s->thc8); - s->con = graphic_console_init(tcx_update_display, - tcx_invalidate_display, - NULL, s); + s->con = graphic_console_init(&tcx_ops, s); } qemu_console_resize(s->con, s->width, s->height); diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c index e177197f15..2da08a11f7 100644 --- a/hw/display/vga-isa-mm.c +++ b/hw/display/vga-isa-mm.c @@ -135,9 +135,7 @@ int isa_vga_mm_init(hwaddr vram_base, vga_common_init(&s->vga); vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space); - s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate, - s->vga.text_update, - s); + s->vga.con = graphic_console_init(s->vga.hw_ops, s); vga_init_vbe(&s->vga, address_space); return 0; diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c index 228657e6b8..d2c548e14c 100644 --- a/hw/display/vga-isa.c +++ b/hw/display/vga-isa.c @@ -62,8 +62,7 @@ static int vga_initfn(ISADevice *dev) isa_mem_base + 0x000a0000, vga_io_memory, 1); memory_region_set_coalescing(vga_io_memory); - s->con = graphic_console_init(s->update, s->invalidate, - s->text_update, s); + s->con = graphic_console_init(s->hw_ops, s); vga_init_vbe(s, isa_address_space(dev)); /* ROM BIOS */ diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index a6245b4f7d..dc73f286da 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -150,8 +150,7 @@ static int pci_std_vga_initfn(PCIDevice *dev) vga_common_init(s); vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true); - s->con = graphic_console_init(s->update, s->invalidate, - s->text_update, s); + s->con = graphic_console_init(s->hw_ops, s); /* XXX: VGA_RAM_SIZE must be a power of two */ pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); diff --git a/hw/display/vga.c b/hw/display/vga.c index 5d7684a94c..21a108d8c0 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -2250,6 +2250,12 @@ const VMStateDescription vmstate_vga_common = { } }; +static const GraphicHwOps vga_ops = { + .invalidate = vga_invalidate_display, + .gfx_update = vga_update_display, + .text_update = vga_update_text, +}; + void vga_common_init(VGACommonState *s) { int i, j, v, b; @@ -2293,9 +2299,7 @@ void vga_common_init(VGACommonState *s) s->get_bpp = vga_get_bpp; s->get_offsets = vga_get_offsets; s->get_resolution = vga_get_resolution; - s->update = vga_update_display; - s->invalidate = vga_invalidate_display; - s->text_update = vga_update_text; + s->hw_ops = &vga_ops; switch (vga_retrace_method) { case VGA_RETRACE_DUMB: s->retrace = vga_dumb_retrace; diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index e4bb4a03c3..66f9f3ceed 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -152,9 +152,7 @@ typedef struct VGACommonState { uint32_t cursor_offset; unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b); - graphic_hw_update_ptr update; - graphic_hw_invalidate_ptr invalidate; - graphic_hw_text_update_ptr text_update; + const GraphicHwOps *hw_ops; bool full_update_text; bool full_update_gfx; /* hardware mouse cursor support */ diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 61d8c15367..263bf0915e 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -913,7 +913,7 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) case SVGA_REG_ENABLE: s->enable = !!value; s->invalidated = 1; - s->vga.invalidate(&s->vga); + s->vga.hw_ops->invalidate(&s->vga); if (s->enable && s->config) { vga_dirty_log_stop(&s->vga); } else { @@ -1058,7 +1058,7 @@ static void vmsvga_update_display(void *opaque) bool dirty = false; if (!s->enable) { - s->vga.update(&s->vga); + s->vga.hw_ops->gfx_update(&s->vga); return; } @@ -1112,7 +1112,7 @@ static void vmsvga_invalidate_display(void *opaque) { struct vmsvga_state_s *s = opaque; if (!s->enable) { - s->vga.invalidate(&s->vga); + s->vga.hw_ops->invalidate(&s->vga); return; } @@ -1123,8 +1123,8 @@ static void vmsvga_text_update(void *opaque, console_ch_t *chardata) { struct vmsvga_state_s *s = opaque; - if (s->vga.text_update) { - s->vga.text_update(&s->vga, chardata); + if (s->vga.hw_ops->text_update) { + s->vga.hw_ops->text_update(&s->vga, chardata); } } @@ -1179,15 +1179,19 @@ static const VMStateDescription vmstate_vmware_vga = { } }; +static const GraphicHwOps vmsvga_ops = { + .invalidate = vmsvga_invalidate_display, + .gfx_update = vmsvga_update_display, + .text_update = vmsvga_text_update, +}; + static void vmsvga_init(struct vmsvga_state_s *s, MemoryRegion *address_space, MemoryRegion *io) { s->scratch_size = SVGA_SCRATCH_SIZE; s->scratch = g_malloc(s->scratch_size * 4); - s->vga.con = graphic_console_init(vmsvga_update_display, - vmsvga_invalidate_display, - vmsvga_text_update, s); + s->vga.con = graphic_console_init(&vmsvga_ops, s); s->fifo_size = SVGA_FIFO_SIZE; memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size); diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c index 80cc9e8320..8d327f138e 100644 --- a/hw/display/xenfb.c +++ b/hw/display/xenfb.c @@ -977,6 +977,11 @@ struct XenDevOps xen_framebuffer_ops = { .frontend_changed = fb_frontend_changed, }; +static const GraphicHwOps xenfb_ops = { + .invalidate = xenfb_invalidate, + .gfx_update = xenfb_update, +}; + /* * FIXME/TODO: Kill this. * Temporary needed while DisplayState reorganization is in flight. @@ -1004,10 +1009,7 @@ wait_more: /* vfb */ fb = container_of(xfb, struct XenFB, c.xendev); - fb->c.con = graphic_console_init(xenfb_update, - xenfb_invalidate, - NULL, - fb); + fb->c.con = graphic_console_init(&xenfb_ops, fb); fb->have_console = 1; /* vkbd */ diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c index 7488547eef..f8d32bc04e 100644 --- a/hw/unicore32/puv3.c +++ b/hw/unicore32/puv3.c @@ -78,6 +78,8 @@ static void puv3_board_init(CPUUniCore32State *env, ram_addr_t ram_size) memory_region_add_subregion(get_system_memory(), 0, ram_memory); } +static const GraphicHwOps no_ops; + static void puv3_load_kernel(const char *kernel_filename) { int size; @@ -92,7 +94,7 @@ static void puv3_load_kernel(const char *kernel_filename) } /* cheat curses that we have a graphic console, only under ocd console */ - graphic_console_init(NULL, NULL, NULL, NULL); + graphic_console_init(&no_ops, NULL); } static void puv3_init(QEMUMachineInitArgs *args) diff --git a/include/ui/console.h b/include/ui/console.h index 50cd7b0560..f3e779193c 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -267,13 +267,13 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch) *dest = ch; } -typedef void (*graphic_hw_update_ptr)(void *); -typedef void (*graphic_hw_invalidate_ptr)(void *); -typedef void (*graphic_hw_text_update_ptr)(void *, console_ch_t *); +typedef struct GraphicHwOps { + void (*invalidate)(void *opaque); + void (*gfx_update)(void *opaque); + void (*text_update)(void *opaque, console_ch_t *text); +} GraphicHwOps; -QemuConsole *graphic_console_init(graphic_hw_update_ptr update, - graphic_hw_invalidate_ptr invalidate, - graphic_hw_text_update_ptr text_update, +QemuConsole *graphic_console_init(const GraphicHwOps *ops, void *opaque); void graphic_hw_update(QemuConsole *con); diff --git a/ui/console.c b/ui/console.c index 07fba67f79..79a306be8c 100644 --- a/ui/console.c +++ b/ui/console.c @@ -119,9 +119,7 @@ struct QemuConsole { DisplaySurface *surface; /* Graphic console state. */ - graphic_hw_update_ptr hw_update; - graphic_hw_invalidate_ptr hw_invalidate; - graphic_hw_text_update_ptr hw_text_update; + const GraphicHwOps *hw_ops; void *hw; /* Text console state */ @@ -229,8 +227,8 @@ void graphic_hw_update(QemuConsole *con) if (!con) { con = active_console; } - if (con && con->hw_update) { - con->hw_update(con->hw); + if (con && con->hw_ops->gfx_update) { + con->hw_ops->gfx_update(con->hw); } } @@ -239,8 +237,8 @@ void graphic_hw_invalidate(QemuConsole *con) if (!con) { con = active_console; } - if (con && con->hw_invalidate) { - con->hw_invalidate(con->hw); + if (con && con->hw_ops->invalidate) { + con->hw_ops->invalidate(con->hw); } } @@ -310,8 +308,9 @@ void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata) if (!con) { con = active_console; } - if (con && con->hw_text_update) - con->hw_text_update(con->hw, chardata); + if (con && con->hw_ops->text_update) { + con->hw_ops->text_update(con->hw, chardata); + } } static void vga_fill_rect(QemuConsole *con, @@ -1493,9 +1492,7 @@ DisplayState *init_displaystate(void) return display_state; } -QemuConsole *graphic_console_init(graphic_hw_update_ptr update, - graphic_hw_invalidate_ptr invalidate, - graphic_hw_text_update_ptr text_update, +QemuConsole *graphic_console_init(const GraphicHwOps *hw_ops, void *opaque) { int width = 640; @@ -1506,9 +1503,7 @@ QemuConsole *graphic_console_init(graphic_hw_update_ptr update, ds = get_alloc_displaystate(); trace_console_gfx_new(); s = new_console(ds, GRAPHIC_CONSOLE); - s->hw_update = update; - s->hw_invalidate = invalidate; - s->hw_text_update = text_update; + s->hw_ops = hw_ops; s->hw = opaque; s->surface = qemu_create_displaysurface(width, height); @@ -1542,6 +1537,11 @@ static void text_console_update_cursor(void *opaque) qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2); } +static const GraphicHwOps text_console_ops = { + .invalidate = text_console_invalidate, + .text_update = text_console_update, +}; + static void text_console_do_init(CharDriverState *chr, DisplayState *ds) { QemuConsole *s; @@ -1573,8 +1573,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds) s->cursor_timer = qemu_new_timer_ms(rt_clock, text_console_update_cursor, s); - s->hw_invalidate = text_console_invalidate; - s->hw_text_update = text_console_update; + s->hw_ops = &text_console_ops; s->hw = s; /* Set text attribute defaults */ -- cgit v1.2.3 From 0f7b2864d0d0c3ef2801f9214d8c510c80a220d1 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 14 Mar 2013 11:56:16 +0100 Subject: console: gui timer fixes Make gui update rate adaption code in gui_update() actually work. Sprinkle in a tracepoint so you can see the code at work. Remove the update rate adaption code in vnc and make vnc simply use the generic bits instead. Signed-off-by: Gerd Hoffmann --- include/ui/console.h | 9 ++++--- trace-events | 1 + ui/console.c | 34 +++++++++++++++++++++---- ui/sdl.c | 10 ++++---- ui/vnc.c | 71 +++++++++++++++------------------------------------- ui/vnc.h | 2 -- 6 files changed, 60 insertions(+), 67 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index f3e779193c..3cb00180ae 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -21,7 +21,8 @@ #define QEMU_CAPS_LOCK_LED (1 << 2) /* in ms */ -#define GUI_REFRESH_INTERVAL 30 +#define GUI_REFRESH_INTERVAL_DEFAULT 30 +#define GUI_REFRESH_INTERVAL_IDLE 3000 typedef void QEMUPutKBDEvent(void *opaque, int keycode); typedef void QEMUPutLEDEvent(void *opaque, int ledstate); @@ -174,8 +175,7 @@ typedef struct DisplayChangeListenerOps { } DisplayChangeListenerOps; struct DisplayChangeListener { - int idle; - uint64_t gui_timer_interval; + uint64_t update_interval; const DisplayChangeListenerOps *ops; DisplayState *ds; @@ -207,12 +207,13 @@ static inline int is_buffer_shared(DisplaySurface *surface) void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl); +void update_displaychangelistener(DisplayChangeListener *dcl, + uint64_t interval); void unregister_displaychangelistener(DisplayChangeListener *dcl); void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h); void dpy_gfx_replace_surface(QemuConsole *con, DisplaySurface *surface); -void dpy_refresh(DisplayState *s); void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y, int dst_x, int dst_y, int w, int h); void dpy_text_cursor(QemuConsole *con, int x, int y); diff --git a/trace-events b/trace-events index b08627b192..968edb6988 100644 --- a/trace-events +++ b/trace-events @@ -965,6 +965,7 @@ dma_map_wait(void *dbs) "dbs=%p" console_gfx_new(void) "" console_txt_new(int w, int h) "%dx%d" console_select(int nr) "%d" +console_refresh(int interval) "interval %d ms" displaysurface_create(void *display_surface, int w, int h) "surface=%p, %dx%d" displaysurface_create_from(void *display_surface, int w, int h, int bpp, int swap) "surface=%p, %dx%d, bpp %d, bswap %d" displaysurface_free(void *display_surface) "surface=%p" diff --git a/ui/console.c b/ui/console.c index 79a306be8c..5bbc891f25 100644 --- a/ui/console.c +++ b/ui/console.c @@ -157,6 +157,9 @@ struct QemuConsole { struct DisplayState { struct QEMUTimer *gui_timer; + uint64_t last_update; + uint64_t update_interval; + bool refreshing; bool have_gfx; bool have_text; @@ -171,22 +174,32 @@ static int nb_consoles = 0; static void text_console_do_init(CharDriverState *chr, DisplayState *ds); static void dpy_gfx_switch_surface(DisplayState *ds, DisplaySurface *surface); +static void dpy_refresh(DisplayState *s); static void gui_update(void *opaque) { - uint64_t interval = GUI_REFRESH_INTERVAL; + uint64_t interval = GUI_REFRESH_INTERVAL_IDLE; + uint64_t dcl_interval; DisplayState *ds = opaque; DisplayChangeListener *dcl; + ds->refreshing = true; dpy_refresh(ds); + ds->refreshing = false; QLIST_FOREACH(dcl, &ds->listeners, next) { - if (dcl->gui_timer_interval && - dcl->gui_timer_interval < interval) { - interval = dcl->gui_timer_interval; + dcl_interval = dcl->update_interval ? + dcl->update_interval : GUI_REFRESH_INTERVAL_DEFAULT; + if (interval > dcl_interval) { + interval = dcl_interval; } } - qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock)); + if (ds->update_interval != interval) { + ds->update_interval = interval; + trace_console_refresh(interval); + } + ds->last_update = qemu_get_clock_ms(rt_clock); + qemu_mod_timer(ds->gui_timer, ds->last_update + interval); } static void gui_setup_refresh(DisplayState *ds) @@ -1286,6 +1299,17 @@ void register_displaychangelistener(DisplayState *ds, } } +void update_displaychangelistener(DisplayChangeListener *dcl, + uint64_t interval) +{ + DisplayState *ds = dcl->ds; + + dcl->update_interval = interval; + if (!ds->refreshing && ds->update_interval > interval) { + qemu_mod_timer(ds->gui_timer, ds->last_update + interval); + } +} + void unregister_displaychangelistener(DisplayChangeListener *dcl) { DisplayState *ds = dcl->ds; diff --git a/ui/sdl.c b/ui/sdl.c index ede31dc794..97764a683f 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -751,12 +751,12 @@ static void handle_activation(SDL_Event *ev) if (ev->active.state & SDL_APPACTIVE) { if (ev->active.gain) { /* Back to default interval */ - dcl->gui_timer_interval = 0; - dcl->idle = 0; + update_displaychangelistener(dcl, GUI_REFRESH_INTERVAL_DEFAULT); } else { - /* Sleeping interval */ - dcl->gui_timer_interval = 500; - dcl->idle = 1; + /* Sleeping interval. Not using the long default here as + * sdl_refresh does not only update the guest screen, but + * also checks for gui events. */ + update_displaychangelistener(dcl, 500); } } } diff --git a/ui/vnc.c b/ui/vnc.c index bc787ccb77..75ad67fd33 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -34,9 +34,9 @@ #include "qmp-commands.h" #include "qemu/osdep.h" -#define VNC_REFRESH_INTERVAL_BASE 30 +#define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT #define VNC_REFRESH_INTERVAL_INC 50 -#define VNC_REFRESH_INTERVAL_MAX 2000 +#define VNC_REFRESH_INTERVAL_MAX GUI_REFRESH_INTERVAL_IDLE static const struct timeval VNC_REFRESH_STATS = { 0, 500000 }; static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 }; @@ -419,14 +419,12 @@ out_error: static int vnc_update_client(VncState *vs, int has_dirty); static int vnc_update_client_sync(VncState *vs, int has_dirty); static void vnc_disconnect_start(VncState *vs); -static void vnc_init_timer(VncDisplay *vd); -static void vnc_remove_timer(VncDisplay *vd); static void vnc_colordepth(VncState *vs); static void framebuffer_update_request(VncState *vs, int incremental, int x_position, int y_position, int w, int h); -static void vnc_refresh(void *opaque); +static void vnc_refresh(DisplayChangeListener *dcl); static int vnc_refresh_server_surface(VncDisplay *vd); static void vnc_dpy_update(DisplayChangeListener *dcl, @@ -1064,11 +1062,6 @@ void vnc_disconnect_finish(VncState *vs) qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier); } - if (QTAILQ_EMPTY(&vs->vd->clients)) { - vs->vd->dcl.idle = 1; - } - - vnc_remove_timer(vs->vd); if (vs->vd->lock_key_sync) qemu_remove_led_event_handler(vs->led); vnc_unlock_output(vs); @@ -2013,9 +2006,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) VncDisplay *vd = vs->vd; if (data[0] > 3) { - vd->timer_interval = VNC_REFRESH_INTERVAL_BASE; - if (!qemu_timer_expired(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval)) - qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval); + update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE); } switch (data[0]) { @@ -2647,18 +2638,16 @@ static int vnc_refresh_server_surface(VncDisplay *vd) return has_dirty; } -static void vnc_refresh(void *opaque) +static void vnc_refresh(DisplayChangeListener *dcl) { - VncDisplay *vd = opaque; + VncDisplay *vd = container_of(dcl, VncDisplay, dcl); VncState *vs, *vn; int has_dirty, rects = 0; graphic_hw_update(NULL); if (vnc_trylock_display(vd)) { - vd->timer_interval = VNC_REFRESH_INTERVAL_BASE; - qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) + - vd->timer_interval); + update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE); return; } @@ -2670,39 +2659,21 @@ static void vnc_refresh(void *opaque) /* vs might be free()ed here */ } - /* vd->timer could be NULL now if the last client disconnected, - * in this case don't update the timer */ - if (vd->timer == NULL) + if (QTAILQ_EMPTY(&vd->clients)) { + update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_MAX); return; + } if (has_dirty && rects) { - vd->timer_interval /= 2; - if (vd->timer_interval < VNC_REFRESH_INTERVAL_BASE) - vd->timer_interval = VNC_REFRESH_INTERVAL_BASE; + vd->dcl.update_interval /= 2; + if (vd->dcl.update_interval < VNC_REFRESH_INTERVAL_BASE) { + vd->dcl.update_interval = VNC_REFRESH_INTERVAL_BASE; + } } else { - vd->timer_interval += VNC_REFRESH_INTERVAL_INC; - if (vd->timer_interval > VNC_REFRESH_INTERVAL_MAX) - vd->timer_interval = VNC_REFRESH_INTERVAL_MAX; - } - qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval); -} - -static void vnc_init_timer(VncDisplay *vd) -{ - vd->timer_interval = VNC_REFRESH_INTERVAL_BASE; - if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) { - vd->timer = qemu_new_timer_ms(rt_clock, vnc_refresh, vd); - graphic_hw_update(NULL); - vnc_refresh(vd); - } -} - -static void vnc_remove_timer(VncDisplay *vd) -{ - if (vd->timer != NULL && QTAILQ_EMPTY(&vd->clients)) { - qemu_del_timer(vd->timer); - qemu_free_timer(vd->timer); - vd->timer = NULL; + vd->dcl.update_interval += VNC_REFRESH_INTERVAL_INC; + if (vd->dcl.update_interval > VNC_REFRESH_INTERVAL_MAX) { + vd->dcl.update_interval = VNC_REFRESH_INTERVAL_MAX; + } } } @@ -2731,7 +2702,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket) } VNC_DEBUG("New client on socket %d\n", csock); - vd->dcl.idle = 0; + update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE); qemu_set_nonblock(vs->csock); #ifdef CONFIG_VNC_WS if (websocket) { @@ -2787,8 +2758,6 @@ void vnc_init_state(VncState *vs) vs->mouse_mode_notifier.notify = check_pointer_type_change; qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier); - vnc_init_timer(vd); - /* vs might be free()ed here */ } @@ -2829,6 +2798,7 @@ static void vnc_listen_websocket_read(void *opaque) static const DisplayChangeListenerOps dcl_ops = { .dpy_name = "vnc", + .dpy_refresh = vnc_refresh, .dpy_gfx_copy = vnc_dpy_copy, .dpy_gfx_update = vnc_dpy_update, .dpy_gfx_switch = vnc_dpy_switch, @@ -2840,7 +2810,6 @@ void vnc_display_init(DisplayState *ds) { VncDisplay *vs = g_malloc0(sizeof(*vs)); - vs->dcl.idle = 1; vnc_display = vs; vs->lsock = -1; diff --git a/ui/vnc.h b/ui/vnc.h index 58e002eed3..ad1dec2894 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -142,8 +142,6 @@ struct VncDisplay QTAILQ_HEAD(, VncState) clients; int num_exclusive; VncSharePolicy share_policy; - QEMUTimer *timer; - int timer_interval; int lsock; #ifdef CONFIG_VNC_WS int lwebsock; -- cgit v1.2.3 From dea1b0bdd8b0bb9d76a012fd0f234ba1768a4a93 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 19 Mar 2013 15:01:02 +0100 Subject: xen: re-enable refresh interval reporting for xenfb xenfb informs the guest about the gui refresh interval so it can avoid pointless work. That logic was temporarely disabled for the DisplayState reorganization. Restore it now, with a proper interface for it. Signed-off-by: Gerd Hoffmann --- hw/display/xenfb.c | 56 ++++++++++++++++------------------------------------ include/ui/console.h | 1 + ui/console.c | 6 ++++++ 3 files changed, 24 insertions(+), 39 deletions(-) diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c index 8d327f138e..f2eb89fa7f 100644 --- a/hw/display/xenfb.c +++ b/hw/display/xenfb.c @@ -78,7 +78,6 @@ struct XenFB { void *pixels; int fbpages; int feature_update; - int refresh_period; int bug_trigger; int have_console; int do_resize; @@ -646,7 +645,7 @@ static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h) dpy_gfx_update(xenfb->c.con, x, y, w, h); } -#if 0 /* def XENFB_TYPE_REFRESH_PERIOD */ +#ifdef XENFB_TYPE_REFRESH_PERIOD static int xenfb_queue_full(struct XenFB *xenfb) { struct xenfb_page *page = xenfb->c.page; @@ -704,39 +703,7 @@ static void xenfb_update(void *opaque) if (xenfb->c.xendev.be_state != XenbusStateConnected) return; - if (xenfb->feature_update) { -#if 0 /* XENFB_TYPE_REFRESH_PERIOD */ - struct DisplayChangeListener *l; - int period = 99999999; - int idle = 1; - - if (xenfb_queue_full(xenfb)) - return; - - QLIST_FOREACH(l, &xenfb->c.ds->listeners, next) { - if (l->idle) - continue; - idle = 0; - if (!l->gui_timer_interval) { - if (period > GUI_REFRESH_INTERVAL) - period = GUI_REFRESH_INTERVAL; - } else { - if (period > l->gui_timer_interval) - period = l->gui_timer_interval; - } - } - if (idle) - period = XENFB_NO_REFRESH; - - if (xenfb->refresh_period != period) { - xenfb_send_refresh_period(xenfb, period); - xenfb->refresh_period = period; - xen_be_printf(&xenfb->c.xendev, 1, "refresh period: %d\n", period); - } -#else - ; /* nothing */ -#endif - } else { + if (!xenfb->feature_update) { /* we don't get update notifications, thus use the * sledge hammer approach ... */ xenfb->up_fullscreen = 1; @@ -785,6 +752,20 @@ static void xenfb_update(void *opaque) xenfb->up_fullscreen = 0; } +static void xenfb_update_interval(void *opaque, uint64_t interval) +{ + struct XenFB *xenfb = opaque; + + if (xenfb->feature_update) { +#ifdef XENFB_TYPE_REFRESH_PERIOD + if (xenfb_queue_full(xenfb)) { + return; + } + xenfb_send_refresh_period(xenfb, interval); +#endif + } +} + /* QEMU display state changed, so refresh the framebuffer copy */ static void xenfb_invalidate(void *opaque) { @@ -858,10 +839,6 @@ static void xenfb_handle_events(struct XenFB *xenfb) static int fb_init(struct XenDevice *xendev) { - struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev); - - fb->refresh_period = -1; - #ifdef XENFB_TYPE_RESIZE xenstore_write_be_int(xendev, "feature-resize", 1); #endif @@ -980,6 +957,7 @@ struct XenDevOps xen_framebuffer_ops = { static const GraphicHwOps xenfb_ops = { .invalidate = xenfb_invalidate, .gfx_update = xenfb_update, + .update_interval = xenfb_update_interval, }; /* diff --git a/include/ui/console.h b/include/ui/console.h index 3cb00180ae..800f458b02 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -272,6 +272,7 @@ typedef struct GraphicHwOps { void (*invalidate)(void *opaque); void (*gfx_update)(void *opaque); void (*text_update)(void *opaque, console_ch_t *text); + void (*update_interval)(void *opaque, uint64_t interval); } GraphicHwOps; QemuConsole *graphic_console_init(const GraphicHwOps *ops, diff --git a/ui/console.c b/ui/console.c index 5bbc891f25..43ff80b451 100644 --- a/ui/console.c +++ b/ui/console.c @@ -182,6 +182,7 @@ static void gui_update(void *opaque) uint64_t dcl_interval; DisplayState *ds = opaque; DisplayChangeListener *dcl; + int i; ds->refreshing = true; dpy_refresh(ds); @@ -196,6 +197,11 @@ static void gui_update(void *opaque) } if (ds->update_interval != interval) { ds->update_interval = interval; + for (i = 0; i < nb_consoles; i++) { + if (consoles[i]->hw_ops->update_interval) { + consoles[i]->hw_ops->update_interval(consoles[i]->hw, interval); + } + } trace_console_refresh(interval); } ds->last_update = qemu_get_clock_ms(rt_clock); -- cgit v1.2.3 From 81c0d5a66295024d0a42e3d28efcd102a32f93c3 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 14 Mar 2013 14:27:08 +0100 Subject: console: add qemu_console_is_* Signed-off-by: Gerd Hoffmann --- include/ui/console.h | 6 ++++-- ui/console.c | 59 +++++++++++++++++++++++++++++----------------------- ui/curses.c | 7 ++++--- ui/sdl.c | 24 ++++++++++----------- ui/vnc.c | 6 +++--- 5 files changed, 56 insertions(+), 46 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 800f458b02..bcd013900a 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -282,8 +282,10 @@ void graphic_hw_update(QemuConsole *con); void graphic_hw_invalidate(QemuConsole *con); void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata); -int is_graphic_console(void); -int is_fixedsize_console(void); +bool qemu_console_is_visible(QemuConsole *con); +bool qemu_console_is_graphic(QemuConsole *con); +bool qemu_console_is_fixedsize(QemuConsole *con); + void text_consoles_set_display(DisplayState *ds); void console_select(unsigned int index); void console_color_init(DisplayState *ds); diff --git a/ui/console.c b/ui/console.c index 43ff80b451..214cdba489 100644 --- a/ui/console.c +++ b/ui/console.c @@ -515,7 +515,7 @@ static void update_xy(QemuConsole *s, int x, int y) TextCell *c; int y1, y2; - if (s != active_console) { + if (!qemu_console_is_visible(s)) { return; } @@ -543,7 +543,7 @@ static void console_show_cursor(QemuConsole *s, int show) int y, y1; int x = s->x; - if (s != active_console) { + if (!qemu_console_is_visible(s)) { return; } @@ -579,8 +579,9 @@ static void console_refresh(QemuConsole *s) TextCell *c; int x, y, y1; - if (s != active_console) + if (!qemu_console_is_visible(s)) { return; + } if (s->ds->have_text) { s->text_x[0] = 0; @@ -611,15 +612,10 @@ static void console_refresh(QemuConsole *s) } } -static void console_scroll(int ydelta) +static void console_scroll(QemuConsole *s, int ydelta) { - QemuConsole *s; int i, y1; - s = active_console; - if (!s || (s->console_type == GRAPHIC_CONSOLE)) - return; - if (ydelta > 0) { for(i = 0; i < ydelta; i++) { if (s->y_displayed == s->y_base) @@ -669,7 +665,7 @@ static void console_put_lf(QemuConsole *s) c->t_attrib = s->t_attrib_default; c++; } - if (s == active_console && s->y_displayed == s->y_base) { + if (qemu_console_is_visible(s) && s->y_displayed == s->y_base) { if (s->ds->have_text) { s->text_x[0] = 0; s->text_y[0] = 0; @@ -1112,16 +1108,16 @@ void kbd_put_keysym(int keysym) switch(keysym) { case QEMU_KEY_CTRL_UP: - console_scroll(-1); + console_scroll(s, -1); break; case QEMU_KEY_CTRL_DOWN: - console_scroll(1); + console_scroll(s, 1); break; case QEMU_KEY_CTRL_PAGEUP: - console_scroll(-10); + console_scroll(s, -10); break; case QEMU_KEY_CTRL_PAGEDOWN: - console_scroll(10); + console_scroll(s, 10); break; default: /* convert the QEMU keysym to VT100 key string */ @@ -1338,7 +1334,7 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h) w = MIN(w, width - x); h = MIN(h, height - y); - if (con != active_console) { + if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { @@ -1367,7 +1363,7 @@ void dpy_gfx_replace_surface(QemuConsole *con, DisplaySurface *old_surface = con->surface; con->surface = surface; - if (con == active_console) { + if (qemu_console_is_visible(con)) { dpy_gfx_switch_surface(s, surface); } qemu_free_displaysurface(old_surface); @@ -1389,7 +1385,7 @@ void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y, DisplayState *s = con->ds; struct DisplayChangeListener *dcl; - if (con != active_console) { + if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { @@ -1406,7 +1402,7 @@ void dpy_text_cursor(QemuConsole *con, int x, int y) DisplayState *s = con->ds; struct DisplayChangeListener *dcl; - if (con != active_console) { + if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { @@ -1421,7 +1417,7 @@ void dpy_text_update(QemuConsole *con, int x, int y, int w, int h) DisplayState *s = con->ds; struct DisplayChangeListener *dcl; - if (con != active_console) { + if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { @@ -1436,7 +1432,7 @@ void dpy_text_resize(QemuConsole *con, int w, int h) DisplayState *s = con->ds; struct DisplayChangeListener *dcl; - if (con != active_console) { + if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { @@ -1451,7 +1447,7 @@ void dpy_mouse_set(QemuConsole *con, int x, int y, int on) DisplayState *s = con->ds; struct DisplayChangeListener *dcl; - if (con != active_console) { + if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { @@ -1466,7 +1462,7 @@ void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor) DisplayState *s = con->ds; struct DisplayChangeListener *dcl; - if (con != active_console) { + if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { @@ -1540,14 +1536,25 @@ QemuConsole *graphic_console_init(const GraphicHwOps *hw_ops, return s; } -int is_graphic_console(void) +bool qemu_console_is_visible(QemuConsole *con) { - return active_console && active_console->console_type == GRAPHIC_CONSOLE; + return con == active_console; } -int is_fixedsize_console(void) +bool qemu_console_is_graphic(QemuConsole *con) { - return active_console && active_console->console_type != TEXT_CONSOLE; + if (con == NULL) { + con = active_console; + } + return con && (con->console_type == GRAPHIC_CONSOLE); +} + +bool qemu_console_is_fixedsize(QemuConsole *con) +{ + if (con == NULL) { + con = active_console; + } + return con && (con->console_type != TEXT_CONSOLE); } static void text_console_set_echo(CharDriverState *chr, bool echo) diff --git a/ui/curses.c b/ui/curses.c index ed9e65c7f0..a85a7da316 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -56,7 +56,7 @@ static void curses_update(DisplayChangeListener *dcl, static void curses_calc_pad(void) { - if (is_fixedsize_console()) { + if (qemu_console_is_fixedsize(NULL)) { width = gwidth; height = gheight; } else { @@ -143,8 +143,9 @@ static void curses_cursor_position(DisplayChangeListener *dcl, curs_set(1); /* it seems that curs_set(1) must always be called before * curs_set(2) for the latter to have effect */ - if (!is_graphic_console()) + if (!qemu_console_is_graphic(NULL)) { curs_set(2); + } return; } } @@ -252,7 +253,7 @@ static void curses_refresh(DisplayChangeListener *dcl) if (keycode == -1) continue; - if (is_graphic_console()) { + if (qemu_console_is_graphic(NULL)) { /* since terminals don't know about key press and release * events, we need to emit both for each key received */ if (keycode & SHIFT) diff --git a/ui/sdl.c b/ui/sdl.c index 97764a683f..c9f2928f00 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -358,7 +358,7 @@ static void sdl_show_cursor(void) if (!cursor_hide) return; - if (!kbd_mouse_is_absolute() || !is_graphic_console()) { + if (!kbd_mouse_is_absolute() || !qemu_console_is_graphic(NULL)) { SDL_ShowCursor(1); if (guest_cursor && (gui_grab || kbd_mouse_is_absolute() || absolute_enabled)) @@ -413,7 +413,7 @@ static void sdl_mouse_mode_change(Notifier *notify, void *data) if (kbd_mouse_is_absolute()) { if (!absolute_enabled) { absolute_enabled = 1; - if (is_graphic_console()) { + if (qemu_console_is_graphic(NULL)) { absolute_mouse_grab(); } } @@ -488,7 +488,7 @@ static void toggle_full_screen(void) } else { do_sdl_resize(width, height, 0); } - if (!gui_saved_grab || !is_graphic_console()) { + if (!gui_saved_grab || !qemu_console_is_graphic(NULL)) { sdl_grab_end(); } } @@ -535,7 +535,7 @@ static void handle_keydown(SDL_Event *ev) if (gui_fullscreen) { break; } - if (!is_graphic_console()) { + if (!qemu_console_is_graphic(NULL)) { /* release grab if going to a text console */ if (gui_grab) { sdl_grab_end(); @@ -563,7 +563,7 @@ static void handle_keydown(SDL_Event *ev) default: break; } - } else if (!is_graphic_console()) { + } else if (!qemu_console_is_graphic(NULL)) { int keysym = 0; if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) { @@ -637,7 +637,7 @@ static void handle_keydown(SDL_Event *ev) kbd_put_keysym(ev->key.keysym.unicode); } } - if (is_graphic_console() && !gui_keysym) { + if (qemu_console_is_graphic(NULL) && !gui_keysym) { sdl_process_key(&ev->key); } } @@ -656,7 +656,7 @@ static void handle_keyup(SDL_Event *ev) if (gui_keysym == 0) { /* exit/enter grab if pressing Ctrl-Alt */ if (!gui_grab) { - if (is_graphic_console()) { + if (qemu_console_is_graphic(NULL)) { sdl_grab_start(); } } else if (!gui_fullscreen) { @@ -669,7 +669,7 @@ static void handle_keyup(SDL_Event *ev) } gui_keysym = 0; } - if (is_graphic_console() && !gui_keysym) { + if (qemu_console_is_graphic(NULL) && !gui_keysym) { sdl_process_key(&ev->key); } } @@ -678,7 +678,7 @@ static void handle_mousemotion(SDL_Event *ev) { int max_x, max_y; - if (is_graphic_console() && + if (qemu_console_is_graphic(NULL) && (kbd_mouse_is_absolute() || absolute_enabled)) { max_x = real_screen->w - 1; max_y = real_screen->h - 1; @@ -704,7 +704,7 @@ static void handle_mousebutton(SDL_Event *ev) SDL_MouseButtonEvent *bev; int dz; - if (!is_graphic_console()) { + if (!qemu_console_is_graphic(NULL)) { return; } @@ -744,7 +744,7 @@ static void handle_activation(SDL_Event *ev) sdl_grab_end(); } #endif - if (!gui_grab && ev->active.gain && is_graphic_console() && + if (!gui_grab && ev->active.gain && qemu_console_is_graphic(NULL) && (kbd_mouse_is_absolute() || absolute_enabled)) { absolute_mouse_grab(); } @@ -771,7 +771,7 @@ static void sdl_refresh(DisplayChangeListener *dcl) } graphic_hw_update(NULL); - SDL_EnableUNICODE(!is_graphic_console()); + SDL_EnableUNICODE(!qemu_console_is_graphic(NULL)); while (SDL_PollEvent(ev)) { switch (ev->type) { diff --git a/ui/vnc.c b/ui/vnc.c index 75ad67fd33..8ee66b7d3b 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1609,7 +1609,7 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym) } } - if (is_graphic_console()) { + if (qemu_console_is_graphic(NULL)) { if (keycode & SCANCODE_GREY) kbd_put_keycode(SCANCODE_EMUL0); if (down) @@ -1728,7 +1728,7 @@ static void vnc_release_modifiers(VncState *vs) }; int i, keycode; - if (!is_graphic_console()) { + if (!qemu_console_is_graphic(NULL)) { return; } for (i = 0; i < ARRAY_SIZE(keycodes); i++) { @@ -1748,7 +1748,7 @@ static void key_event(VncState *vs, int down, uint32_t sym) int keycode; int lsym = sym; - if (lsym >= 'A' && lsym <= 'Z' && is_graphic_console()) { + if (lsym >= 'A' && lsym <= 'Z' && qemu_console_is_graphic(NULL)) { lsym = lsym - 'A' + 'a'; } -- cgit v1.2.3 From 284d1c6b3bf4ece6278f4b9831c7192e3777290c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 15 Mar 2013 15:45:54 +0100 Subject: console: allow pinning displaychangelisteners to consoles DisplayChangeListener gets a new QemuConsole field, which can be set to non-NULL before registering. This will pin the QemuConsole, so that particular DisplayChangeListener will not follow console switches. spice+gtk (which don't support text console input anyway) are switched over to be pinned to console 0, which usually is the graphical display. Signed-off-by: Gerd Hoffmann --- hw/display/qxl.c | 2 +- include/ui/console.h | 2 + include/ui/spice-display.h | 1 - ui/console.c | 103 ++++++++++++++++++++++++++++++++------------- ui/gtk.c | 3 +- ui/spice-display.c | 11 ++--- 6 files changed, 84 insertions(+), 38 deletions(-) diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 8721d44d74..bbc6f56a0d 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -2061,7 +2061,6 @@ static int qxl_init_primary(PCIDevice *dev) portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0); vga->con = graphic_console_init(&qxl_ops, qxl); - qxl->ssd.con = vga->con, qemu_spice_display_init_common(&qxl->ssd); rc = qxl_init_common(qxl); @@ -2070,6 +2069,7 @@ static int qxl_init_primary(PCIDevice *dev) } qxl->ssd.dcl.ops = &display_listener_ops; + qxl->ssd.dcl.con = vga->con; ds = qemu_console_displaystate(vga->con); register_displaychangelistener(ds, &qxl->ssd.dcl); return rc; diff --git a/include/ui/console.h b/include/ui/console.h index bcd013900a..e591d742d4 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -178,6 +178,7 @@ struct DisplayChangeListener { uint64_t update_interval; const DisplayChangeListenerOps *ops; DisplayState *ds; + QemuConsole *con; QLIST_ENTRY(DisplayChangeListener) next; }; @@ -282,6 +283,7 @@ void graphic_hw_update(QemuConsole *con); void graphic_hw_invalidate(QemuConsole *con); void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata); +QemuConsole *qemu_console_lookup_by_index(unsigned int index); bool qemu_console_is_visible(QemuConsole *con); bool qemu_console_is_graphic(QemuConsole *con); bool qemu_console_is_fixedsize(QemuConsole *con); diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index 7a20fc43ff..a46bc80019 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -71,7 +71,6 @@ typedef struct SimpleSpiceDisplay SimpleSpiceDisplay; typedef struct SimpleSpiceUpdate SimpleSpiceUpdate; struct SimpleSpiceDisplay { - QemuConsole *con; DisplaySurface *ds; DisplayChangeListener dcl; void *buf; diff --git a/ui/console.c b/ui/console.c index 214cdba489..4f9219e38d 100644 --- a/ui/console.c +++ b/ui/console.c @@ -117,6 +117,7 @@ struct QemuConsole { console_type_t console_type; DisplayState *ds; DisplaySurface *surface; + int dcls; /* Graphic console state. */ const GraphicHwOps *hw_ops; @@ -172,8 +173,6 @@ static QemuConsole *consoles[MAX_CONSOLES]; static int nb_consoles = 0; static void text_console_do_init(CharDriverState *chr, DisplayState *ds); -static void dpy_gfx_switch_surface(DisplayState *ds, - DisplaySurface *surface); static void dpy_refresh(DisplayState *s); static void gui_update(void *opaque) @@ -309,7 +308,7 @@ write_err: void qmp_screendump(const char *filename, Error **errp) { - QemuConsole *con = consoles[0]; + QemuConsole *con = qemu_console_lookup_by_index(0); DisplaySurface *surface; if (con == NULL) { @@ -1022,13 +1021,14 @@ static void console_putchar(QemuConsole *s, int ch) void console_select(unsigned int index) { + DisplayChangeListener *dcl; QemuConsole *s; if (index >= MAX_CONSOLES) return; trace_console_select(index); - s = consoles[index]; + s = qemu_console_lookup_by_index(index); if (s) { DisplayState *ds = s->ds; @@ -1037,7 +1037,14 @@ void console_select(unsigned int index) } active_console = s; if (ds->have_gfx) { - dpy_gfx_switch_surface(ds, s->surface); + QLIST_FOREACH(dcl, &ds->listeners, next) { + if (dcl->con != NULL) { + continue; + } + if (dcl->ops->dpy_gfx_switch) { + dcl->ops->dpy_gfx_switch(dcl, s->surface); + } + } dpy_gfx_update(s, 0, 0, surface_width(s->surface), surface_height(s->surface)); } @@ -1292,12 +1299,20 @@ void qemu_free_displaysurface(DisplaySurface *surface) void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) { + QemuConsole *con; + trace_displaychangelistener_register(dcl, dcl->ops->dpy_name); dcl->ds = ds; QLIST_INSERT_HEAD(&ds->listeners, dcl, next); gui_setup_refresh(ds); - if (dcl->ops->dpy_gfx_switch && active_console) { - dcl->ops->dpy_gfx_switch(dcl, active_console->surface); + if (dcl->con) { + dcl->con->dcls++; + con = dcl->con; + } else { + con = active_console; + } + if (dcl->ops->dpy_gfx_switch && con) { + dcl->ops->dpy_gfx_switch(dcl, con->surface); } } @@ -1316,6 +1331,9 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl) { DisplayState *ds = dcl->ds; trace_displaychangelistener_unregister(dcl, dcl->ops->dpy_name); + if (dcl->con) { + dcl->con->dcls--; + } QLIST_REMOVE(dcl, next); gui_setup_refresh(ds); } @@ -1323,7 +1341,7 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl) void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h) { DisplayState *s = con->ds; - struct DisplayChangeListener *dcl; + DisplayChangeListener *dcl; int width = surface_width(con->surface); int height = surface_height(con->surface); @@ -1338,40 +1356,38 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h) return; } QLIST_FOREACH(dcl, &s->listeners, next) { + if (con != (dcl->con ? dcl->con : active_console)) { + continue; + } if (dcl->ops->dpy_gfx_update) { dcl->ops->dpy_gfx_update(dcl, x, y, w, h); } } } -static void dpy_gfx_switch_surface(DisplayState *ds, - DisplaySurface *surface) -{ - struct DisplayChangeListener *dcl; - - QLIST_FOREACH(dcl, &ds->listeners, next) { - if (dcl->ops->dpy_gfx_switch) { - dcl->ops->dpy_gfx_switch(dcl, surface); - } - } -} - void dpy_gfx_replace_surface(QemuConsole *con, DisplaySurface *surface) { DisplayState *s = con->ds; DisplaySurface *old_surface = con->surface; + DisplayChangeListener *dcl; con->surface = surface; - if (qemu_console_is_visible(con)) { - dpy_gfx_switch_surface(s, surface); + QLIST_FOREACH(dcl, &s->listeners, next) { + if (con != (dcl->con ? dcl->con : active_console)) { + continue; + } + if (dcl->ops->dpy_gfx_switch) { + dcl->ops->dpy_gfx_switch(dcl, surface); + } } qemu_free_displaysurface(old_surface); } void dpy_refresh(DisplayState *s) { - struct DisplayChangeListener *dcl; + DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_refresh) { dcl->ops->dpy_refresh(dcl); @@ -1383,12 +1399,15 @@ void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { DisplayState *s = con->ds; - struct DisplayChangeListener *dcl; + DisplayChangeListener *dcl; if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { + if (con != (dcl->con ? dcl->con : active_console)) { + continue; + } if (dcl->ops->dpy_gfx_copy) { dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h); } else { /* TODO */ @@ -1400,12 +1419,15 @@ void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y, void dpy_text_cursor(QemuConsole *con, int x, int y) { DisplayState *s = con->ds; - struct DisplayChangeListener *dcl; + DisplayChangeListener *dcl; if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { + if (con != (dcl->con ? dcl->con : active_console)) { + continue; + } if (dcl->ops->dpy_text_cursor) { dcl->ops->dpy_text_cursor(dcl, x, y); } @@ -1415,12 +1437,15 @@ void dpy_text_cursor(QemuConsole *con, int x, int y) void dpy_text_update(QemuConsole *con, int x, int y, int w, int h) { DisplayState *s = con->ds; - struct DisplayChangeListener *dcl; + DisplayChangeListener *dcl; if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { + if (con != (dcl->con ? dcl->con : active_console)) { + continue; + } if (dcl->ops->dpy_text_update) { dcl->ops->dpy_text_update(dcl, x, y, w, h); } @@ -1436,6 +1461,9 @@ void dpy_text_resize(QemuConsole *con, int w, int h) return; } QLIST_FOREACH(dcl, &s->listeners, next) { + if (con != (dcl->con ? dcl->con : active_console)) { + continue; + } if (dcl->ops->dpy_text_resize) { dcl->ops->dpy_text_resize(dcl, w, h); } @@ -1445,12 +1473,15 @@ void dpy_text_resize(QemuConsole *con, int w, int h) void dpy_mouse_set(QemuConsole *con, int x, int y, int on) { DisplayState *s = con->ds; - struct DisplayChangeListener *dcl; + DisplayChangeListener *dcl; if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { + if (con != (dcl->con ? dcl->con : active_console)) { + continue; + } if (dcl->ops->dpy_mouse_set) { dcl->ops->dpy_mouse_set(dcl, x, y, on); } @@ -1460,12 +1491,15 @@ void dpy_mouse_set(QemuConsole *con, int x, int y, int on) void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor) { DisplayState *s = con->ds; - struct DisplayChangeListener *dcl; + DisplayChangeListener *dcl; if (!qemu_console_is_visible(con)) { return; } QLIST_FOREACH(dcl, &s->listeners, next) { + if (con != (dcl->con ? dcl->con : active_console)) { + continue; + } if (dcl->ops->dpy_cursor_define) { dcl->ops->dpy_cursor_define(dcl, cursor); } @@ -1475,7 +1509,8 @@ void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor) bool dpy_cursor_define_supported(QemuConsole *con) { DisplayState *s = con->ds; - struct DisplayChangeListener *dcl; + DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_cursor_define) { return true; @@ -1536,9 +1571,17 @@ QemuConsole *graphic_console_init(const GraphicHwOps *hw_ops, return s; } +QemuConsole *qemu_console_lookup_by_index(unsigned int index) +{ + if (index >= MAX_CONSOLES) { + return NULL; + } + return consoles[index]; +} + bool qemu_console_is_visible(QemuConsole *con) { - return con == active_console; + return (con == active_console) || (con->dcls > 0); } bool qemu_console_is_graphic(QemuConsole *con) diff --git a/ui/gtk.c b/ui/gtk.c index d0e444cece..e9ebbd3cbf 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -327,7 +327,7 @@ static void gd_update(DisplayChangeListener *dcl, static void gd_refresh(DisplayChangeListener *dcl) { - graphic_hw_update(NULL); + graphic_hw_update(dcl->con); } static void gd_switch(DisplayChangeListener *dcl, @@ -1368,6 +1368,7 @@ void gtk_display_init(DisplayState *ds) gtk_init(NULL, NULL); s->dcl.ops = &dcl_ops; + s->dcl.con = qemu_console_lookup_by_index(0); s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); #if GTK_CHECK_VERSION(3, 2, 0) diff --git a/ui/spice-display.c b/ui/spice-display.c index 2c0167488b..53c19bea0f 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -398,14 +398,14 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd, void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd) { if (ssd->cursor) { - assert(ssd->con); - dpy_cursor_define(ssd->con, ssd->cursor); + assert(ssd->dcl.con); + dpy_cursor_define(ssd->dcl.con, ssd->cursor); cursor_put(ssd->cursor); ssd->cursor = NULL; } if (ssd->mouse_x != -1 && ssd->mouse_y != -1) { - assert(ssd->con); - dpy_mouse_set(ssd->con, ssd->mouse_x, ssd->mouse_y, 1); + assert(ssd->dcl.con); + dpy_mouse_set(ssd->dcl.con, ssd->mouse_x, ssd->mouse_y, 1); ssd->mouse_x = -1; ssd->mouse_y = -1; } @@ -414,7 +414,7 @@ void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd) void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) { dprint(3, "%s:\n", __func__); - graphic_hw_update(ssd->con); + graphic_hw_update(ssd->dcl.con); qemu_mutex_lock(&ssd->lock); if (QTAILQ_EMPTY(&ssd->updates) && ssd->ds) { @@ -624,6 +624,7 @@ void qemu_spice_display_init(DisplayState *ds) qemu_spice_create_host_memslot(ssd); ssd->dcl.ops = &display_listener_ops; + ssd->dcl.con = qemu_console_lookup_by_index(0); register_displaychangelistener(ds, &ssd->dcl); qemu_spice_create_host_primary(ssd); -- cgit v1.2.3 From 9697f5d2d38e5dd1e64e8e0d64436e6d44e7b1fe Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 20 Mar 2013 09:11:41 +0100 Subject: gtk: custom cursor support Makes gtk ui play nicely with qxl (and vmware_svga) as you can actually see your pointer now ;) Signed-off-by: Gerd Hoffmann --- ui/gtk.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/ui/gtk.c b/ui/gtk.c index e9ebbd3cbf..d48529a34f 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -330,6 +330,37 @@ static void gd_refresh(DisplayChangeListener *dcl) graphic_hw_update(dcl->con); } +static void gd_mouse_set(DisplayChangeListener *dcl, + int x, int y, int visible) +{ + GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); + gint x_root, y_root; + + gdk_window_get_root_coords(s->drawing_area->window, + x, y, &x_root, &y_root); + gdk_display_warp_pointer(gtk_widget_get_display(s->drawing_area), + gtk_widget_get_screen(s->drawing_area), + x_root, y_root); +} + +static void gd_cursor_define(DisplayChangeListener *dcl, + QEMUCursor *c) +{ + GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); + GdkPixbuf *pixbuf; + GdkCursor *cursor; + + pixbuf = gdk_pixbuf_new_from_data((guchar *)(c->data), + GDK_COLORSPACE_RGB, true, 8, + c->width, c->height, c->width * 4, + NULL, NULL); + cursor = gdk_cursor_new_from_pixbuf(gtk_widget_get_display(s->drawing_area), + pixbuf, c->hot_x, c->hot_y); + gdk_window_set_cursor(s->drawing_area->window, cursor); + g_object_unref(pixbuf); + g_object_unref(cursor); +} + static void gd_switch(DisplayChangeListener *dcl, DisplaySurface *surface) { @@ -1358,6 +1389,8 @@ static const DisplayChangeListenerOps dcl_ops = { .dpy_gfx_update = gd_update, .dpy_gfx_switch = gd_switch, .dpy_refresh = gd_refresh, + .dpy_mouse_set = gd_mouse_set, + .dpy_cursor_define = gd_cursor_define, }; void gtk_display_init(DisplayState *ds) -- cgit v1.2.3 From bfe528b9b99d52693a55f2b803039d68a97bcfb2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 19 Mar 2013 16:59:58 +0100 Subject: qxl: register QemuConsole for secondary cards Hook secondary qxl cards properly into the qemu console subsystem. Signed-off-by: Gerd Hoffmann --- hw/display/qxl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/display/qxl.c b/hw/display/qxl.c index bbc6f56a0d..437f8d0eee 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1769,7 +1769,10 @@ static void qxl_hw_invalidate(void *opaque) PCIQXLDevice *qxl = opaque; VGACommonState *vga = &qxl->vga; - vga->hw_ops->invalidate(vga); + if (qxl->mode == QXL_MODE_VGA) { + vga->hw_ops->invalidate(vga); + return; + } } static void qxl_hw_text_update(void *opaque, console_ch_t *chardata) @@ -2085,6 +2088,7 @@ static int qxl_init_secondary(PCIDevice *dev) memory_region_init_ram(&qxl->vga.vram, "qxl.vgavram", qxl->vga.vram_size); vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev); qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram); + qxl->vga.con = graphic_console_init(&qxl_ops, qxl); return qxl_init_common(qxl); } -- cgit v1.2.3