Merge remote-tracking branch 'kraxel/pixman.v11' into staging
# By Gerd Hoffmann (22) and Igor Mitsyanko (2) # Via Gerd Hoffmann * kraxel/pixman.v11: (24 commits) qxl: register QemuConsole for secondary cards gtk: custom cursor support console: allow pinning displaychangelisteners to consoles console: add qemu_console_is_* xen: re-enable refresh interval reporting for xenfb console: gui timer fixes console: add GraphicHwOps console: make DisplayState private to console.c console: move gui_update+gui_setup_refresh from vl.c into console.c console: zap g_width + g_height console: simplify screendump console: give each QemuConsole its own DisplaySurface console: rename vga_hw_*, add QemuConsole param console: displaystate init revamp console: add trace events console: switch color_table_rgb to pixman_color_t console: use pixman for font rendering console: use pixman for fill+blit pixman: render vgafont glyphs into pixman images pixman: add qemu_pixman_color() ... Message-id: 1366105178-26744-1-git-send-email-kraxel@redhat.com Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
commit
100c533220
@ -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, 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);
|
||||
|
@ -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
|
||||
@ -956,6 +944,11 @@ static void blizzard_screen_dump(void *opaque, const char *filename,
|
||||
#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));
|
||||
@ -963,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,
|
||||
blizzard_screen_dump, NULL, s);
|
||||
s->con = graphic_console_init(&blizzard_ops, s);
|
||||
surface = qemu_console_surface(s->con);
|
||||
|
||||
switch (surface_bits_per_pixel(surface)) {
|
||||
|
@ -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),
|
||||
@ -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->screen_dump, 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.screen_dump, s->vga.text_update,
|
||||
&s->vga);
|
||||
s->vga.con = graphic_console_init(s->vga.hw_ops, &s->vga);
|
||||
|
||||
/* setup PCI */
|
||||
|
||||
|
@ -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];
|
||||
@ -1886,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);
|
||||
@ -1899,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, NULL, s);
|
||||
s->console = graphic_console_init(&exynos4210_fimd_ops, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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,
|
||||
@ -546,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,
|
||||
g364fb_screen_dump, 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",
|
||||
|
@ -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,10 +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,
|
||||
NULL,
|
||||
jazz_led_text_update, s);
|
||||
s->con = graphic_console_init(&jazz_led_ops, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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, NULL, s);
|
||||
s->con = graphic_console_init(&vgafb_ops, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -468,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,
|
||||
@ -485,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,
|
||||
omap_screen_dump, NULL, s);
|
||||
s->con = graphic_console_init(&omap_ops, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -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, NULL, s);
|
||||
s->con = graphic_console_init(&pl110_gfx_ops, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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, NULL, s);
|
||||
s->con = graphic_console_init(&pxa2xx_ops, s);
|
||||
surface = qemu_console_surface(s->con);
|
||||
|
||||
switch (surface_bits_per_pixel(surface)) {
|
||||
|
@ -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)
|
||||
@ -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,26 +1769,9 @@ static void qxl_hw_invalidate(void *opaque)
|
||||
PCIQXLDevice *qxl = opaque;
|
||||
VGACommonState *vga = &qxl->vga;
|
||||
|
||||
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;
|
||||
if (qxl->mode == QXL_MODE_VGA) {
|
||||
vga->hw_ops->invalidate(vga);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1798,7 +1781,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;
|
||||
}
|
||||
}
|
||||
@ -2058,6 +2041,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);
|
||||
@ -2074,10 +2063,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_screen_dump, qxl_hw_text_update,
|
||||
qxl);
|
||||
qxl->ssd.con = vga->con,
|
||||
vga->con = graphic_console_init(&qxl_ops, qxl);
|
||||
qemu_spice_display_init_common(&qxl->ssd);
|
||||
|
||||
rc = qxl_init_common(qxl);
|
||||
@ -2086,6 +2072,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;
|
||||
@ -2101,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);
|
||||
}
|
||||
|
@ -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, NULL, s);
|
||||
s->con = graphic_console_init(&sm501_ops, s);
|
||||
}
|
||||
|
@ -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, NULL, s);
|
||||
s->con = graphic_console_init(&ssd0303_ops, s);
|
||||
qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY);
|
||||
return 0;
|
||||
}
|
||||
|
@ -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, 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);
|
||||
|
@ -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,11 +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, /* screen_dump */
|
||||
NULL, /* text_update */
|
||||
s);
|
||||
s->con = graphic_console_init(&tc6393xb_gfx_ops, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
143
hw/display/tcx.c
143
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);
|
||||
@ -515,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);
|
||||
@ -567,144 +572,20 @@ 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,
|
||||
tcx24_screen_dump, 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,
|
||||
tcx_screen_dump, NULL, s);
|
||||
s->con = graphic_console_init(&tcx_ops, 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),
|
||||
|
@ -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.screen_dump, 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;
|
||||
|
@ -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->screen_dump, s->text_update, s);
|
||||
s->con = graphic_console_init(s->hw_ops, s);
|
||||
|
||||
vga_init_vbe(s, isa_address_space(dev));
|
||||
/* ROM BIOS */
|
||||
|
@ -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->screen_dump, 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);
|
||||
|
@ -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;
|
||||
@ -2253,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;
|
||||
@ -2296,10 +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->screen_dump = vga_screen_dump;
|
||||
s->text_update = vga_update_text;
|
||||
s->hw_ops = &vga_ops;
|
||||
switch (vga_retrace_method) {
|
||||
case VGA_RETRACE_DUMB:
|
||||
s->retrace = vga_dumb_retrace;
|
||||
@ -2393,65 +2393,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);
|
||||
}
|
||||
vga_hw_update();
|
||||
ppm_save(filename, surface, errp);
|
||||
}
|
||||
|
@ -152,10 +152,7 @@ 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;
|
||||
const GraphicHwOps *hw_ops;
|
||||
bool full_update_text;
|
||||
bool full_update_gfx;
|
||||
/* hardware mouse cursor support */
|
||||
@ -198,7 +195,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);
|
||||
|
||||
|
@ -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,61 +720,88 @@ 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) {
|
||||
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 = s->new_width ? s->new_width : surface_width(surface);
|
||||
break;
|
||||
|
||||
case SVGA_REG_HEIGHT:
|
||||
return surface_height(surface);
|
||||
ret = s->new_height ? s->new_height : 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->new_depth == 32) ? 24 : s->new_depth;
|
||||
break;
|
||||
|
||||
case SVGA_REG_BITS_PER_PIXEL:
|
||||
return (s->depth + 7) & ~7;
|
||||
case SVGA_REG_HOST_BITS_PER_PIXEL:
|
||||
ret = s->new_depth;
|
||||
break;
|
||||
|
||||
case SVGA_REG_PSEUDOCOLOR:
|
||||
return 0x0;
|
||||
ret = 0x0;
|
||||
break;
|
||||
|
||||
case SVGA_REG_RED_MASK:
|
||||
return surface->pf.rmask;
|
||||
pf = qemu_default_pixelformat(s->new_depth);
|
||||
ret = pf.rmask;
|
||||
break;
|
||||
|
||||
case SVGA_REG_GREEN_MASK:
|
||||
return surface->pf.gmask;
|
||||
pf = qemu_default_pixelformat(s->new_depth);
|
||||
ret = pf.gmask;
|
||||
break;
|
||||
|
||||
case SVGA_REG_BLUE_MASK:
|
||||
return surface->pf.bmask;
|
||||
pf = qemu_default_pixelformat(s->new_depth);
|
||||
ret = pf.bmask;
|
||||
break;
|
||||
|
||||
case SVGA_REG_BYTES_PER_LINE:
|
||||
return 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: {
|
||||
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 +817,92 @@ 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;
|
||||
|
||||
case SVGA_REG_HOST_BITS_PER_PIXEL:
|
||||
return (s->depth + 7) & ~7;
|
||||
ret = s->cursor.on;
|
||||
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) {
|
||||
@ -861,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 {
|
||||
@ -888,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;
|
||||
|
||||
@ -986,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;
|
||||
}
|
||||
}
|
||||
@ -995,15 +1054,16 @@ 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) {
|
||||
s->vga.update(&s->vga);
|
||||
s->vga.hw_ops->gfx_update(&s->vga);
|
||||
return;
|
||||
}
|
||||
|
||||
vmsvga_check_size(s);
|
||||
surface = qemu_console_surface(s->vga.con);
|
||||
|
||||
vmsvga_fifo_run(s);
|
||||
vmsvga_update_rect_flush(s);
|
||||
@ -1020,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));
|
||||
}
|
||||
@ -1054,44 +1112,19 @@ 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1113,7 +1146,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),
|
||||
@ -1146,19 +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)
|
||||
{
|
||||
DisplaySurface *surface;
|
||||
|
||||
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_screen_dump,
|
||||
vmsvga_text_update, s);
|
||||
surface = qemu_console_surface(s->vga.con);
|
||||
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);
|
||||
@ -1168,10 +1201,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)
|
||||
|
@ -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
|
||||
@ -977,6 +954,12 @@ struct XenDevOps xen_framebuffer_ops = {
|
||||
.frontend_changed = fb_frontend_changed,
|
||||
};
|
||||
|
||||
static const GraphicHwOps xenfb_ops = {
|
||||
.invalidate = xenfb_invalidate,
|
||||
.gfx_update = xenfb_update,
|
||||
.update_interval = xenfb_update_interval,
|
||||
};
|
||||
|
||||
/*
|
||||
* FIXME/TODO: Kill this.
|
||||
* Temporary needed while DisplayState reorganization is in flight.
|
||||
@ -1004,11 +987,7 @@ wait_more:
|
||||
|
||||
/* vfb */
|
||||
fb = container_of(xfb, struct XenFB, c.xendev);
|
||||
fb->c.con = graphic_console_init(xenfb_update,
|
||||
xenfb_invalidate,
|
||||
NULL,
|
||||
NULL,
|
||||
fb);
|
||||
fb->c.con = graphic_console_init(&xenfb_ops, fb);
|
||||
fb->have_console = 1;
|
||||
|
||||
/* vkbd */
|
||||
|
@ -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, NULL);
|
||||
graphic_console_init(&no_ops, NULL);
|
||||
}
|
||||
|
||||
static void puv3_init(QEMUMachineInitArgs *args)
|
||||
|
@ -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,27 +175,15 @@ typedef struct DisplayChangeListenerOps {
|
||||
} DisplayChangeListenerOps;
|
||||
|
||||
struct DisplayChangeListener {
|
||||
int idle;
|
||||
uint64_t gui_timer_interval;
|
||||
uint64_t update_interval;
|
||||
const DisplayChangeListenerOps *ops;
|
||||
DisplayState *ds;
|
||||
QemuConsole *con;
|
||||
|
||||
QLIST_ENTRY(DisplayChangeListener) next;
|
||||
};
|
||||
|
||||
struct DisplayState {
|
||||
struct DisplaySurface *surface;
|
||||
struct QEMUTimer *gui_timer;
|
||||
bool have_gfx;
|
||||
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);
|
||||
@ -217,16 +206,15 @@ 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 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);
|
||||
@ -281,24 +269,25 @@ 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,
|
||||
Error **errp);
|
||||
typedef void (*vga_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);
|
||||
void (*update_interval)(void *opaque, uint64_t interval);
|
||||
} GraphicHwOps;
|
||||
|
||||
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(const GraphicHwOps *ops,
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
int is_graphic_console(void);
|
||||
int is_fixedsize_console(void);
|
||||
void text_consoles_set_display(DisplayState *ds);
|
||||
void console_select(unsigned int index);
|
||||
void console_color_init(DisplayState *ds);
|
||||
|
@ -43,4 +43,13 @@ 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);
|
||||
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 */
|
||||
|
@ -71,7 +71,6 @@ typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
|
||||
typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
|
||||
|
||||
struct SimpleSpiceDisplay {
|
||||
QemuConsole *con;
|
||||
DisplaySurface *ds;
|
||||
DisplayChangeListener dcl;
|
||||
void *buf;
|
||||
|
11
trace-events
11
trace-events
@ -962,6 +962,10 @@ 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"
|
||||
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"
|
||||
@ -970,6 +974,13 @@ 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"
|
||||
vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) "%dx%d @ %d bpp"
|
||||
|
||||
# savevm.c
|
||||
|
||||
|
684
ui/console.c
684
ui/console.c
File diff suppressed because it is too large
Load Diff
11
ui/curses.c
11
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;
|
||||
}
|
||||
}
|
||||
@ -166,11 +167,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) {
|
||||
@ -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)
|
||||
|
36
ui/gtk.c
36
ui/gtk.c
@ -327,7 +327,38 @@ static void gd_update(DisplayChangeListener *dcl,
|
||||
|
||||
static void gd_refresh(DisplayChangeListener *dcl)
|
||||
{
|
||||
vga_hw_update();
|
||||
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,
|
||||
@ -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)
|
||||
@ -1368,6 +1401,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)
|
||||
|
@ -79,3 +79,57 @@ 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
52
ui/sdl.c
52
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,12 +488,12 @@ 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();
|
||||
}
|
||||
}
|
||||
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;
|
||||
@ -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();
|
||||
@ -556,14 +556,14 @@ 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:
|
||||
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,19 +744,19 @@ 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();
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -770,8 +770,8 @@ static void sdl_refresh(DisplayChangeListener *dcl)
|
||||
sdl_update_caption();
|
||||
}
|
||||
|
||||
vga_hw_update();
|
||||
SDL_EnableUNICODE(!is_graphic_console());
|
||||
graphic_hw_update(NULL);
|
||||
SDL_EnableUNICODE(!qemu_console_is_graphic(NULL));
|
||||
|
||||
while (SDL_PollEvent(ev)) {
|
||||
switch (ev->type) {
|
||||
@ -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;
|
||||
|
@ -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__);
|
||||
vga_hw_update();
|
||||
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);
|
||||
|
87
ui/vnc.c
87
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);
|
||||
@ -1616,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)
|
||||
@ -1735,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++) {
|
||||
@ -1755,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';
|
||||
}
|
||||
|
||||
@ -1956,8 +1949,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) {
|
||||
@ -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;
|
||||
|
||||
vga_hw_update();
|
||||
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);
|
||||
vga_hw_update();
|
||||
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) {
|
||||
@ -2775,7 +2746,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);
|
||||
@ -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 */
|
||||
}
|
||||
|
||||
@ -2800,7 +2769,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);
|
||||
@ -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;
|
||||
|
2
ui/vnc.h
2
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;
|
||||
|
55
vl.c
55
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;
|
||||
@ -4331,8 +4282,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 +4338,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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user