From cdef10bb9373c2c22c517a4deef2363c7ebd5d48 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Mar 2013 16:41:56 +0000 Subject: [PATCH 01/37] hw/vexpress: Pass proc_id via VEDBoardInfo Pass the daughterboard-specific proc_id property to the code that creates the sysctl device via the VEDBoardInfo struct, rather than by having the daughterboard init function write to a uint32_t* argument. This is a cleaner way to pass the info around, and is in line with the way we are going to handle voltage and oscillator initialization. Signed-off-by: Peter Maydell --- hw/arm/vexpress.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index 02922c38b3..47a844f756 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -147,19 +147,20 @@ typedef struct VEDBoardInfo VEDBoardInfo; typedef void DBoardInitFn(const VEDBoardInfo *daughterboard, ram_addr_t ram_size, const char *cpu_model, - qemu_irq *pic, uint32_t *proc_id); + qemu_irq *pic); struct VEDBoardInfo { const hwaddr *motherboard_map; hwaddr loader_start; const hwaddr gic_cpu_if_addr; + uint32_t proc_id; DBoardInitFn *init; }; static void a9_daughterboard_init(const VEDBoardInfo *daughterboard, ram_addr_t ram_size, const char *cpu_model, - qemu_irq *pic, uint32_t *proc_id) + qemu_irq *pic) { MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); @@ -175,8 +176,6 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard, cpu_model = "cortex-a9"; } - *proc_id = 0x0c000191; - for (n = 0; n < smp_cpus; n++) { ARMCPU *cpu = cpu_arm_init(cpu_model); if (!cpu) { @@ -251,13 +250,14 @@ static const VEDBoardInfo a9_daughterboard = { .motherboard_map = motherboard_legacy_map, .loader_start = 0x60000000, .gic_cpu_if_addr = 0x1e000100, + .proc_id = 0x0c000191, .init = a9_daughterboard_init, }; static void a15_daughterboard_init(const VEDBoardInfo *daughterboard, ram_addr_t ram_size, const char *cpu_model, - qemu_irq *pic, uint32_t *proc_id) + qemu_irq *pic) { int n; MemoryRegion *sysmem = get_system_memory(); @@ -271,8 +271,6 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard, cpu_model = "cortex-a15"; } - *proc_id = 0x14000237; - for (n = 0; n < smp_cpus; n++) { ARMCPU *cpu; qemu_irq *irqp; @@ -344,6 +342,7 @@ static const VEDBoardInfo a15_daughterboard = { .motherboard_map = motherboard_aseries_map, .loader_start = 0x80000000, .gic_cpu_if_addr = 0x2c002000, + .proc_id = 0x14000237, .init = a15_daughterboard_init, }; @@ -352,7 +351,6 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, { DeviceState *dev, *sysctl, *pl041; qemu_irq pic[64]; - uint32_t proc_id; uint32_t sys_id; DriveInfo *dinfo; ram_addr_t vram_size, sram_size; @@ -361,8 +359,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, MemoryRegion *sram = g_new(MemoryRegion, 1); const hwaddr *map = daughterboard->motherboard_map; - daughterboard->init(daughterboard, args->ram_size, args->cpu_model, - pic, &proc_id); + daughterboard->init(daughterboard, args->ram_size, args->cpu_model, pic); /* Motherboard peripherals: the wiring is the same but the * addresses vary between the legacy and A-Series memory maps. @@ -372,7 +369,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, sysctl = qdev_create(NULL, "realview_sysctl"); qdev_prop_set_uint32(sysctl, "sys_id", sys_id); - qdev_prop_set_uint32(sysctl, "proc_id", proc_id); + qdev_prop_set_uint32(sysctl, "proc_id", daughterboard->proc_id); qdev_init_nofail(sysctl); sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]); From 71538323358d77f6472d66a30e948a1c23bd9e87 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Mar 2013 16:41:56 +0000 Subject: [PATCH 02/37] hw/arm_sysctl: Handle SYS_CFGCTRL in a more structured way The SYS_CFGCTRL register consists of separate fields for DCC, function, site, position and device, as well as a read/write bit. Refactor the code handling SYS_CFGCTRL writes to make it easier to add support for functions like SYS_CFG_OSC which support multiple device fields. We also pull the handling out into its own function for clarity, as there are potentially a lot of implementable subfunctions. Signed-off-by: Peter Maydell --- hw/arm_sysctl.c | 143 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 132 insertions(+), 11 deletions(-) diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index a46f8d450e..05a3200c63 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -9,6 +9,7 @@ #include "hw/hw.h" #include "qemu/timer.h" +#include "qemu/bitops.h" #include "hw/sysbus.h" #include "hw/primecell.h" #include "sysemu/sysemu.h" @@ -191,6 +192,110 @@ static uint64_t arm_sysctl_read(void *opaque, hwaddr offset, } } +/* SYS_CFGCTRL functions */ +#define SYS_CFG_OSC 1 +#define SYS_CFG_VOLT 2 +#define SYS_CFG_AMP 3 +#define SYS_CFG_TEMP 4 +#define SYS_CFG_RESET 5 +#define SYS_CFG_SCC 6 +#define SYS_CFG_MUXFPGA 7 +#define SYS_CFG_SHUTDOWN 8 +#define SYS_CFG_REBOOT 9 +#define SYS_CFG_DVIMODE 11 +#define SYS_CFG_POWER 12 +#define SYS_CFG_ENERGY 13 + +/* SYS_CFGCTRL site field values */ +#define SYS_CFG_SITE_MB 0 +#define SYS_CFG_SITE_DB1 1 +#define SYS_CFG_SITE_DB2 2 + +/** + * vexpress_cfgctrl_read: + * @s: arm_sysctl_state pointer + * @dcc, @function, @site, @position, @device: split out values from + * SYS_CFGCTRL register + * @val: pointer to where to put the read data on success + * + * Handle a VExpress SYS_CFGCTRL register read. On success, return true and + * write the read value to *val. On failure, return false (and val may + * or may not be written to). + */ +static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc, + unsigned int function, unsigned int site, + unsigned int position, unsigned int device, + uint32_t *val) +{ + /* We don't support anything other than DCC 0, board stack position 0 + * or sites other than motherboard/daughterboard: + */ + if (dcc != 0 || position != 0 || + (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) { + goto cfgctrl_unimp; + } + + switch (function) { + default: + break; + } + +cfgctrl_unimp: + qemu_log_mask(LOG_UNIMP, + "arm_sysctl: Unimplemented SYS_CFGCTRL read of function " + "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n", + function, dcc, site, position, device); + return false; +} + +/** + * vexpress_cfgctrl_write: + * @s: arm_sysctl_state pointer + * @dcc, @function, @site, @position, @device: split out values from + * SYS_CFGCTRL register + * @val: data to write + * + * Handle a VExpress SYS_CFGCTRL register write. On success, return true. + * On failure, return false. + */ +static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc, + unsigned int function, unsigned int site, + unsigned int position, unsigned int device, + uint32_t val) +{ + /* We don't support anything other than DCC 0, board stack position 0 + * or sites other than motherboard/daughterboard: + */ + if (dcc != 0 || position != 0 || + (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) { + goto cfgctrl_unimp; + } + + switch (function) { + case SYS_CFG_SHUTDOWN: + if (site == SYS_CFG_SITE_MB && device == 0) { + qemu_system_shutdown_request(); + return true; + } + break; + case SYS_CFG_REBOOT: + if (site == SYS_CFG_SITE_MB && device == 0) { + qemu_system_reset_request(); + return true; + } + break; + default: + break; + } + +cfgctrl_unimp: + qemu_log_mask(LOG_UNIMP, + "arm_sysctl: Unimplemented SYS_CFGCTRL write of function " + "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n", + function, dcc, site, position, device); + return false; +} + static void arm_sysctl_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { @@ -322,17 +427,33 @@ static void arm_sysctl_write(void *opaque, hwaddr offset, if (board_id(s) != BOARD_ID_VEXPRESS) { goto bad_reg; } - s->sys_cfgctrl = val & ~(3 << 18); - s->sys_cfgstat = 1; /* complete */ - switch (s->sys_cfgctrl) { - case 0xc0800000: /* SYS_CFG_SHUTDOWN to motherboard */ - qemu_system_shutdown_request(); - break; - case 0xc0900000: /* SYS_CFG_REBOOT to motherboard */ - qemu_system_reset_request(); - break; - default: - s->sys_cfgstat |= 2; /* error */ + /* Undefined bits [19:18] are RAZ/WI, and writing to + * the start bit just triggers the action; it always reads + * as zero. + */ + s->sys_cfgctrl = val & ~((3 << 18) | (1 << 31)); + if (val & (1 << 31)) { + /* Start bit set -- actually do something */ + unsigned int dcc = extract32(s->sys_cfgctrl, 26, 4); + unsigned int function = extract32(s->sys_cfgctrl, 20, 6); + unsigned int site = extract32(s->sys_cfgctrl, 16, 2); + unsigned int position = extract32(s->sys_cfgctrl, 12, 4); + unsigned int device = extract32(s->sys_cfgctrl, 0, 12); + s->sys_cfgstat = 1; /* complete */ + if (s->sys_cfgctrl & (1 << 30)) { + if (!vexpress_cfgctrl_write(s, dcc, function, site, position, + device, s->sys_cfgdata)) { + s->sys_cfgstat |= 2; /* error */ + } + } else { + uint32_t val; + if (!vexpress_cfgctrl_read(s, dcc, function, site, position, + device, &val)) { + s->sys_cfgstat |= 2; /* error */ + } else { + s->sys_cfgdata = val; + } + } } s->sys_cfgctrl &= ~(1 << 31); return; From 8ff05c9842e28888b936dbd960f6416cee5addb6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Mar 2013 16:41:56 +0000 Subject: [PATCH 03/37] hw/arm_sysctl: Implement SYS_CFG_MUXFPGA writes as a no-op SYS_CFG_MUXFPGA allows the guest to select whether the video output should come from the motherboard's LCD controller or the daughterboard's one. Since QEMU doesn't currently support selecting the video output like this, implement as a no-op, so Linux doesn't complain about the register not being implemented. Signed-off-by: Peter Maydell --- hw/arm_sysctl.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index 05a3200c63..a6e5ed4cc1 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -272,6 +272,17 @@ static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc, } switch (function) { + case SYS_CFG_MUXFPGA: + if (site == SYS_CFG_SITE_MB && device == 0) { + /* Select whether video output comes from motherboard + * or daughterboard: log and ignore as QEMU doesn't + * support this. + */ + qemu_log_mask(LOG_UNIMP, "arm_sysctl: selection of video output " + "not supported, ignoring\n"); + return true; + } + break; case SYS_CFG_SHUTDOWN: if (site == SYS_CFG_SITE_MB && device == 0) { qemu_system_shutdown_request(); From 291155cbc54212a451d0b899a01b6e3e14ed9135 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Mar 2013 16:41:56 +0000 Subject: [PATCH 04/37] hw/arm_sysctl: Implement SYS_CFG_DVIMODE as a no-op SYS_CFG_DVIMODE allows the guest to select whether the output DVI signal is VGA, SVGA, XGA, SGA or UXGA. Since this makes no difference to QEMU, implement writes as a no-op so Linux doesn't complain. Signed-off-by: Peter Maydell --- hw/arm_sysctl.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index a6e5ed4cc1..840bfadad3 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -295,6 +295,14 @@ static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc, return true; } break; + case SYS_CFG_DVIMODE: + if (site == SYS_CFG_SITE_MB && device == 0) { + /* Selecting DVI mode is meaningless for QEMU: we will + * always display the output correctly according to the + * pixel height/width programmed into the CLCD controller. + */ + return true; + } default: break; } From 1f56f50ac484653fe996c37ac894418a34f92b89 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Mar 2013 16:41:56 +0000 Subject: [PATCH 05/37] hw/arm_sysctl: Convert from qdev init to instance_init Convert this device from old-style qdev init to an instance_init function. We don't need a realize function yet, though. Signed-off-by: Peter Maydell --- hw/arm_sysctl.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index 840bfadad3..7c94b78498 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -525,15 +525,16 @@ static void arm_sysctl_gpio_set(void *opaque, int line, int level) } } -static int arm_sysctl_init(SysBusDevice *dev) +static void arm_sysctl_init(Object *obj) { - arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev); + DeviceState *dev = DEVICE(obj); + SysBusDevice *sd = SYS_BUS_DEVICE(obj); + arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sd); memory_region_init_io(&s->iomem, &arm_sysctl_ops, s, "arm-sysctl", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - qdev_init_gpio_in(&s->busdev.qdev, arm_sysctl_gpio_set, 2); - qdev_init_gpio_out(&s->busdev.qdev, &s->pl110_mux_ctrl, 1); - return 0; + sysbus_init_mmio(sd, &s->iomem); + qdev_init_gpio_in(dev, arm_sysctl_gpio_set, 2); + qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1); } static Property arm_sysctl_properties[] = { @@ -545,9 +546,7 @@ static Property arm_sysctl_properties[] = { static void arm_sysctl_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = arm_sysctl_init; dc->reset = arm_sysctl_reset; dc->vmsd = &vmstate_arm_sysctl; dc->props = arm_sysctl_properties; @@ -557,6 +556,7 @@ static const TypeInfo arm_sysctl_info = { .name = "realview_sysctl", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(arm_sysctl_state), + .instance_init = arm_sysctl_init, .class_init = arm_sysctl_class_init, }; From 0be6bfac6262900425c10847de513ee2490078d3 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Mar 2013 16:41:57 +0000 Subject: [PATCH 06/37] qdev: Implement (variable length) array properties Add support for declaring array properties for qdev devices. These work by defining an initial static property 'len-arrayname' which the user of the device should set to the desired size of the array. When this property is set, memory is allocated for the array elements, and dynamic properties "arrayname[0]", "arrayname[1]"... are created so the user of the device can then set the values of the individual array elements. Signed-off-by: Peter Maydell --- hw/qdev-core.h | 3 ++ hw/qdev-properties.c | 104 +++++++++++++++++++++++++++++++++++++++++++ hw/qdev-properties.h | 39 ++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/hw/qdev-core.h b/hw/qdev-core.h index 2486f36853..547fbc7e0d 100644 --- a/hw/qdev-core.h +++ b/hw/qdev-core.h @@ -175,6 +175,9 @@ struct Property { uint8_t bitnr; uint8_t qtype; int64_t defval; + int arrayoffset; + PropertyInfo *arrayinfo; + int arrayfieldsize; }; struct PropertyInfo { diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 0307a7830b..247ca6c5b4 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -779,6 +779,110 @@ PropertyInfo qdev_prop_pci_host_devaddr = { .set = set_pci_host_devaddr, }; +/* --- support for array properties --- */ + +/* Used as an opaque for the object properties we add for each + * array element. Note that the struct Property must be first + * in the struct so that a pointer to this works as the opaque + * for the underlying element's property hooks as well as for + * our own release callback. + */ +typedef struct { + struct Property prop; + char *propname; + ObjectPropertyRelease *release; +} ArrayElementProperty; + +/* object property release callback for array element properties: + * we call the underlying element's property release hook, and + * then free the memory we allocated when we added the property. + */ +static void array_element_release(Object *obj, const char *name, void *opaque) +{ + ArrayElementProperty *p = opaque; + if (p->release) { + p->release(obj, name, opaque); + } + g_free(p->propname); + g_free(p); +} + +static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + /* Setter for the property which defines the length of a + * variable-sized property array. As well as actually setting the + * array-length field in the device struct, we have to create the + * array itself and dynamically add the corresponding properties. + */ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + uint32_t *alenptr = qdev_get_prop_ptr(dev, prop); + void **arrayptr = (void *)dev + prop->arrayoffset; + void *eltptr; + const char *arrayname; + int i; + + if (dev->realized) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + if (*alenptr) { + error_setg(errp, "array size property %s may not be set more than once", + name); + return; + } + visit_type_uint32(v, alenptr, name, errp); + if (error_is_set(errp)) { + return; + } + if (!*alenptr) { + return; + } + + /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix; + * strip it off so we can get the name of the array itself. + */ + assert(strncmp(name, PROP_ARRAY_LEN_PREFIX, + strlen(PROP_ARRAY_LEN_PREFIX)) == 0); + arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX); + + /* Note that it is the responsibility of the individual device's deinit + * to free the array proper. + */ + *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize); + for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) { + char *propname = g_strdup_printf("%s[%d]", arrayname, i); + ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1); + arrayprop->release = prop->arrayinfo->release; + arrayprop->propname = propname; + arrayprop->prop.info = prop->arrayinfo; + arrayprop->prop.name = propname; + /* This ugly piece of pointer arithmetic sets up the offset so + * that when the underlying get/set hooks call qdev_get_prop_ptr + * they get the right answer despite the array element not actually + * being inside the device struct. + */ + arrayprop->prop.offset = eltptr - (void *)dev; + assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr); + object_property_add(obj, propname, + arrayprop->prop.info->name, + arrayprop->prop.info->get, + arrayprop->prop.info->set, + array_element_release, + arrayprop, errp); + if (error_is_set(errp)) { + return; + } + } +} + +PropertyInfo qdev_prop_arraylen = { + .name = "uint32", + .get = get_uint32, + .set = set_prop_arraylen, +}; + /* --- public helpers --- */ static Property *qdev_prop_walk(Property *props, const char *name) diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h index 0b0465c9b3..c9bb246841 100644 --- a/hw/qdev-properties.h +++ b/hw/qdev-properties.h @@ -26,6 +26,7 @@ extern PropertyInfo qdev_prop_vlan; extern PropertyInfo qdev_prop_pci_devfn; extern PropertyInfo qdev_prop_blocksize; extern PropertyInfo qdev_prop_pci_host_devaddr; +extern PropertyInfo qdev_prop_arraylen; #define DEFINE_PROP(_name, _state, _field, _prop, _type) { \ .name = (_name), \ @@ -51,6 +52,44 @@ extern PropertyInfo qdev_prop_pci_host_devaddr; .defval = (bool)_defval, \ } +#define PROP_ARRAY_LEN_PREFIX "len-" + +/** + * DEFINE_PROP_ARRAY: + * @_name: name of the array + * @_state: name of the device state structure type + * @_field: uint32_t field in @_state to hold the array length + * @_arrayfield: field in @_state (of type '@_arraytype *') which + * will point to the array + * @_arrayprop: PropertyInfo defining what property the array elements have + * @_arraytype: C type of the array elements + * + * Define device properties for a variable-length array _name. A + * static property "len-arrayname" is defined. When the device creator + * sets this property to the desired length of array, further dynamic + * properties "arrayname[0]", "arrayname[1]", ... are defined so the + * device creator can set the array element values. Setting the + * "len-arrayname" property more than once is an error. + * + * When the array length is set, the @_field member of the device + * struct is set to the array length, and @_arrayfield is set to point + * to (zero-initialised) memory allocated for the array. For a zero + * length array, @_field will be set to 0 and @_arrayfield to NULL. + * It is the responsibility of the device deinit code to free the + * @_arrayfield memory. + */ +#define DEFINE_PROP_ARRAY(_name, _state, _field, \ + _arrayfield, _arrayprop, _arraytype) { \ + .name = (PROP_ARRAY_LEN_PREFIX _name), \ + .info = &(qdev_prop_arraylen), \ + .offset = offsetof(_state, _field) \ + + type_check(uint32_t, typeof_field(_state, _field)), \ + .qtype = QTYPE_QINT, \ + .arrayinfo = &(_arrayprop), \ + .arrayfieldsize = sizeof(_arraytype), \ + .arrayoffset = offsetof(_state, _arrayfield), \ + } + #define DEFINE_PROP_UINT8(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t) #define DEFINE_PROP_UINT16(_n, _s, _f, _d) \ From 8bd4824a6122292060a318741595927e0d05ff5e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Mar 2013 16:41:57 +0000 Subject: [PATCH 07/37] hw/arm_sysctl: Implement SYS_CFG_VOLT Implement the SYS_CFG_VOLT registers which return the voltage of various supplies on motherboard and daughterboard. Since QEMU implements a perfectly stable power supply these registers always return a constant value. The number and value of the daughterboard voltages is dependent on the specific daughterboard, so we use a property array to allow the board to configure them appropriately. Signed-off-by: Peter Maydell --- hw/arm_sysctl.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index 7c94b78498..e2f00d37c0 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -35,6 +35,8 @@ typedef struct { uint32_t sys_cfgctrl; uint32_t sys_cfgstat; uint32_t sys_clcd; + uint32_t db_num_vsensors; + uint32_t *db_voltage; } arm_sysctl_state; static const VMStateDescription vmstate_arm_sysctl = { @@ -236,6 +238,19 @@ static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc, } switch (function) { + case SYS_CFG_VOLT: + if (site == SYS_CFG_SITE_DB1 && device < s->db_num_vsensors) { + *val = s->db_voltage[device]; + return true; + } + if (site == SYS_CFG_SITE_MB && device == 0) { + /* There is only one motherboard voltage sensor: + * VIO : 3.3V : bus voltage between mother and daughterboard + */ + *val = 3300000; + return true; + } + break; default: break; } @@ -537,9 +552,19 @@ static void arm_sysctl_init(Object *obj) qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1); } +static void arm_sysctl_finalize(Object *obj) +{ + SysBusDevice *dev = SYS_BUS_DEVICE(obj); + arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev); + g_free(s->db_voltage); +} + static Property arm_sysctl_properties[] = { DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0), DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0), + /* Daughterboard power supply voltages (as reported via SYS_CFG) */ + DEFINE_PROP_ARRAY("db-voltage", arm_sysctl_state, db_num_vsensors, + db_voltage, qdev_prop_uint32, uint32_t), DEFINE_PROP_END_OF_LIST(), }; @@ -557,6 +582,7 @@ static const TypeInfo arm_sysctl_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(arm_sysctl_state), .instance_init = arm_sysctl_init, + .instance_finalize = arm_sysctl_finalize, .class_init = arm_sysctl_class_init, }; From 31410948bc1c8001098b076caf35aab8a5cf063d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Mar 2013 16:41:57 +0000 Subject: [PATCH 08/37] hw/vexpress: Pass voltage sensor properties to sysctl device Pass voltage sensor properties to the sysctl device. Since these are daughterboard specific, we specify them via the VEDBoardInfo structure. Signed-off-by: Peter Maydell Message-id: 1359985476-29380-9-git-send-email-peter.maydell@linaro.org --- hw/arm/vexpress.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index 47a844f756..a2dc759930 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -154,6 +154,8 @@ struct VEDBoardInfo { hwaddr loader_start; const hwaddr gic_cpu_if_addr; uint32_t proc_id; + uint32_t num_voltage_sensors; + const uint32_t *voltages; DBoardInitFn *init; }; @@ -246,11 +248,25 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard, sysbus_create_varargs("l2x0", 0x1e00a000, NULL); } +/* Voltage values for SYS_CFG_VOLT daughterboard registers; + * values are in microvolts. + */ +static const uint32_t a9_voltages[] = { + 1000000, /* VD10 : 1.0V : SoC internal logic voltage */ + 1000000, /* VD10_S2 : 1.0V : PL310, L2 cache, RAM, non-PL310 logic */ + 1000000, /* VD10_S3 : 1.0V : Cortex-A9, cores, MPEs, SCU, PL310 logic */ + 1800000, /* VCC1V8 : 1.8V : DDR2 SDRAM, test chip DDR2 I/O supply */ + 900000, /* DDR2VTT : 0.9V : DDR2 SDRAM VTT termination voltage */ + 3300000, /* VCC3V3 : 3.3V : local board supply for misc external logic */ +}; + static const VEDBoardInfo a9_daughterboard = { .motherboard_map = motherboard_legacy_map, .loader_start = 0x60000000, .gic_cpu_if_addr = 0x1e000100, .proc_id = 0x0c000191, + .num_voltage_sensors = ARRAY_SIZE(a9_voltages), + .voltages = a9_voltages, .init = a9_daughterboard_init, }; @@ -338,11 +354,17 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard, /* 0x7ffd0000: PL354 static memory controller: not modelled */ } +static const uint32_t a15_voltages[] = { + 900000, /* Vcore: 0.9V : CPU core voltage */ +}; + static const VEDBoardInfo a15_daughterboard = { .motherboard_map = motherboard_aseries_map, .loader_start = 0x80000000, .gic_cpu_if_addr = 0x2c002000, .proc_id = 0x14000237, + .num_voltage_sensors = ARRAY_SIZE(a15_voltages), + .voltages = a15_voltages, .init = a15_daughterboard_init, }; @@ -358,6 +380,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, MemoryRegion *vram = g_new(MemoryRegion, 1); MemoryRegion *sram = g_new(MemoryRegion, 1); const hwaddr *map = daughterboard->motherboard_map; + int i; daughterboard->init(daughterboard, args->ram_size, args->cpu_model, pic); @@ -370,6 +393,13 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, sysctl = qdev_create(NULL, "realview_sysctl"); qdev_prop_set_uint32(sysctl, "sys_id", sys_id); qdev_prop_set_uint32(sysctl, "proc_id", daughterboard->proc_id); + qdev_prop_set_uint32(sysctl, "len-db-voltage", + daughterboard->num_voltage_sensors); + for (i = 0; i < daughterboard->num_voltage_sensors; i++) { + char *propname = g_strdup_printf("db-voltage[%d]", i); + qdev_prop_set_uint32(sysctl, propname, daughterboard->voltages[i]); + g_free(propname); + } qdev_init_nofail(sysctl); sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]); From 1f81f94bebc2f8c4b32a89910d071099a67dc44d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Mar 2013 16:41:57 +0000 Subject: [PATCH 09/37] hw/arm_sysctl: Implement SYS_CFG_OSC function Implement the SYS_CFG_OSC function. Since the idea of programmable clock rates doesn't make much sense for QEMU, we simply allow the clock rate to be read back as written. The number and value of the daughterboard oscillators varies between daughterboards, so we provide an array property to allow their reset values to be configured. Signed-off-by: Peter Maydell --- hw/arm_sysctl.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index e2f00d37c0..25fc6eac94 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -35,13 +35,17 @@ typedef struct { uint32_t sys_cfgctrl; uint32_t sys_cfgstat; uint32_t sys_clcd; + uint32_t mb_clock[6]; + uint32_t *db_clock; uint32_t db_num_vsensors; uint32_t *db_voltage; + uint32_t db_num_clocks; + uint32_t *db_clock_reset; } arm_sysctl_state; static const VMStateDescription vmstate_arm_sysctl = { .name = "realview_sysctl", - .version_id = 3, + .version_id = 4, .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(leds, arm_sysctl_state), @@ -56,6 +60,9 @@ static const VMStateDescription vmstate_arm_sysctl = { VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2), VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2), VMSTATE_UINT32_V(sys_clcd, arm_sysctl_state, 3), + VMSTATE_UINT32_ARRAY_V(mb_clock, arm_sysctl_state, 6, 4), + VMSTATE_VARRAY_UINT32(db_clock, arm_sysctl_state, db_num_clocks, + 4, vmstate_info_uint32, uint32_t), VMSTATE_END_OF_LIST() } }; @@ -79,6 +86,7 @@ static int board_id(arm_sysctl_state *s) static void arm_sysctl_reset(DeviceState *d) { arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, SYS_BUS_DEVICE(d)); + int i; s->leds = 0; s->lockval = 0; @@ -86,6 +94,17 @@ static void arm_sysctl_reset(DeviceState *d) s->cfgdata2 = 0; s->flags = 0; s->resetlevel = 0; + /* Motherboard oscillators (in Hz) */ + s->mb_clock[0] = 50000000; /* Static memory clock: 50MHz */ + s->mb_clock[1] = 23750000; /* motherboard CLCD clock: 23.75MHz */ + s->mb_clock[2] = 24000000; /* IO FPGA peripheral clock: 24MHz */ + s->mb_clock[3] = 24000000; /* IO FPGA reserved clock: 24MHz */ + s->mb_clock[4] = 24000000; /* System bus global clock: 24MHz */ + s->mb_clock[5] = 24000000; /* IO FPGA reserved clock: 24MHz */ + /* Daughterboard oscillators: reset from property values */ + for (i = 0; i < s->db_num_clocks; i++) { + s->db_clock[i] = s->db_clock_reset[i]; + } if (board_id(s) == BOARD_ID_VEXPRESS) { /* On VExpress this register will RAZ/WI */ s->sys_clcd = 0; @@ -251,6 +270,18 @@ static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc, return true; } break; + case SYS_CFG_OSC: + if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) { + /* motherboard clock */ + *val = s->mb_clock[device]; + return true; + } + if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) { + /* daughterboard clock */ + *val = s->db_clock[device]; + return true; + } + break; default: break; } @@ -287,6 +318,18 @@ static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc, } switch (function) { + case SYS_CFG_OSC: + if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) { + /* motherboard clock */ + s->mb_clock[device] = val; + return true; + } + if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) { + /* daughterboard clock */ + s->db_clock[device] = val; + return true; + } + break; case SYS_CFG_MUXFPGA: if (site == SYS_CFG_SITE_MB && device == 0) { /* Select whether video output comes from motherboard @@ -552,11 +595,19 @@ static void arm_sysctl_init(Object *obj) qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1); } +static void arm_sysctl_realize(DeviceState *d, Error **errp) +{ + arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, SYS_BUS_DEVICE(d)); + s->db_clock = g_new0(uint32_t, s->db_num_clocks); +} + static void arm_sysctl_finalize(Object *obj) { SysBusDevice *dev = SYS_BUS_DEVICE(obj); arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev); g_free(s->db_voltage); + g_free(s->db_clock); + g_free(s->db_clock_reset); } static Property arm_sysctl_properties[] = { @@ -565,6 +616,9 @@ static Property arm_sysctl_properties[] = { /* Daughterboard power supply voltages (as reported via SYS_CFG) */ DEFINE_PROP_ARRAY("db-voltage", arm_sysctl_state, db_num_vsensors, db_voltage, qdev_prop_uint32, uint32_t), + /* Daughterboard clock reset values (as reported via SYS_CFG) */ + DEFINE_PROP_ARRAY("db-clock", arm_sysctl_state, db_num_clocks, + db_clock_reset, qdev_prop_uint32, uint32_t), DEFINE_PROP_END_OF_LIST(), }; @@ -572,6 +626,7 @@ static void arm_sysctl_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + dc->realize = arm_sysctl_realize; dc->reset = arm_sysctl_reset; dc->vmsd = &vmstate_arm_sysctl; dc->props = arm_sysctl_properties; From 9c7d489379c2a2923b4805d337dfd54f2f432449 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Mar 2013 16:41:58 +0000 Subject: [PATCH 10/37] hw/vexpress: Set reset values for daughterboard oscillators Set the reset values for the VExpress daughterboard oscillators via the new sysctl properties. Signed-off-by: Peter Maydell --- hw/arm/vexpress.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index a2dc759930..2e1a5d0e5b 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -156,6 +156,8 @@ struct VEDBoardInfo { uint32_t proc_id; uint32_t num_voltage_sensors; const uint32_t *voltages; + uint32_t num_clocks; + const uint32_t *clocks; DBoardInitFn *init; }; @@ -260,6 +262,13 @@ static const uint32_t a9_voltages[] = { 3300000, /* VCC3V3 : 3.3V : local board supply for misc external logic */ }; +/* Reset values for daughterboard oscillators (in Hz) */ +static const uint32_t a9_clocks[] = { + 45000000, /* AMBA AXI ACLK: 45MHz */ + 23750000, /* daughterboard CLCD clock: 23.75MHz */ + 66670000, /* Test chip reference clock: 66.67MHz */ +}; + static const VEDBoardInfo a9_daughterboard = { .motherboard_map = motherboard_legacy_map, .loader_start = 0x60000000, @@ -267,6 +276,8 @@ static const VEDBoardInfo a9_daughterboard = { .proc_id = 0x0c000191, .num_voltage_sensors = ARRAY_SIZE(a9_voltages), .voltages = a9_voltages, + .num_clocks = ARRAY_SIZE(a9_clocks), + .clocks = a9_clocks, .init = a9_daughterboard_init, }; @@ -358,6 +369,18 @@ static const uint32_t a15_voltages[] = { 900000, /* Vcore: 0.9V : CPU core voltage */ }; +static const uint32_t a15_clocks[] = { + 60000000, /* OSCCLK0: 60MHz : CPU_CLK reference */ + 0, /* OSCCLK1: reserved */ + 0, /* OSCCLK2: reserved */ + 0, /* OSCCLK3: reserved */ + 40000000, /* OSCCLK4: 40MHz : external AXI master clock */ + 23750000, /* OSCCLK5: 23.75MHz : HDLCD PLL reference */ + 50000000, /* OSCCLK6: 50MHz : static memory controller clock */ + 60000000, /* OSCCLK7: 60MHz : SYSCLK reference */ + 40000000, /* OSCCLK8: 40MHz : DDR2 PLL reference */ +}; + static const VEDBoardInfo a15_daughterboard = { .motherboard_map = motherboard_aseries_map, .loader_start = 0x80000000, @@ -365,6 +388,8 @@ static const VEDBoardInfo a15_daughterboard = { .proc_id = 0x14000237, .num_voltage_sensors = ARRAY_SIZE(a15_voltages), .voltages = a15_voltages, + .num_clocks = ARRAY_SIZE(a15_clocks), + .clocks = a15_clocks, .init = a15_daughterboard_init, }; @@ -400,6 +425,13 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, qdev_prop_set_uint32(sysctl, propname, daughterboard->voltages[i]); g_free(propname); } + qdev_prop_set_uint32(sysctl, "len-db-clock", + daughterboard->num_clocks); + for (i = 0; i < daughterboard->num_clocks; i++) { + char *propname = g_strdup_printf("db-clock[%d]", i); + qdev_prop_set_uint32(sysctl, propname, daughterboard->clocks[i]); + g_free(propname); + } qdev_init_nofail(sysctl); sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]); From 6ff66f50f0999c3455c39de68fc2d2949963c796 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Fri, 15 Mar 2013 16:41:58 +0000 Subject: [PATCH 11/37] iov: Factor out hexdumper Factor out the hexdumper functionality from iov for all to use. Useful for creating verbose debug printfery that dumps packet data. Signed-off-by: Peter Crosthwaite Message-id: faaac219c55ea586d3f748befaf5a2788fd271b8.1361853677.git.peter.crosthwaite@xilinx.com Signed-off-by: Peter Maydell --- include/qemu-common.h | 6 ++++++ util/Makefile.objs | 1 + util/hexdump.c | 37 +++++++++++++++++++++++++++++++++++++ util/iov.c | 34 ++++++++++------------------------ 4 files changed, 54 insertions(+), 24 deletions(-) create mode 100644 util/hexdump.c diff --git a/include/qemu-common.h b/include/qemu-common.h index 5e137084b5..7754ee2fcc 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -442,4 +442,10 @@ int64_t pow2floor(int64_t value); int uleb128_encode_small(uint8_t *out, uint32_t n); int uleb128_decode_small(const uint8_t *in, uint32_t *n); +/* + * Hexdump a buffer to a file. An optional string prefix is added to every line + */ + +void hexdump(const char *buf, FILE *fp, const char *prefix, size_t size); + #endif diff --git a/util/Makefile.objs b/util/Makefile.objs index cad5ce87db..557bda7a15 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -9,3 +9,4 @@ util-obj-y += error.o qemu-error.o util-obj-$(CONFIG_POSIX) += compatfd.o util-obj-y += iov.o aes.o qemu-config.o qemu-sockets.o uri.o notify.o util-obj-y += qemu-option.o qemu-progress.o +util-obj-y += hexdump.o diff --git a/util/hexdump.c b/util/hexdump.c new file mode 100644 index 0000000000..0d0efc86de --- /dev/null +++ b/util/hexdump.c @@ -0,0 +1,37 @@ +/* + * Helper to hexdump a buffer + * + * Copyright (c) 2013 Red Hat, Inc. + * Copyright (c) 2013 Gerd Hoffmann + * Copyright (c) 2013 Peter Crosthwaite + * Copyright (c) 2013 Xilinx, Inc + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#include "qemu-common.h" + +void hexdump(const char *buf, FILE *fp, const char *prefix, size_t size) +{ + unsigned int b; + + for (b = 0; b < size; b++) { + if ((b % 16) == 0) { + fprintf(fp, "%s: %04x:", prefix, b); + } + if ((b % 4) == 0) { + fprintf(fp, " "); + } + fprintf(fp, " %02x", (unsigned char)buf[b]); + if ((b % 16) == 15) { + fprintf(fp, "\n"); + } + } + if ((b % 16) != 0) { + fprintf(fp, "\n"); + } +} diff --git a/util/iov.c b/util/iov.c index fbe675d373..9dae318197 100644 --- a/util/iov.c +++ b/util/iov.c @@ -201,32 +201,18 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, FILE *fp, const char *prefix, size_t limit) { - unsigned int i, v, b; - uint8_t *c; + int v; + size_t size = 0; + char *buf; - c = iov[0].iov_base; - for (i = 0, v = 0, b = 0; b < limit; i++, b++) { - if (i == iov[v].iov_len) { - i = 0; v++; - if (v == iov_cnt) { - break; - } - c = iov[v].iov_base; - } - if ((b % 16) == 0) { - fprintf(fp, "%s: %04x:", prefix, b); - } - if ((b % 4) == 0) { - fprintf(fp, " "); - } - fprintf(fp, " %02x", c[i]); - if ((b % 16) == 15) { - fprintf(fp, "\n"); - } - } - if ((b % 16) != 0) { - fprintf(fp, "\n"); + for (v = 0; v < iov_cnt; v++) { + size += iov[v].iov_len; } + size = size > limit ? limit : size; + buf = g_malloc(size); + iov_to_buf(iov, iov_cnt, 0, buf, size); + hexdump(buf, fp, prefix, size); + g_free(buf); } unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt, From 06a1cea5f631f6ac69f85ae07bb47ef47b88f5f7 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Fri, 15 Mar 2013 16:41:58 +0000 Subject: [PATCH 12/37] pl330: Initial version Device model for Primecell PL330 DMA controller. Signed-off-by: Peter Crosthwaite Signed-off-by: Kirill Batuzov Tested-by: Igor Mitsyanko Reviewed-by: Igor Mitsyanko Reviewed-by: Peter Maydell Message-id: 098aac26233d7334bed2bca4f06f539638ca6d24.1361853677.git.peter.crosthwaite@xilinx.com Signed-off-by: Peter Maydell --- default-configs/arm-softmmu.mak | 1 + hw/Makefile.objs | 1 + hw/pl330.c | 1654 +++++++++++++++++++++++++++++++ 3 files changed, 1656 insertions(+) create mode 100644 hw/pl330.c diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index 68b204547c..ab8703578e 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -42,6 +42,7 @@ CONFIG_PL110=y CONFIG_PL181=y CONFIG_PL190=y CONFIG_PL310=y +CONFIG_PL330=y CONFIG_CADENCE=y CONFIG_XGMAC=y diff --git a/hw/Makefile.objs b/hw/Makefile.objs index eb7eb31a19..11812c6a4e 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -98,6 +98,7 @@ common-obj-$(CONFIG_PL110) += pl110.o common-obj-$(CONFIG_PL181) += pl181.o common-obj-$(CONFIG_PL190) += pl190.o common-obj-$(CONFIG_PL310) += arm_l2x0.o +common-obj-$(CONFIG_PL330) += pl330.o common-obj-$(CONFIG_VERSATILE_PCI) += versatile_pci.o common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o common-obj-$(CONFIG_CADENCE) += cadence_uart.o diff --git a/hw/pl330.c b/hw/pl330.c new file mode 100644 index 0000000000..1a04773a71 --- /dev/null +++ b/hw/pl330.c @@ -0,0 +1,1654 @@ +/* + * ARM PrimeCell PL330 DMA Controller + * + * Copyright (c) 2009 Samsung Electronics. + * Contributed by Kirill Batuzov + * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com) + * Copyright (c) 2012 PetaLogix Pty Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 or later. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "sysbus.h" +#include "qemu/timer.h" +#include "sysemu/dma.h" + +#ifndef PL330_ERR_DEBUG +#define PL330_ERR_DEBUG 0 +#endif + +#define DB_PRINT_L(lvl, fmt, args...) do {\ + if (PL330_ERR_DEBUG >= lvl) {\ + fprintf(stderr, "PL330: %s:" fmt, __func__, ## args);\ + } \ +} while (0); + +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) + +#define PL330_PERIPH_NUM 32 +#define PL330_MAX_BURST_LEN 128 +#define PL330_INSN_MAXSIZE 6 + +#define PL330_FIFO_OK 0 +#define PL330_FIFO_STALL 1 +#define PL330_FIFO_ERR (-1) + +#define PL330_FAULT_UNDEF_INSTR (1 << 0) +#define PL330_FAULT_OPERAND_INVALID (1 << 1) +#define PL330_FAULT_DMAGO_ERR (1 << 4) +#define PL330_FAULT_EVENT_ERR (1 << 5) +#define PL330_FAULT_CH_PERIPH_ERR (1 << 6) +#define PL330_FAULT_CH_RDWR_ERR (1 << 7) +#define PL330_FAULT_ST_DATA_UNAVAILABLE (1 << 12) +#define PL330_FAULT_FIFOEMPTY_ERR (1 << 13) +#define PL330_FAULT_INSTR_FETCH_ERR (1 << 16) +#define PL330_FAULT_DATA_WRITE_ERR (1 << 17) +#define PL330_FAULT_DATA_READ_ERR (1 << 18) +#define PL330_FAULT_DBG_INSTR (1 << 30) +#define PL330_FAULT_LOCKUP_ERR (1 << 31) + +#define PL330_UNTAGGED 0xff + +#define PL330_SINGLE 0x0 +#define PL330_BURST 0x1 + +#define PL330_WATCHDOG_LIMIT 1024 + +/* IOMEM mapped registers */ +#define PL330_REG_DSR 0x000 +#define PL330_REG_DPC 0x004 +#define PL330_REG_INTEN 0x020 +#define PL330_REG_INT_EVENT_RIS 0x024 +#define PL330_REG_INTMIS 0x028 +#define PL330_REG_INTCLR 0x02C +#define PL330_REG_FSRD 0x030 +#define PL330_REG_FSRC 0x034 +#define PL330_REG_FTRD 0x038 +#define PL330_REG_FTR_BASE 0x040 +#define PL330_REG_CSR_BASE 0x100 +#define PL330_REG_CPC_BASE 0x104 +#define PL330_REG_CHANCTRL 0x400 +#define PL330_REG_DBGSTATUS 0xD00 +#define PL330_REG_DBGCMD 0xD04 +#define PL330_REG_DBGINST0 0xD08 +#define PL330_REG_DBGINST1 0xD0C +#define PL330_REG_CR0_BASE 0xE00 +#define PL330_REG_PERIPH_ID 0xFE0 + +#define PL330_IOMEM_SIZE 0x1000 + +#define CFG_BOOT_ADDR 2 +#define CFG_INS 3 +#define CFG_PNS 4 +#define CFG_CRD 5 + +static const uint32_t pl330_id[] = { + 0x30, 0x13, 0x24, 0x00, 0x0D, 0xF0, 0x05, 0xB1 +}; + +/* DMA channel states as they are described in PL330 Technical Reference Manual + * Most of them will not be used in emulation. + */ +typedef enum { + pl330_chan_stopped = 0, + pl330_chan_executing = 1, + pl330_chan_cache_miss = 2, + pl330_chan_updating_pc = 3, + pl330_chan_waiting_event = 4, + pl330_chan_at_barrier = 5, + pl330_chan_queue_busy = 6, + pl330_chan_waiting_periph = 7, + pl330_chan_killing = 8, + pl330_chan_completing = 9, + pl330_chan_fault_completing = 14, + pl330_chan_fault = 15, +} PL330ChanState; + +typedef struct PL330State PL330State; + +typedef struct PL330Chan { + uint32_t src; + uint32_t dst; + uint32_t pc; + uint32_t control; + uint32_t status; + uint32_t lc[2]; + uint32_t fault_type; + uint32_t watchdog_timer; + + bool ns; + uint8_t request_flag; + uint8_t wakeup; + uint8_t wfp_sbp; + + uint8_t state; + uint8_t stall; + + bool is_manager; + PL330State *parent; + uint8_t tag; +} PL330Chan; + +static const VMStateDescription vmstate_pl330_chan = { + .name = "pl330_chan", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(src, PL330Chan), + VMSTATE_UINT32(dst, PL330Chan), + VMSTATE_UINT32(pc, PL330Chan), + VMSTATE_UINT32(control, PL330Chan), + VMSTATE_UINT32(status, PL330Chan), + VMSTATE_UINT32_ARRAY(lc, PL330Chan, 2), + VMSTATE_UINT32(fault_type, PL330Chan), + VMSTATE_UINT32(watchdog_timer, PL330Chan), + VMSTATE_BOOL(ns, PL330Chan), + VMSTATE_UINT8(request_flag, PL330Chan), + VMSTATE_UINT8(wakeup, PL330Chan), + VMSTATE_UINT8(wfp_sbp, PL330Chan), + VMSTATE_UINT8(state, PL330Chan), + VMSTATE_UINT8(stall, PL330Chan), + VMSTATE_END_OF_LIST() + } +}; + +typedef struct PL330Fifo { + uint8_t *buf; + uint8_t *tag; + uint32_t head; + uint32_t num; + uint32_t buf_size; +} PL330Fifo; + +static const VMStateDescription vmstate_pl330_fifo = { + .name = "pl330_chan", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_VBUFFER_UINT32(buf, PL330Fifo, 1, NULL, 0, buf_size), + VMSTATE_VBUFFER_UINT32(tag, PL330Fifo, 1, NULL, 0, buf_size), + VMSTATE_UINT32(head, PL330Fifo), + VMSTATE_UINT32(num, PL330Fifo), + VMSTATE_UINT32(buf_size, PL330Fifo), + VMSTATE_END_OF_LIST() + } +}; + +typedef struct PL330QueueEntry { + uint32_t addr; + uint32_t len; + uint8_t n; + bool inc; + bool z; + uint8_t tag; + uint8_t seqn; +} PL330QueueEntry; + +static const VMStateDescription vmstate_pl330_queue_entry = { + .name = "pl330_queue_entry", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(addr, PL330QueueEntry), + VMSTATE_UINT32(len, PL330QueueEntry), + VMSTATE_UINT8(n, PL330QueueEntry), + VMSTATE_BOOL(inc, PL330QueueEntry), + VMSTATE_BOOL(z, PL330QueueEntry), + VMSTATE_UINT8(tag, PL330QueueEntry), + VMSTATE_UINT8(seqn, PL330QueueEntry), + VMSTATE_END_OF_LIST() + } +}; + +typedef struct PL330Queue { + PL330State *parent; + PL330QueueEntry *queue; + uint32_t queue_size; +} PL330Queue; + +static const VMStateDescription vmstate_pl330_queue = { + .name = "pl330_queue", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT_VARRAY_UINT32(queue, PL330Queue, queue_size, 1, + vmstate_pl330_queue_entry, PL330QueueEntry), + VMSTATE_END_OF_LIST() + } +}; + +struct PL330State { + SysBusDevice busdev; + MemoryRegion iomem; + qemu_irq irq_abort; + qemu_irq *irq; + + /* Config registers. cfg[5] = CfgDn. */ + uint32_t cfg[6]; +#define EVENT_SEC_STATE 3 +#define PERIPH_SEC_STATE 4 + /* cfg 0 bits and pieces */ + uint32_t num_chnls; + uint8_t num_periph_req; + uint8_t num_events; + uint8_t mgr_ns_at_rst; + /* cfg 1 bits and pieces */ + uint8_t i_cache_len; + uint8_t num_i_cache_lines; + /* CRD bits and pieces */ + uint8_t data_width; + uint8_t wr_cap; + uint8_t wr_q_dep; + uint8_t rd_cap; + uint8_t rd_q_dep; + uint16_t data_buffer_dep; + + PL330Chan manager; + PL330Chan *chan; + PL330Fifo fifo; + PL330Queue read_queue; + PL330Queue write_queue; + uint8_t *lo_seqn; + uint8_t *hi_seqn; + QEMUTimer *timer; /* is used for restore dma. */ + + uint32_t inten; + uint32_t int_status; + uint32_t ev_status; + uint32_t dbg[2]; + uint8_t debug_status; + uint8_t num_faulting; + uint8_t periph_busy[PL330_PERIPH_NUM]; + +}; + +#define TYPE_PL330 "pl330" +#define PL330(obj) OBJECT_CHECK(PL330State, (obj), TYPE_PL330) + +static const VMStateDescription vmstate_pl330 = { + .name = "pl330", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(manager, PL330State, 0, vmstate_pl330_chan, PL330Chan), + VMSTATE_STRUCT_VARRAY_UINT32(chan, PL330State, num_chnls, 0, + vmstate_pl330_chan, PL330Chan), + VMSTATE_VBUFFER_UINT32(lo_seqn, PL330State, 1, NULL, 0, num_chnls), + VMSTATE_VBUFFER_UINT32(hi_seqn, PL330State, 1, NULL, 0, num_chnls), + VMSTATE_STRUCT(fifo, PL330State, 0, vmstate_pl330_fifo, PL330Fifo), + VMSTATE_STRUCT(read_queue, PL330State, 0, vmstate_pl330_queue, + PL330Queue), + VMSTATE_STRUCT(write_queue, PL330State, 0, vmstate_pl330_queue, + PL330Queue), + VMSTATE_TIMER(timer, PL330State), + VMSTATE_UINT32(inten, PL330State), + VMSTATE_UINT32(int_status, PL330State), + VMSTATE_UINT32(ev_status, PL330State), + VMSTATE_UINT32_ARRAY(dbg, PL330State, 2), + VMSTATE_UINT8(debug_status, PL330State), + VMSTATE_UINT8(num_faulting, PL330State), + VMSTATE_UINT8_ARRAY(periph_busy, PL330State, PL330_PERIPH_NUM), + VMSTATE_END_OF_LIST() + } +}; + +typedef struct PL330InsnDesc { + /* OPCODE of the instruction */ + uint8_t opcode; + /* Mask so we can select several sibling instructions, such as + DMALD, DMALDS and DMALDB */ + uint8_t opmask; + /* Size of instruction in bytes */ + uint8_t size; + /* Interpreter */ + void (*exec)(PL330Chan *, uint8_t opcode, uint8_t *args, int len); +} PL330InsnDesc; + + +/* MFIFO Implementation + * + * MFIFO is implemented as a cyclic buffer of BUF_SIZE size. Tagged bytes are + * stored in this buffer. Data is stored in BUF field, tags - in the + * corresponding array elements of TAG field. + */ + +/* Initialize queue. */ + +static void pl330_fifo_init(PL330Fifo *s, uint32_t size) +{ + s->buf = g_malloc0(size); + s->tag = g_malloc0(size); + s->buf_size = size; +} + +/* Cyclic increment */ + +static inline int pl330_fifo_inc(PL330Fifo *s, int x) +{ + return (x + 1) % s->buf_size; +} + +/* Number of empty bytes in MFIFO */ + +static inline int pl330_fifo_num_free(PL330Fifo *s) +{ + return s->buf_size - s->num; +} + +/* Push LEN bytes of data stored in BUF to MFIFO and tag it with TAG. + * Zero returned on success, PL330_FIFO_STALL if there is no enough free + * space in MFIFO to store requested amount of data. If push was unsuccessful + * no data is stored to MFIFO. + */ + +static int pl330_fifo_push(PL330Fifo *s, uint8_t *buf, int len, uint8_t tag) +{ + int i; + + if (s->buf_size - s->num < len) { + return PL330_FIFO_STALL; + } + for (i = 0; i < len; i++) { + int push_idx = (s->head + s->num + i) % s->buf_size; + s->buf[push_idx] = buf[i]; + s->tag[push_idx] = tag; + } + s->num += len; + return PL330_FIFO_OK; +} + +/* Get LEN bytes of data from MFIFO and store it to BUF. Tag value of each + * byte is verified. Zero returned on success, PL330_FIFO_ERR on tag mismatch + * and PL330_FIFO_STALL if there is no enough data in MFIFO. If get was + * unsuccessful no data is removed from MFIFO. + */ + +static int pl330_fifo_get(PL330Fifo *s, uint8_t *buf, int len, uint8_t tag) +{ + int i; + + if (s->num < len) { + return PL330_FIFO_STALL; + } + for (i = 0; i < len; i++) { + if (s->tag[s->head] == tag) { + int get_idx = (s->head + i) % s->buf_size; + buf[i] = s->buf[get_idx]; + } else { /* Tag mismatch - Rollback transaction */ + return PL330_FIFO_ERR; + } + } + s->head = (s->head + len) % s->buf_size; + s->num -= len; + return PL330_FIFO_OK; +} + +/* Reset MFIFO. This completely erases all data in it. */ + +static inline void pl330_fifo_reset(PL330Fifo *s) +{ + s->head = 0; + s->num = 0; +} + +/* Return tag of the first byte stored in MFIFO. If MFIFO is empty + * PL330_UNTAGGED is returned. + */ + +static inline uint8_t pl330_fifo_tag(PL330Fifo *s) +{ + return (!s->num) ? PL330_UNTAGGED : s->tag[s->head]; +} + +/* Returns non-zero if tag TAG is present in fifo or zero otherwise */ + +static int pl330_fifo_has_tag(PL330Fifo *s, uint8_t tag) +{ + int i, n; + + i = s->head; + for (n = 0; n < s->num; n++) { + if (s->tag[i] == tag) { + return 1; + } + i = pl330_fifo_inc(s, i); + } + return 0; +} + +/* Remove all entry tagged with TAG from MFIFO */ + +static void pl330_fifo_tagged_remove(PL330Fifo *s, uint8_t tag) +{ + int i, t, n; + + t = i = s->head; + for (n = 0; n < s->num; n++) { + if (s->tag[i] != tag) { + s->buf[t] = s->buf[i]; + s->tag[t] = s->tag[i]; + t = pl330_fifo_inc(s, t); + } else { + s->num = s->num - 1; + } + i = pl330_fifo_inc(s, i); + } +} + +/* Read-Write Queue implementation + * + * A Read-Write Queue stores up to QUEUE_SIZE instructions (loads or stores). + * Each instruction is described by source (for loads) or destination (for + * stores) address ADDR, width of data to be loaded/stored LEN, number of + * stores/loads to be performed N, INC bit, Z bit and TAG to identify channel + * this instruction belongs to. Queue does not store any information about + * nature of the instruction: is it load or store. PL330 has different queues + * for loads and stores so this is already known at the top level where it + * matters. + * + * Queue works as FIFO for instructions with equivalent tags, but can issue + * instructions with different tags in arbitrary order. SEQN field attached to + * each instruction helps to achieve this. For each TAG queue contains + * instructions with consecutive SEQN values ranging from LO_SEQN[TAG] to + * HI_SEQN[TAG]-1 inclusive. SEQN is 8-bit unsigned integer, so SEQN=255 is + * followed by SEQN=0. + * + * Z bit indicates that zeroes should be stored. No MFIFO fetches are performed + * in this case. + */ + +static void pl330_queue_reset(PL330Queue *s) +{ + int i; + + for (i = 0; i < s->queue_size; i++) { + s->queue[i].tag = PL330_UNTAGGED; + } +} + +/* Initialize queue */ +static void pl330_queue_init(PL330Queue *s, int size, PL330State *parent) +{ + s->parent = parent; + s->queue = g_new0(PL330QueueEntry, size); + s->queue_size = size; +} + +/* Returns pointer to an empty slot or NULL if queue is full */ +static PL330QueueEntry *pl330_queue_find_empty(PL330Queue *s) +{ + int i; + + for (i = 0; i < s->queue_size; i++) { + if (s->queue[i].tag == PL330_UNTAGGED) { + return &s->queue[i]; + } + } + return NULL; +} + +/* Put instruction in queue. + * Return value: + * - zero - OK + * - non-zero - queue is full + */ + +static int pl330_queue_put_insn(PL330Queue *s, uint32_t addr, + int len, int n, bool inc, bool z, uint8_t tag) +{ + PL330QueueEntry *entry = pl330_queue_find_empty(s); + + if (!entry) { + return 1; + } + entry->tag = tag; + entry->addr = addr; + entry->len = len; + entry->n = n; + entry->z = z; + entry->inc = inc; + entry->seqn = s->parent->hi_seqn[tag]; + s->parent->hi_seqn[tag]++; + return 0; +} + +/* Returns a pointer to queue slot containing instruction which satisfies + * following conditions: + * - it has valid tag value (not PL330_UNTAGGED) + * - if enforce_seq is set it has to be issuable without violating queue + * logic (see above) + * - if TAG argument is not PL330_UNTAGGED this instruction has tag value + * equivalent to the argument TAG value. + * If such instruction cannot be found NULL is returned. + */ + +static PL330QueueEntry *pl330_queue_find_insn(PL330Queue *s, uint8_t tag, + bool enforce_seq) +{ + int i; + + for (i = 0; i < s->queue_size; i++) { + if (s->queue[i].tag != PL330_UNTAGGED) { + if ((!enforce_seq || + s->queue[i].seqn == s->parent->lo_seqn[s->queue[i].tag]) && + (s->queue[i].tag == tag || tag == PL330_UNTAGGED || + s->queue[i].z)) { + return &s->queue[i]; + } + } + } + return NULL; +} + +/* Removes instruction from queue. */ + +static inline void pl330_queue_remove_insn(PL330Queue *s, PL330QueueEntry *e) +{ + s->parent->lo_seqn[e->tag]++; + e->tag = PL330_UNTAGGED; +} + +/* Removes all instructions tagged with TAG from queue. */ + +static inline void pl330_queue_remove_tagged(PL330Queue *s, uint8_t tag) +{ + int i; + + for (i = 0; i < s->queue_size; i++) { + if (s->queue[i].tag == tag) { + s->queue[i].tag = PL330_UNTAGGED; + } + } +} + +/* DMA instruction execution engine */ + +/* Moves DMA channel to the FAULT state and updates it's status. */ + +static inline void pl330_fault(PL330Chan *ch, uint32_t flags) +{ + DB_PRINT("ch: %p, flags: %x\n", ch, flags); + ch->fault_type |= flags; + if (ch->state == pl330_chan_fault) { + return; + } + ch->state = pl330_chan_fault; + ch->parent->num_faulting++; + if (ch->parent->num_faulting == 1) { + DB_PRINT("abort interrupt raised\n"); + qemu_irq_raise(ch->parent->irq_abort); + } +} + +/* + * For information about instructions see PL330 Technical Reference Manual. + * + * Arguments: + * CH - channel executing the instruction + * OPCODE - opcode + * ARGS - array of 8-bit arguments + * LEN - number of elements in ARGS array + */ + +static void pl330_dmaaddh(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) +{ + uint16_t im = (((uint16_t)args[1]) << 8) | ((uint16_t)args[0]); + uint8_t ra = (opcode >> 1) & 1; + + if (ch->is_manager) { + pl330_fault(ch, PL330_FAULT_UNDEF_INSTR); + return; + } + if (ra) { + ch->dst += im; + } else { + ch->src += im; + } +} + +static void pl330_dmaend(PL330Chan *ch, uint8_t opcode, + uint8_t *args, int len) +{ + PL330State *s = ch->parent; + + if (ch->state == pl330_chan_executing && !ch->is_manager) { + /* Wait for all transfers to complete */ + if (pl330_fifo_has_tag(&s->fifo, ch->tag) || + pl330_queue_find_insn(&s->read_queue, ch->tag, false) != NULL || + pl330_queue_find_insn(&s->write_queue, ch->tag, false) != NULL) { + + ch->stall = 1; + return; + } + } + DB_PRINT("DMA ending!\n"); + pl330_fifo_tagged_remove(&s->fifo, ch->tag); + pl330_queue_remove_tagged(&s->read_queue, ch->tag); + pl330_queue_remove_tagged(&s->write_queue, ch->tag); + ch->state = pl330_chan_stopped; +} + +static void pl330_dmaflushp(PL330Chan *ch, uint8_t opcode, + uint8_t *args, int len) +{ + uint8_t periph_id; + + if (args[0] & 7) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + periph_id = (args[0] >> 3) & 0x1f; + if (periph_id >= ch->parent->num_periph_req) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) { + pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR); + return; + } + /* Do nothing */ +} + +static void pl330_dmago(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) +{ + uint8_t chan_id; + uint8_t ns; + uint32_t pc; + PL330Chan *s; + + DB_PRINT("\n"); + + if (!ch->is_manager) { + pl330_fault(ch, PL330_FAULT_UNDEF_INSTR); + return; + } + ns = !!(opcode & 2); + chan_id = args[0] & 7; + if ((args[0] >> 3)) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + if (chan_id >= ch->parent->num_chnls) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + pc = (((uint32_t)args[4]) << 24) | (((uint32_t)args[3]) << 16) | + (((uint32_t)args[2]) << 8) | (((uint32_t)args[1])); + if (ch->parent->chan[chan_id].state != pl330_chan_stopped) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + if (ch->ns && !ns) { + pl330_fault(ch, PL330_FAULT_DMAGO_ERR); + return; + } + s = &ch->parent->chan[chan_id]; + s->ns = ns; + s->pc = pc; + s->state = pl330_chan_executing; +} + +static void pl330_dmald(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) +{ + uint8_t bs = opcode & 3; + uint32_t size, num; + bool inc; + + if (bs == 2) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + if ((bs == 1 && ch->request_flag == PL330_BURST) || + (bs == 3 && ch->request_flag == PL330_SINGLE)) { + /* Perform NOP */ + return; + } + if (bs == 1 && ch->request_flag == PL330_SINGLE) { + num = 1; + } else { + num = ((ch->control >> 4) & 0xf) + 1; + } + size = (uint32_t)1 << ((ch->control >> 1) & 0x7); + inc = !!(ch->control & 1); + ch->stall = pl330_queue_put_insn(&ch->parent->read_queue, ch->src, + size, num, inc, 0, ch->tag); + if (!ch->stall) { + DB_PRINT("channel:%d address:%08x size:%d num:%d %c\n", + ch->tag, ch->src, size, num, inc ? 'Y' : 'N'); + ch->src += inc ? size * num - (ch->src & (size - 1)) : 0; + } +} + +static void pl330_dmaldp(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) +{ + uint8_t periph_id; + + if (args[0] & 7) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + periph_id = (args[0] >> 3) & 0x1f; + if (periph_id >= ch->parent->num_periph_req) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) { + pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR); + return; + } + pl330_dmald(ch, opcode, args, len); +} + +static void pl330_dmalp(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) +{ + uint8_t lc = (opcode & 2) >> 1; + + ch->lc[lc] = args[0]; +} + +static void pl330_dmakill(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) +{ + if (ch->state == pl330_chan_fault || + ch->state == pl330_chan_fault_completing) { + /* This is the only way for a channel to leave the faulting state */ + ch->fault_type = 0; + ch->parent->num_faulting--; + if (ch->parent->num_faulting == 0) { + DB_PRINT("abort interrupt lowered\n"); + qemu_irq_lower(ch->parent->irq_abort); + } + } + ch->state = pl330_chan_killing; + pl330_fifo_tagged_remove(&ch->parent->fifo, ch->tag); + pl330_queue_remove_tagged(&ch->parent->read_queue, ch->tag); + pl330_queue_remove_tagged(&ch->parent->write_queue, ch->tag); + ch->state = pl330_chan_stopped; +} + +static void pl330_dmalpend(PL330Chan *ch, uint8_t opcode, + uint8_t *args, int len) +{ + uint8_t nf = (opcode & 0x10) >> 4; + uint8_t bs = opcode & 3; + uint8_t lc = (opcode & 4) >> 2; + + if (bs == 2) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + if ((bs == 1 && ch->request_flag == PL330_BURST) || + (bs == 3 && ch->request_flag == PL330_SINGLE)) { + /* Perform NOP */ + return; + } + if (!nf || ch->lc[lc]) { + if (nf) { + ch->lc[lc]--; + } + DB_PRINT("loop reiteration\n"); + ch->pc -= args[0]; + ch->pc -= len + 1; + /* "ch->pc -= args[0] + len + 1" is incorrect when args[0] == 256 */ + } else { + DB_PRINT("loop fallthrough\n"); + } +} + + +static void pl330_dmamov(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) +{ + uint8_t rd = args[0] & 7; + uint32_t im; + + if ((args[0] >> 3)) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + im = (((uint32_t)args[4]) << 24) | (((uint32_t)args[3]) << 16) | + (((uint32_t)args[2]) << 8) | (((uint32_t)args[1])); + switch (rd) { + case 0: + ch->src = im; + break; + case 1: + ch->control = im; + break; + case 2: + ch->dst = im; + break; + default: + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } +} + +static void pl330_dmanop(PL330Chan *ch, uint8_t opcode, + uint8_t *args, int len) +{ + /* NOP is NOP. */ +} + +static void pl330_dmarmb(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) +{ + if (pl330_queue_find_insn(&ch->parent->read_queue, ch->tag, false)) { + ch->state = pl330_chan_at_barrier; + ch->stall = 1; + return; + } else { + ch->state = pl330_chan_executing; + } +} + +static void pl330_dmasev(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) +{ + uint8_t ev_id; + + if (args[0] & 7) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + ev_id = (args[0] >> 3) & 0x1f; + if (ev_id >= ch->parent->num_events) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + if (ch->ns && !(ch->parent->cfg[CFG_INS] & (1 << ev_id))) { + pl330_fault(ch, PL330_FAULT_EVENT_ERR); + return; + } + if (ch->parent->inten & (1 << ev_id)) { + ch->parent->int_status |= (1 << ev_id); + DB_PRINT("event interrupt raised %d\n", ev_id); + qemu_irq_raise(ch->parent->irq[ev_id]); + } else { + ch->parent->ev_status |= (1 << ev_id); + } +} + +static void pl330_dmast(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) +{ + uint8_t bs = opcode & 3; + uint32_t size, num; + bool inc; + + if (bs == 2) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + if ((bs == 1 && ch->request_flag == PL330_BURST) || + (bs == 3 && ch->request_flag == PL330_SINGLE)) { + /* Perform NOP */ + return; + } + num = ((ch->control >> 18) & 0xf) + 1; + size = (uint32_t)1 << ((ch->control >> 15) & 0x7); + inc = !!((ch->control >> 14) & 1); + ch->stall = pl330_queue_put_insn(&ch->parent->write_queue, ch->dst, + size, num, inc, 0, ch->tag); + if (!ch->stall) { + DB_PRINT("channel:%d address:%08x size:%d num:%d %c\n", + ch->tag, ch->dst, size, num, inc ? 'Y' : 'N'); + ch->dst += inc ? size * num - (ch->dst & (size - 1)) : 0; + } +} + +static void pl330_dmastp(PL330Chan *ch, uint8_t opcode, + uint8_t *args, int len) +{ + uint8_t periph_id; + + if (args[0] & 7) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + periph_id = (args[0] >> 3) & 0x1f; + if (periph_id >= ch->parent->num_periph_req) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) { + pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR); + return; + } + pl330_dmast(ch, opcode, args, len); +} + +static void pl330_dmastz(PL330Chan *ch, uint8_t opcode, + uint8_t *args, int len) +{ + uint32_t size, num; + bool inc; + + num = ((ch->control >> 18) & 0xf) + 1; + size = (uint32_t)1 << ((ch->control >> 15) & 0x7); + inc = !!((ch->control >> 14) & 1); + ch->stall = pl330_queue_put_insn(&ch->parent->write_queue, ch->dst, + size, num, inc, 1, ch->tag); + if (inc) { + ch->dst += size * num; + } +} + +static void pl330_dmawfe(PL330Chan *ch, uint8_t opcode, + uint8_t *args, int len) +{ + uint8_t ev_id; + int i; + + if (args[0] & 5) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + ev_id = (args[0] >> 3) & 0x1f; + if (ev_id >= ch->parent->num_events) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + if (ch->ns && !(ch->parent->cfg[CFG_INS] & (1 << ev_id))) { + pl330_fault(ch, PL330_FAULT_EVENT_ERR); + return; + } + ch->wakeup = ev_id; + ch->state = pl330_chan_waiting_event; + if (~ch->parent->inten & ch->parent->ev_status & 1 << ev_id) { + ch->state = pl330_chan_executing; + /* If anyone else is currently waiting on the same event, let them + * clear the ev_status so they pick up event as well + */ + for (i = 0; i < ch->parent->num_chnls; ++i) { + PL330Chan *peer = &ch->parent->chan[i]; + if (peer->state == pl330_chan_waiting_event && + peer->wakeup == ev_id) { + return; + } + } + ch->parent->ev_status &= ~(1 << ev_id); + } else { + ch->stall = 1; + } +} + +static void pl330_dmawfp(PL330Chan *ch, uint8_t opcode, + uint8_t *args, int len) +{ + uint8_t bs = opcode & 3; + uint8_t periph_id; + + if (args[0] & 7) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + periph_id = (args[0] >> 3) & 0x1f; + if (periph_id >= ch->parent->num_periph_req) { + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) { + pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR); + return; + } + switch (bs) { + case 0: /* S */ + ch->request_flag = PL330_SINGLE; + ch->wfp_sbp = 0; + break; + case 1: /* P */ + ch->request_flag = PL330_BURST; + ch->wfp_sbp = 2; + break; + case 2: /* B */ + ch->request_flag = PL330_BURST; + ch->wfp_sbp = 1; + break; + default: + pl330_fault(ch, PL330_FAULT_OPERAND_INVALID); + return; + } + + if (ch->parent->periph_busy[periph_id]) { + ch->state = pl330_chan_waiting_periph; + ch->stall = 1; + } else if (ch->state == pl330_chan_waiting_periph) { + ch->state = pl330_chan_executing; + } +} + +static void pl330_dmawmb(PL330Chan *ch, uint8_t opcode, + uint8_t *args, int len) +{ + if (pl330_queue_find_insn(&ch->parent->write_queue, ch->tag, false)) { + ch->state = pl330_chan_at_barrier; + ch->stall = 1; + return; + } else { + ch->state = pl330_chan_executing; + } +} + +/* NULL terminated array of the instruction descriptions. */ +static const PL330InsnDesc insn_desc[] = { + { .opcode = 0x54, .opmask = 0xFD, .size = 3, .exec = pl330_dmaaddh, }, + { .opcode = 0x00, .opmask = 0xFF, .size = 1, .exec = pl330_dmaend, }, + { .opcode = 0x35, .opmask = 0xFF, .size = 2, .exec = pl330_dmaflushp, }, + { .opcode = 0xA0, .opmask = 0xFD, .size = 6, .exec = pl330_dmago, }, + { .opcode = 0x04, .opmask = 0xFC, .size = 1, .exec = pl330_dmald, }, + { .opcode = 0x25, .opmask = 0xFD, .size = 2, .exec = pl330_dmaldp, }, + { .opcode = 0x20, .opmask = 0xFD, .size = 2, .exec = pl330_dmalp, }, + /* dmastp must be before dmalpend in this list, because their maps + * are overlapping + */ + { .opcode = 0x29, .opmask = 0xFD, .size = 2, .exec = pl330_dmastp, }, + { .opcode = 0x28, .opmask = 0xE8, .size = 2, .exec = pl330_dmalpend, }, + { .opcode = 0x01, .opmask = 0xFF, .size = 1, .exec = pl330_dmakill, }, + { .opcode = 0xBC, .opmask = 0xFF, .size = 6, .exec = pl330_dmamov, }, + { .opcode = 0x18, .opmask = 0xFF, .size = 1, .exec = pl330_dmanop, }, + { .opcode = 0x12, .opmask = 0xFF, .size = 1, .exec = pl330_dmarmb, }, + { .opcode = 0x34, .opmask = 0xFF, .size = 2, .exec = pl330_dmasev, }, + { .opcode = 0x08, .opmask = 0xFC, .size = 1, .exec = pl330_dmast, }, + { .opcode = 0x0C, .opmask = 0xFF, .size = 1, .exec = pl330_dmastz, }, + { .opcode = 0x36, .opmask = 0xFF, .size = 2, .exec = pl330_dmawfe, }, + { .opcode = 0x30, .opmask = 0xFC, .size = 2, .exec = pl330_dmawfp, }, + { .opcode = 0x13, .opmask = 0xFF, .size = 1, .exec = pl330_dmawmb, }, + { .opcode = 0x00, .opmask = 0x00, .size = 0, .exec = NULL, } +}; + +/* Instructions which can be issued via debug registers. */ +static const PL330InsnDesc debug_insn_desc[] = { + { .opcode = 0xA0, .opmask = 0xFD, .size = 6, .exec = pl330_dmago, }, + { .opcode = 0x01, .opmask = 0xFF, .size = 1, .exec = pl330_dmakill, }, + { .opcode = 0x34, .opmask = 0xFF, .size = 2, .exec = pl330_dmasev, }, + { .opcode = 0x00, .opmask = 0x00, .size = 0, .exec = NULL, } +}; + +static inline const PL330InsnDesc *pl330_fetch_insn(PL330Chan *ch) +{ + uint8_t opcode; + int i; + + dma_memory_read(&dma_context_memory, ch->pc, &opcode, 1); + for (i = 0; insn_desc[i].size; i++) { + if ((opcode & insn_desc[i].opmask) == insn_desc[i].opcode) { + return &insn_desc[i]; + } + } + return NULL; +} + +static inline void pl330_exec_insn(PL330Chan *ch, const PL330InsnDesc *insn) +{ + uint8_t buf[PL330_INSN_MAXSIZE]; + + assert(insn->size <= PL330_INSN_MAXSIZE); + dma_memory_read(&dma_context_memory, ch->pc, buf, insn->size); + insn->exec(ch, buf[0], &buf[1], insn->size - 1); +} + +static inline void pl330_update_pc(PL330Chan *ch, + const PL330InsnDesc *insn) +{ + ch->pc += insn->size; +} + +/* Try to execute current instruction in channel CH. Number of executed + instructions is returned (0 or 1). */ +static int pl330_chan_exec(PL330Chan *ch) +{ + const PL330InsnDesc *insn; + + if (ch->state != pl330_chan_executing && + ch->state != pl330_chan_waiting_periph && + ch->state != pl330_chan_at_barrier && + ch->state != pl330_chan_waiting_event) { + DB_PRINT("%d\n", ch->state); + return 0; + } + ch->stall = 0; + insn = pl330_fetch_insn(ch); + if (!insn) { + DB_PRINT("pl330 undefined instruction\n"); + pl330_fault(ch, PL330_FAULT_UNDEF_INSTR); + return 0; + } + pl330_exec_insn(ch, insn); + if (!ch->stall) { + pl330_update_pc(ch, insn); + ch->watchdog_timer = 0; + return 1; + /* WDT only active in exec state */ + } else if (ch->state == pl330_chan_executing) { + ch->watchdog_timer++; + if (ch->watchdog_timer >= PL330_WATCHDOG_LIMIT) { + pl330_fault(ch, PL330_FAULT_LOCKUP_ERR); + } + } + return 0; +} + +/* Try to execute 1 instruction in each channel, one instruction from read + queue and one instruction from write queue. Number of successfully executed + instructions is returned. */ +static int pl330_exec_cycle(PL330Chan *channel) +{ + PL330State *s = channel->parent; + PL330QueueEntry *q; + int i; + int num_exec = 0; + int fifo_res = 0; + uint8_t buf[PL330_MAX_BURST_LEN]; + + /* Execute one instruction in each channel */ + num_exec += pl330_chan_exec(channel); + + /* Execute one instruction from read queue */ + q = pl330_queue_find_insn(&s->read_queue, PL330_UNTAGGED, true); + if (q != NULL && q->len <= pl330_fifo_num_free(&s->fifo)) { + int len = q->len - (q->addr & (q->len - 1)); + + dma_memory_read(&dma_context_memory, q->addr, buf, len); + if (PL330_ERR_DEBUG > 1) { + DB_PRINT("PL330 read from memory @%08x (size = %08x):\n", + q->addr, len); + hexdump((char *)buf, stderr, "", len); + } + fifo_res = pl330_fifo_push(&s->fifo, buf, len, q->tag); + if (fifo_res == PL330_FIFO_OK) { + if (q->inc) { + q->addr += len; + } + q->n--; + if (!q->n) { + pl330_queue_remove_insn(&s->read_queue, q); + } + num_exec++; + } + } + + /* Execute one instruction from write queue. */ + q = pl330_queue_find_insn(&s->write_queue, pl330_fifo_tag(&s->fifo), true); + if (q != NULL) { + int len = q->len - (q->addr & (q->len - 1)); + + if (q->z) { + for (i = 0; i < len; i++) { + buf[i] = 0; + } + } else { + fifo_res = pl330_fifo_get(&s->fifo, buf, len, q->tag); + } + if (fifo_res == PL330_FIFO_OK || q->z) { + dma_memory_write(&dma_context_memory, q->addr, buf, len); + if (PL330_ERR_DEBUG > 1) { + DB_PRINT("PL330 read from memory @%08x (size = %08x):\n", + q->addr, len); + hexdump((char *)buf, stderr, "", len); + } + if (q->inc) { + q->addr += len; + } + num_exec++; + } else if (fifo_res == PL330_FIFO_STALL) { + pl330_fault(&channel->parent->chan[q->tag], + PL330_FAULT_FIFOEMPTY_ERR); + } + q->n--; + if (!q->n) { + pl330_queue_remove_insn(&s->write_queue, q); + } + } + + return num_exec; +} + +static int pl330_exec_channel(PL330Chan *channel) +{ + int insr_exec = 0; + + /* TODO: Is it all right to execute everything or should we do per-cycle + simulation? */ + while (pl330_exec_cycle(channel)) { + insr_exec++; + } + + /* Detect deadlock */ + if (channel->state == pl330_chan_executing) { + pl330_fault(channel, PL330_FAULT_LOCKUP_ERR); + } + /* Situation when one of the queues has deadlocked but all channels + * have finished their programs should be impossible. + */ + + return insr_exec; +} + +static inline void pl330_exec(PL330State *s) +{ + DB_PRINT("\n"); + int i, insr_exec; + do { + insr_exec = pl330_exec_channel(&s->manager); + + for (i = 0; i < s->num_chnls; i++) { + insr_exec += pl330_exec_channel(&s->chan[i]); + } + } while (insr_exec); +} + +static void pl330_exec_cycle_timer(void *opaque) +{ + PL330State *s = (PL330State *)opaque; + pl330_exec(s); +} + +/* Stop or restore dma operations */ + +static void pl330_dma_stop_irq(void *opaque, int irq, int level) +{ + PL330State *s = (PL330State *)opaque; + + if (s->periph_busy[irq] != level) { + s->periph_busy[irq] = level; + qemu_mod_timer(s->timer, qemu_get_clock_ns(vm_clock)); + } +} + +static void pl330_debug_exec(PL330State *s) +{ + uint8_t args[5]; + uint8_t opcode; + uint8_t chan_id; + int i; + PL330Chan *ch; + const PL330InsnDesc *insn; + + s->debug_status = 1; + chan_id = (s->dbg[0] >> 8) & 0x07; + opcode = (s->dbg[0] >> 16) & 0xff; + args[0] = (s->dbg[0] >> 24) & 0xff; + args[1] = (s->dbg[1] >> 0) & 0xff; + args[2] = (s->dbg[1] >> 8) & 0xff; + args[3] = (s->dbg[1] >> 16) & 0xff; + args[4] = (s->dbg[1] >> 24) & 0xff; + DB_PRINT("chan id: %d\n", chan_id); + if (s->dbg[0] & 1) { + ch = &s->chan[chan_id]; + } else { + ch = &s->manager; + } + insn = NULL; + for (i = 0; debug_insn_desc[i].size; i++) { + if ((opcode & debug_insn_desc[i].opmask) == debug_insn_desc[i].opcode) { + insn = &debug_insn_desc[i]; + } + } + if (!insn) { + pl330_fault(ch, PL330_FAULT_UNDEF_INSTR | PL330_FAULT_DBG_INSTR); + return ; + } + ch->stall = 0; + insn->exec(ch, opcode, args, insn->size - 1); + if (ch->fault_type) { + ch->fault_type |= PL330_FAULT_DBG_INSTR; + } + if (ch->stall) { + qemu_log_mask(LOG_UNIMP, "pl330: stall of debug instruction not " + "implemented\n"); + } + s->debug_status = 0; +} + +/* IOMEM mapped registers */ + +static void pl330_iomem_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + PL330State *s = (PL330State *) opaque; + uint32_t i; + + DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)value); + + switch (offset) { + case PL330_REG_INTEN: + s->inten = value; + break; + case PL330_REG_INTCLR: + for (i = 0; i < s->num_events; i++) { + if (s->int_status & s->inten & value & (1 << i)) { + DB_PRINT("event interrupt lowered %d\n", i); + qemu_irq_lower(s->irq[i]); + } + } + s->ev_status &= ~(value & s->inten); + s->int_status &= ~(value & s->inten); + break; + case PL330_REG_DBGCMD: + if ((value & 3) == 0) { + pl330_debug_exec(s); + pl330_exec(s); + } else { + qemu_log_mask(LOG_GUEST_ERROR, "pl330: write of illegal value %u " + "for offset " TARGET_FMT_plx "\n", (unsigned)value, + offset); + } + break; + case PL330_REG_DBGINST0: + DB_PRINT("s->dbg[0] = %08x\n", (unsigned)value); + s->dbg[0] = value; + break; + case PL330_REG_DBGINST1: + DB_PRINT("s->dbg[1] = %08x\n", (unsigned)value); + s->dbg[1] = value; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad write offset " TARGET_FMT_plx + "\n", offset); + break; + } +} + +static inline uint32_t pl330_iomem_read_imp(void *opaque, + hwaddr offset) +{ + PL330State *s = (PL330State *)opaque; + int chan_id; + int i; + uint32_t res; + + if (offset >= PL330_REG_PERIPH_ID && offset < PL330_REG_PERIPH_ID + 32) { + return pl330_id[(offset - PL330_REG_PERIPH_ID) >> 2]; + } + if (offset >= PL330_REG_CR0_BASE && offset < PL330_REG_CR0_BASE + 24) { + return s->cfg[(offset - PL330_REG_CR0_BASE) >> 2]; + } + if (offset >= PL330_REG_CHANCTRL && offset < PL330_REG_DBGSTATUS) { + offset -= PL330_REG_CHANCTRL; + chan_id = offset >> 5; + if (chan_id >= s->num_chnls) { + qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset " + TARGET_FMT_plx "\n", offset); + return 0; + } + switch (offset & 0x1f) { + case 0x00: + return s->chan[chan_id].src; + case 0x04: + return s->chan[chan_id].dst; + case 0x08: + return s->chan[chan_id].control; + case 0x0C: + return s->chan[chan_id].lc[0]; + case 0x10: + return s->chan[chan_id].lc[1]; + default: + qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset " + TARGET_FMT_plx "\n", offset); + return 0; + } + } + if (offset >= PL330_REG_CSR_BASE && offset < 0x400) { + offset -= PL330_REG_CSR_BASE; + chan_id = offset >> 3; + if (chan_id >= s->num_chnls) { + qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset " + TARGET_FMT_plx "\n", offset); + return 0; + } + switch ((offset >> 2) & 1) { + case 0x0: + res = (s->chan[chan_id].ns << 21) | + (s->chan[chan_id].wakeup << 4) | + (s->chan[chan_id].state) | + (s->chan[chan_id].wfp_sbp << 14); + return res; + case 0x1: + return s->chan[chan_id].pc; + default: + qemu_log_mask(LOG_GUEST_ERROR, "pl330: read error\n"); + return 0; + } + } + if (offset >= PL330_REG_FTR_BASE && offset < 0x100) { + offset -= PL330_REG_FTR_BASE; + chan_id = offset >> 2; + if (chan_id >= s->num_chnls) { + qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset " + TARGET_FMT_plx "\n", offset); + return 0; + } + return s->chan[chan_id].fault_type; + } + switch (offset) { + case PL330_REG_DSR: + return (s->manager.ns << 9) | (s->manager.wakeup << 4) | + (s->manager.state & 0xf); + case PL330_REG_DPC: + return s->manager.pc; + case PL330_REG_INTEN: + return s->inten; + case PL330_REG_INT_EVENT_RIS: + return s->ev_status; + case PL330_REG_INTMIS: + return s->int_status; + case PL330_REG_INTCLR: + /* Documentation says that we can't read this register + * but linux kernel does it + */ + return 0; + case PL330_REG_FSRD: + return s->manager.state ? 1 : 0; + case PL330_REG_FSRC: + res = 0; + for (i = 0; i < s->num_chnls; i++) { + if (s->chan[i].state == pl330_chan_fault || + s->chan[i].state == pl330_chan_fault_completing) { + res |= 1 << i; + } + } + return res; + case PL330_REG_FTRD: + return s->manager.fault_type; + case PL330_REG_DBGSTATUS: + return s->debug_status; + default: + qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset " + TARGET_FMT_plx "\n", offset); + } + return 0; +} + +static uint64_t pl330_iomem_read(void *opaque, hwaddr offset, + unsigned size) +{ + int ret = pl330_iomem_read_imp(opaque, offset); + DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, ret); + return ret; +} + +static const MemoryRegionOps pl330_ops = { + .read = pl330_iomem_read, + .write = pl330_iomem_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + } +}; + +/* Controller logic and initialization */ + +static void pl330_chan_reset(PL330Chan *ch) +{ + ch->src = 0; + ch->dst = 0; + ch->pc = 0; + ch->state = pl330_chan_stopped; + ch->watchdog_timer = 0; + ch->stall = 0; + ch->control = 0; + ch->status = 0; + ch->fault_type = 0; +} + +static void pl330_reset(DeviceState *d) +{ + int i; + PL330State *s = PL330(d); + + s->inten = 0; + s->int_status = 0; + s->ev_status = 0; + s->debug_status = 0; + s->num_faulting = 0; + s->manager.ns = s->mgr_ns_at_rst; + pl330_fifo_reset(&s->fifo); + pl330_queue_reset(&s->read_queue); + pl330_queue_reset(&s->write_queue); + + for (i = 0; i < s->num_chnls; i++) { + pl330_chan_reset(&s->chan[i]); + } + for (i = 0; i < s->num_periph_req; i++) { + s->periph_busy[i] = 0; + } + + qemu_del_timer(s->timer); +} + +static void pl330_realize(DeviceState *dev, Error **errp) +{ + int i; + PL330State *s = PL330(dev); + + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq_abort); + memory_region_init_io(&s->iomem, &pl330_ops, s, "dma", PL330_IOMEM_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); + + s->timer = qemu_new_timer_ns(vm_clock, pl330_exec_cycle_timer, s); + + s->cfg[0] = (s->mgr_ns_at_rst ? 0x4 : 0) | + (s->num_periph_req > 0 ? 1 : 0) | + ((s->num_chnls - 1) & 0x7) << 4 | + ((s->num_periph_req - 1) & 0x1f) << 12 | + ((s->num_events - 1) & 0x1f) << 17; + + switch (s->i_cache_len) { + case (4): + s->cfg[1] |= 2; + break; + case (8): + s->cfg[1] |= 3; + break; + case (16): + s->cfg[1] |= 4; + break; + case (32): + s->cfg[1] |= 5; + break; + default: + error_setg(errp, "Bad value for i-cache_len property: %d\n", + s->i_cache_len); + return; + } + s->cfg[1] |= ((s->num_i_cache_lines - 1) & 0xf) << 4; + + s->chan = g_new0(PL330Chan, s->num_chnls); + s->hi_seqn = g_new0(uint8_t, s->num_chnls); + s->lo_seqn = g_new0(uint8_t, s->num_chnls); + for (i = 0; i < s->num_chnls; i++) { + s->chan[i].parent = s; + s->chan[i].tag = (uint8_t)i; + } + s->manager.parent = s; + s->manager.tag = s->num_chnls; + s->manager.is_manager = true; + + s->irq = g_new0(qemu_irq, s->num_events); + for (i = 0; i < s->num_events; i++) { + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); + } + + qdev_init_gpio_in(dev, pl330_dma_stop_irq, PL330_PERIPH_NUM); + + switch (s->data_width) { + case (32): + s->cfg[CFG_CRD] |= 0x2; + break; + case (64): + s->cfg[CFG_CRD] |= 0x3; + break; + case (128): + s->cfg[CFG_CRD] |= 0x4; + break; + default: + error_setg(errp, "Bad value for data_width property: %d\n", + s->data_width); + return; + } + + s->cfg[CFG_CRD] |= ((s->wr_cap - 1) & 0x7) << 4 | + ((s->wr_q_dep - 1) & 0xf) << 8 | + ((s->rd_cap - 1) & 0x7) << 12 | + ((s->rd_q_dep - 1) & 0xf) << 16 | + ((s->data_buffer_dep - 1) & 0x1ff) << 20; + + pl330_queue_init(&s->read_queue, s->rd_q_dep, s); + pl330_queue_init(&s->write_queue, s->wr_q_dep, s); + pl330_fifo_init(&s->fifo, s->data_buffer_dep); +} + +static Property pl330_properties[] = { + /* CR0 */ + DEFINE_PROP_UINT32("num_chnls", PL330State, num_chnls, 8), + DEFINE_PROP_UINT8("num_periph_req", PL330State, num_periph_req, 4), + DEFINE_PROP_UINT8("num_events", PL330State, num_events, 16), + DEFINE_PROP_UINT8("mgr_ns_at_rst", PL330State, mgr_ns_at_rst, 0), + /* CR1 */ + DEFINE_PROP_UINT8("i-cache_len", PL330State, i_cache_len, 4), + DEFINE_PROP_UINT8("num_i-cache_lines", PL330State, num_i_cache_lines, 8), + /* CR2-4 */ + DEFINE_PROP_UINT32("boot_addr", PL330State, cfg[CFG_BOOT_ADDR], 0), + DEFINE_PROP_UINT32("INS", PL330State, cfg[CFG_INS], 0), + DEFINE_PROP_UINT32("PNS", PL330State, cfg[CFG_PNS], 0), + /* CRD */ + DEFINE_PROP_UINT8("data_width", PL330State, data_width, 64), + DEFINE_PROP_UINT8("wr_cap", PL330State, wr_cap, 8), + DEFINE_PROP_UINT8("wr_q_dep", PL330State, wr_q_dep, 16), + DEFINE_PROP_UINT8("rd_cap", PL330State, rd_cap, 8), + DEFINE_PROP_UINT8("rd_q_dep", PL330State, rd_q_dep, 16), + DEFINE_PROP_UINT16("data_buffer_dep", PL330State, data_buffer_dep, 256), + + DEFINE_PROP_END_OF_LIST(), +}; + +static void pl330_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = pl330_realize; + dc->reset = pl330_reset; + dc->props = pl330_properties; + dc->vmsd = &vmstate_pl330; +} + +static const TypeInfo pl330_type_info = { + .name = TYPE_PL330, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(PL330State), + .class_init = pl330_class_init, +}; + +static void pl330_register_types(void) +{ + type_register_static(&pl330_type_info); +} + +type_init(pl330_register_types) From 7451afb67136275f2461f2d23139f2abed1f15b3 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Fri, 15 Mar 2013 16:41:58 +0000 Subject: [PATCH 13/37] xilinx_zynq: added pl330 to machine model Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Message-id: 5bc295bd2aa50dfe573f428574dbd7d8add7b3f8.1361853677.git.peter.crosthwaite@xilinx.com Signed-off-by: Peter Maydell --- hw/arm/xilinx_zynq.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index f78c47e43e..6f362865f9 100644 --- a/hw/arm/xilinx_zynq.c +++ b/hw/arm/xilinx_zynq.c @@ -35,6 +35,10 @@ #define IRQ_OFFSET 32 /* pic interrupts start from index 32 */ +static const int dma_irqs[8] = { + 46, 47, 48, 49, 72, 73, 74, 75 +}; + static struct arm_boot_info zynq_binfo = {}; static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq) @@ -196,6 +200,26 @@ static void zynq_init(QEMUMachineInitArgs *args) sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]); + dev = qdev_create(NULL, "pl330"); + qdev_prop_set_uint8(dev, "num_chnls", 8); + qdev_prop_set_uint8(dev, "num_periph_req", 4); + qdev_prop_set_uint8(dev, "num_events", 16); + + qdev_prop_set_uint8(dev, "data_width", 64); + qdev_prop_set_uint8(dev, "wr_cap", 8); + qdev_prop_set_uint8(dev, "wr_q_dep", 16); + qdev_prop_set_uint8(dev, "rd_cap", 8); + qdev_prop_set_uint8(dev, "rd_q_dep", 16); + qdev_prop_set_uint16(dev, "data_buffer_dep", 256); + + qdev_init_nofail(dev); + busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, 0xF8003000); + sysbus_connect_irq(busdev, 0, pic[45-IRQ_OFFSET]); /* abort irq line */ + for (n = 0; n < 8; ++n) { /* event irqs */ + sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]); + } + zynq_binfo.ram_size = ram_size; zynq_binfo.kernel_filename = kernel_filename; zynq_binfo.kernel_cmdline = kernel_cmdline; From 2790cd911e563f7fec7eeb7856b7f5f54437cc0a Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Fri, 15 Mar 2013 16:41:58 +0000 Subject: [PATCH 14/37] xilinx_spips: Set unused IRQs to NULL Unused CS lines should init to 0 to avoid segfaulting when accessing an unattached QSPI controller. Signed-off-by: Peter Crosthwaite Message-id: c1e45198032106e69e8fe9339fc2e6348d524fcd.1362373359.git.peter.crosthwaite@xilinx.com Signed-off-by: Peter Maydell --- hw/xilinx_spips.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c index 6c21b9668b..853f4e0b4b 100644 --- a/hw/xilinx_spips.c +++ b/hw/xilinx_spips.c @@ -497,7 +497,7 @@ static int xilinx_spips_init(SysBusDevice *dev) s->spi[i] = ssi_create_bus(&dev->qdev, bus_name); } - s->cs_lines = g_new(qemu_irq, s->num_cs * s->num_busses); + s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses); ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[0]); ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[1]); sysbus_init_irq(dev, &s->irq); From e0891bd8bfd3349fc3fecde30e51900059f53f11 Mon Sep 17 00:00:00 2001 From: Nathan Rossi Date: Fri, 15 Mar 2013 16:41:59 +0000 Subject: [PATCH 15/37] xilinx_spips: Fix bus setup conditional check The R_LQPSI_CFG register has the LQSPI_CFG_SEP_BUS and LQSPI_CFG_TWO_MEM bits. Signed-off-by: Nathan Rossi Signed-off-by: Peter Crosthwaite Message-id: d76c8e364c80a42352ae4f0661aff2cd17ad32a4.1362373359.git.peter.crosthwaite@xilinx.com Signed-off-by: Peter Maydell --- hw/xilinx_spips.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c index 853f4e0b4b..efa1449386 100644 --- a/hw/xilinx_spips.c +++ b/hw/xilinx_spips.c @@ -143,8 +143,8 @@ typedef struct { static inline int num_effective_busses(XilinxSPIPS *s) { - return (s->regs[R_LQSPI_STS] & LQSPI_CFG_SEP_BUS && - s->regs[R_LQSPI_STS] & LQSPI_CFG_TWO_MEM) ? s->num_busses : 1; + return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS && + s->regs[R_LQSPI_CFG] & LQSPI_CFG_TWO_MEM) ? s->num_busses : 1; } static void xilinx_spips_update_cs_lines(XilinxSPIPS *s) From 08a9635b68757e18a6a8bf8569353b40bb6c1fd1 Mon Sep 17 00:00:00 2001 From: Nathan Rossi Date: Fri, 15 Mar 2013 16:41:59 +0000 Subject: [PATCH 16/37] xilinx_spips: Add missing dual-bus snoop commands Added additional commands to the switch to check for when snooping commands in dual bus mode setups. Cleaned up code to use an enum. Signed-off-by: Nathan Rossi Signed-off-by: Peter Crosthwaite Message-id: 848c116c711dab0af10729a487968384aadd9faf.1362373359.git.peter.crosthwaite@xilinx.com Signed-off-by: Peter Maydell --- hw/xilinx_spips.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c index efa1449386..3183f7a992 100644 --- a/hw/xilinx_spips.c +++ b/hw/xilinx_spips.c @@ -115,6 +115,19 @@ #define SNOOP_NONE 0xFE #define SNOOP_STRIPING 0 +typedef enum { + READ = 0x3, + FAST_READ = 0xb, + DOR = 0x3b, + QOR = 0x6b, + DIOR = 0xbb, + QIOR = 0xeb, + + PP = 0x2, + DPP = 0xa2, + QPP = 0x32, +} FlashCMD; + typedef struct { SysBusDevice busdev; MemoryRegion iomem; @@ -251,15 +264,19 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s) switch (s->snoop_state) { case (SNOOP_CHECKING): switch (tx) { /* new instruction code */ - case 0x0b: /* dual/quad output read DOR/QOR */ - case 0x6b: + case READ: /* 3 address bytes, no dummy bytes/cycles */ + case PP: + case DPP: + case QPP: + s->snoop_state = 3; + break; + case FAST_READ: /* 3 address bytes, 1 dummy byte */ + case DOR: + case QOR: + case DIOR: /* FIXME: these vary between vendor - set to spansion */ s->snoop_state = 4; break; - /* FIXME: these vary between vendor - set to spansion */ - case 0xbb: /* high performance dual read DIOR */ - s->snoop_state = 4; - break; - case 0xeb: /* high performance quad read QIOR */ + case QIOR: /* 3 address bytes, 2 dummy bytes */ s->snoop_state = 6; break; default: From f8b9fe249a706bfed61e0bb66c73394553696382 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Fri, 15 Mar 2013 16:41:59 +0000 Subject: [PATCH 17/37] xilinx_spips: QOM styling fixes Few fixes for the latest QOM styling guides. Signed-off-by: Peter Crosthwaite Message-id: de9daeee6c142e8b57ad042fd680cedcdc94d2fc.1362373359.git.peter.crosthwaite@xilinx.com Signed-off-by: Peter Maydell --- hw/xilinx_spips.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c index 3183f7a992..b2397f4a42 100644 --- a/hw/xilinx_spips.c +++ b/hw/xilinx_spips.c @@ -154,6 +154,11 @@ typedef struct { hwaddr lqspi_cached_addr; } XilinxSPIPS; +#define TYPE_XILINX_SPIPS "xilinx,spips" + +#define XILINX_SPIPS(obj) \ + OBJECT_CHECK(XilinxSPIPS, (obj), TYPE_XILINX_SPIPS) + static inline int num_effective_busses(XilinxSPIPS *s) { return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS && @@ -210,7 +215,7 @@ static void xilinx_spips_update_ixr(XilinxSPIPS *s) static void xilinx_spips_reset(DeviceState *d) { - XilinxSPIPS *s = DO_UPCAST(XilinxSPIPS, busdev.qdev, d); + XilinxSPIPS *s = XILINX_SPIPS(d); int i; for (i = 0; i < R_MAX; i++) { @@ -500,9 +505,10 @@ static const MemoryRegionOps lqspi_ops = { } }; -static int xilinx_spips_init(SysBusDevice *dev) +static void xilinx_spips_realize(DeviceState *dev, Error **errp) { - XilinxSPIPS *s = FROM_SYSBUS(typeof(*s), dev); + XilinxSPIPS *s = XILINX_SPIPS(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); int i; DB_PRINT("inited device model\n"); @@ -511,31 +517,29 @@ static int xilinx_spips_init(SysBusDevice *dev) for (i = 0; i < s->num_busses; ++i) { char bus_name[16]; snprintf(bus_name, 16, "spi%d", i); - s->spi[i] = ssi_create_bus(&dev->qdev, bus_name); + s->spi[i] = ssi_create_bus(dev, bus_name); } s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses); ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[0]); ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[1]); - sysbus_init_irq(dev, &s->irq); + sysbus_init_irq(sbd, &s->irq); for (i = 0; i < s->num_cs * s->num_busses; ++i) { - sysbus_init_irq(dev, &s->cs_lines[i]); + sysbus_init_irq(sbd, &s->cs_lines[i]); } memory_region_init_io(&s->iomem, &spips_ops, s, "spi", R_MAX*4); - sysbus_init_mmio(dev, &s->iomem); + sysbus_init_mmio(sbd, &s->iomem); memory_region_init_io(&s->mmlqspi, &lqspi_ops, s, "lqspi", (1 << LQSPI_ADDRESS_BITS) * 2); - sysbus_init_mmio(dev, &s->mmlqspi); + sysbus_init_mmio(sbd, &s->mmlqspi); s->irqline = -1; s->lqspi_cached_addr = ~0ULL; fifo8_create(&s->rx_fifo, RXFF_A); fifo8_create(&s->tx_fifo, TXFF_A); - - return 0; } static int xilinx_spips_post_load(void *opaque, int version_id) @@ -569,16 +573,15 @@ static Property xilinx_spips_properties[] = { static void xilinx_spips_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); - sdc->init = xilinx_spips_init; + dc->realize = xilinx_spips_realize; dc->reset = xilinx_spips_reset; dc->props = xilinx_spips_properties; dc->vmsd = &vmstate_xilinx_spips; } static const TypeInfo xilinx_spips_info = { - .name = "xilinx,spips", + .name = TYPE_XILINX_SPIPS, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(XilinxSPIPS), .class_init = xilinx_spips_class_init, From 8b758d0568a986d58c254b3c209691c82e0f82a1 Mon Sep 17 00:00:00 2001 From: Petar Jovanovic Date: Fri, 15 Mar 2013 18:56:19 +0100 Subject: [PATCH 18/37] target-mips: fix rndrashift_short_acc and code for EXTR_ instructions Fix for rndrashift_short_acc to set correct value to higher 64 bits. This change also corrects conditions when bit 23 of the DSPControl register is set. The existing test files have been extended with several examples that trigger the issues. One bug/example in the test file for EXTR_RS_W has been found and reported by Klaus Peichl. Signed-off-by: Petar Jovanovic Signed-off-by: Aurelien Jarno --- target-mips/dsp_helper.c | 23 ++++++-------- tests/tcg/mips/mips32-dsp/extr_r_w.c | 23 ++++++++++++++ tests/tcg/mips/mips32-dsp/extr_rs_w.c | 46 +++++++++++++++++++++++++++ tests/tcg/mips/mips32-dsp/extr_w.c | 23 ++++++++++++++ 4 files changed, 101 insertions(+), 14 deletions(-) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 472be35bbf..c7df595c9b 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -517,13 +517,8 @@ static inline void mipsdsp_rndrashift_short_acc(int64_t *p, acc = ((int64_t)env->active_tc.HI[ac] << 32) | ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF); - if (shift == 0) { - p[0] = acc << 1; - p[1] = (acc >> 63) & 0x01; - } else { - p[0] = acc >> (shift - 1); - p[1] = 0; - } + p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1)); + p[1] = (acc >> 63) & 0x01; } /* 128 bits long. p[0] is LO, p[1] is HI */ @@ -3161,8 +3156,8 @@ target_ulong helper_extr_w(target_ulong ac, target_ulong shift, tempDL[1] += 1; } - if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) && - (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) { + if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && + ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { set_DSPControl_overflow_flag(1, 23, env); } @@ -3187,8 +3182,8 @@ target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift, tempDL[1] += 1; } - if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && - (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { + if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && + ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { set_DSPControl_overflow_flag(1, 23, env); } @@ -3214,9 +3209,9 @@ target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift, } tempI = tempDL[0] >> 1; - if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && - (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { - temp64 = tempDL[1]; + if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && + ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { + temp64 = tempDL[1] & 0x01; if (temp64 == 0) { tempI = 0x7FFFFFFF; } else { diff --git a/tests/tcg/mips/mips32-dsp/extr_r_w.c b/tests/tcg/mips/mips32-dsp/extr_r_w.c index 02e022427a..489c1931b4 100644 --- a/tests/tcg/mips/mips32-dsp/extr_r_w.c +++ b/tests/tcg/mips/mips32-dsp/extr_r_w.c @@ -67,5 +67,28 @@ int main() assert(dsp == 0); assert(result == rt); + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0xFFFFFFFF; + acl = 0xFFFFFFFF; + result = 0; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_r.w %0, $ac1, 0x1F\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + return 0; } diff --git a/tests/tcg/mips/mips32-dsp/extr_rs_w.c b/tests/tcg/mips/mips32-dsp/extr_rs_w.c index c3a22ee704..f9d2ed646f 100644 --- a/tests/tcg/mips/mips32-dsp/extr_rs_w.c +++ b/tests/tcg/mips/mips32-dsp/extr_rs_w.c @@ -67,5 +67,51 @@ int main() assert(dsp == 0); assert(result == rt); + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0x80000000; + acl = 0x00000000; + result = 0x80000000; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_rs.w %0, $ac1, 0x1F\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 1); + assert(result == rt); + + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0xFFFFFFFF; + acl = 0xFFFFFFFF; + result = 0; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr_rs.w %0, $ac1, 0x1F\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + return 0; } diff --git a/tests/tcg/mips/mips32-dsp/extr_w.c b/tests/tcg/mips/mips32-dsp/extr_w.c index bd6b0b95c2..cf926146d5 100644 --- a/tests/tcg/mips/mips32-dsp/extr_w.c +++ b/tests/tcg/mips/mips32-dsp/extr_w.c @@ -67,5 +67,28 @@ int main() assert(dsp == 0); assert(result == rt); + /* Clear dspcontrol */ + dsp = 0; + __asm + ("wrdsp %0\n\t" + : + : "r"(dsp) + ); + + ach = 0xFFFFFFFF; + acl = 0xFFFFFFFF; + result = 0xFFFFFFFF; + __asm + ("mthi %2, $ac1\n\t" + "mtlo %3, $ac1\n\t" + "extr.w %0, $ac1, 0x1F\n\t" + "rddsp %1\n\t" + : "=r"(rt), "=r"(dsp) + : "r"(ach), "r"(acl) + ); + dsp = (dsp >> 23) & 0x01; + assert(dsp == 0); + assert(result == rt); + return 0; } From 225dc991b03f0f034aa348f5cf499de9d0979107 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 15 Mar 2013 10:57:40 +0100 Subject: [PATCH 19/37] s390: Fix cpu refactoring fallout. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 259186a7 "cpu: Move halted and interrupt_request fields to CPUState" seems to have missed one instance in target-s390x/kvm.c: /home/cohuck/git/qemu/target-s390x/kvm.c: In function ‘kvm_arch_process_async_events’: /home/cohuck/git/qemu/target-s390x/kvm.c:319: error: ‘CPUS390XState’ has no member named ‘halted’ /home/cohuck/git/qemu/target-s390x/kvm.c:320: warning: control reaches end of non-void function make[1]: *** [target-s390x/kvm.o] Error 1 Let's just switch to cs->halted. Signed-off-by: Cornelia Huck Acked-by: Alexander Graf Acked-by: Andreas Färber Signed-off-by: Blue Swirl --- target-s390x/kvm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 8f111ae732..644f484c48 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -315,8 +315,7 @@ void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run) int kvm_arch_process_async_events(CPUState *cs) { - S390CPU *cpu = S390_CPU(cs); - return cpu->env.halted; + return cs->halted; } void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm, From 7c20b4a374d0016e3fce005690fb428354a56621 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 13 Nov 2012 14:51:41 +0100 Subject: [PATCH 20/37] console: fix displaychangelisteners interface Split callbacks into separate Ops struct. Pass DisplayChangeListener pointer as first argument to all callbacks. Uninline a bunch of display functions and move them from console.h to console.c Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 18 ++-- include/ui/console.h | 205 ++++++++++--------------------------- include/ui/spice-display.h | 1 + trace-events | 2 + ui/cocoa.m | 26 +++-- ui/console.c | 144 ++++++++++++++++++++++++++ ui/curses.c | 32 ++++-- ui/gtk.c | 30 ++++-- ui/sdl.c | 44 +++++--- ui/spice-display.c | 19 ++-- ui/vnc.c | 44 +++++--- vl.c | 6 +- 12 files changed, 344 insertions(+), 227 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index ef693486c2..fe1c4f1a35 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1866,21 +1866,25 @@ static void qxl_vm_change_state_handler(void *opaque, int running, /* display change listener */ -static void display_update(struct DisplayState *ds, int x, int y, int w, int h) +static void display_update(DisplayChangeListener *dcl, + struct DisplayState *ds, + int x, int y, int w, int h) { if (qxl0->mode == QXL_MODE_VGA) { qemu_spice_display_update(&qxl0->ssd, x, y, w, h); } } -static void display_resize(struct DisplayState *ds) +static void display_resize(DisplayChangeListener *dcl, + struct DisplayState *ds) { if (qxl0->mode == QXL_MODE_VGA) { qemu_spice_display_resize(&qxl0->ssd); } } -static void display_refresh(struct DisplayState *ds) +static void display_refresh(DisplayChangeListener *dcl, + struct DisplayState *ds) { if (qxl0->mode == QXL_MODE_VGA) { qemu_spice_display_refresh(&qxl0->ssd); @@ -1891,10 +1895,11 @@ static void display_refresh(struct DisplayState *ds) } } -static DisplayChangeListener display_listener = { +static DisplayChangeListenerOps display_listener_ops = { + .dpy_name = "spice/qxl", .dpy_gfx_update = display_update, .dpy_gfx_resize = display_resize, - .dpy_refresh = display_refresh, + .dpy_refresh = display_refresh, }; static void qxl_init_ramsize(PCIQXLDevice *qxl) @@ -2076,7 +2081,8 @@ static int qxl_init_primary(PCIDevice *dev) return rc; } - register_displaychangelistener(vga->ds, &display_listener); + qxl->ssd.dcl.ops = &display_listener_ops; + register_displaychangelistener(vga->ds, &qxl->ssd.dcl); return rc; } diff --git a/include/ui/console.h b/include/ui/console.h index a37cf65602..bf54f1ea54 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -147,24 +147,46 @@ void cursor_set_mono(QEMUCursor *c, void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *mask); void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask); +typedef struct DisplayChangeListenerOps { + const char *dpy_name; + + void (*dpy_refresh)(DisplayChangeListener *dcl, + struct DisplayState *s); + + void (*dpy_gfx_update)(DisplayChangeListener *dcl, + struct DisplayState *s, + int x, int y, int w, int h); + void (*dpy_gfx_resize)(DisplayChangeListener *dcl, + struct DisplayState *s); + void (*dpy_gfx_setdata)(DisplayChangeListener *dcl, + struct DisplayState *s); + void (*dpy_gfx_copy)(DisplayChangeListener *dcl, + struct DisplayState *s, int src_x, int src_y, + int dst_x, int dst_y, int w, int h); + + void (*dpy_text_cursor)(DisplayChangeListener *dcl, + struct DisplayState *s, + int x, int y); + void (*dpy_text_resize)(DisplayChangeListener *dcl, + struct DisplayState *s, + int w, int h); + void (*dpy_text_update)(DisplayChangeListener *dcl, + struct DisplayState *s, + int x, int y, int w, int h); + + void (*dpy_mouse_set)(DisplayChangeListener *dcl, + struct DisplayState *s, + int x, int y, int on); + void (*dpy_cursor_define)(DisplayChangeListener *dcl, + struct DisplayState *s, + QEMUCursor *cursor); +} DisplayChangeListenerOps; + struct DisplayChangeListener { int idle; uint64_t gui_timer_interval; - - void (*dpy_refresh)(struct DisplayState *s); - - void (*dpy_gfx_update)(struct DisplayState *s, int x, int y, int w, int h); - void (*dpy_gfx_resize)(struct DisplayState *s); - void (*dpy_gfx_setdata)(struct DisplayState *s); - void (*dpy_gfx_copy)(struct DisplayState *s, int src_x, int src_y, - int dst_x, int dst_y, int w, int h); - - void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); - void (*dpy_text_resize)(struct DisplayState *s, int w, int h); - void (*dpy_text_update)(struct DisplayState *s, int x, int y, int w, int h); - - void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on); - void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor); + const DisplayChangeListenerOps *ops; + DisplayState *ds; QLIST_ENTRY(DisplayChangeListener) next; }; @@ -210,145 +232,22 @@ static inline int is_buffer_shared(DisplaySurface *surface) void gui_setup_refresh(DisplayState *ds); -static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) -{ - QLIST_INSERT_HEAD(&ds->listeners, dcl, next); - gui_setup_refresh(ds); - if (dcl->dpy_gfx_resize) { - dcl->dpy_gfx_resize(ds); - } -} +void register_displaychangelistener(DisplayState *ds, + DisplayChangeListener *dcl); +void unregister_displaychangelistener(DisplayChangeListener *dcl); -static inline void unregister_displaychangelistener(DisplayState *ds, - DisplayChangeListener *dcl) -{ - QLIST_REMOVE(dcl, next); - gui_setup_refresh(ds); -} - -static inline void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h) -{ - struct DisplayChangeListener *dcl; - int width = pixman_image_get_width(s->surface->image); - int height = pixman_image_get_height(s->surface->image); - - x = MAX(x, 0); - y = MAX(y, 0); - x = MIN(x, width); - y = MIN(y, height); - w = MIN(w, width - x); - h = MIN(h, height - y); - - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_gfx_update) { - dcl->dpy_gfx_update(s, x, y, w, h); - } - } -} - -static inline void dpy_gfx_resize(DisplayState *s) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_gfx_resize) { - dcl->dpy_gfx_resize(s); - } - } -} - -static inline void dpy_gfx_setdata(DisplayState *s) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_gfx_setdata) { - dcl->dpy_gfx_setdata(s); - } - } -} - -static inline void dpy_refresh(DisplayState *s) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_refresh) { - dcl->dpy_refresh(s); - } - } -} - -static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, - int dst_x, int dst_y, int w, int h) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_gfx_copy) { - dcl->dpy_gfx_copy(s, src_x, src_y, dst_x, dst_y, w, h); - } else { /* TODO */ - dcl->dpy_gfx_update(s, dst_x, dst_y, w, h); - } - } -} - -static inline void dpy_text_cursor(struct DisplayState *s, int x, int y) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_text_cursor) { - dcl->dpy_text_cursor(s, x, y); - } - } -} - -static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_text_update) { - dcl->dpy_text_update(s, x, y, w, h); - } - } -} - -static inline void dpy_text_resize(DisplayState *s, int w, int h) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_text_resize) { - dcl->dpy_text_resize(s, w, h); - } - } -} - -static inline void dpy_mouse_set(struct DisplayState *s, int x, int y, int on) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_mouse_set) { - dcl->dpy_mouse_set(s, x, y, on); - } - } -} - -static inline void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_cursor_define) { - dcl->dpy_cursor_define(s, cursor); - } - } -} - -static inline bool dpy_cursor_define_supported(struct DisplayState *s) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_cursor_define) { - return true; - } - } - return false; -} +void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h); +void dpy_gfx_resize(DisplayState *s); +void dpy_gfx_setdata(DisplayState *s); +void dpy_refresh(DisplayState *s); +void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, + int dst_x, int dst_y, int w, int h); +void dpy_text_cursor(struct DisplayState *s, int x, int y); +void dpy_text_update(DisplayState *s, int x, int y, int w, int h); +void dpy_text_resize(DisplayState *s, int w, int h); +void dpy_mouse_set(struct DisplayState *s, int x, int y, int on); +void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor); +bool dpy_cursor_define_supported(struct DisplayState *s); static inline int ds_get_linesize(DisplayState *ds) { diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index 46f9530fe3..f2752aa25a 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -72,6 +72,7 @@ typedef struct SimpleSpiceUpdate SimpleSpiceUpdate; struct SimpleSpiceDisplay { DisplayState *ds; + DisplayChangeListener dcl; void *buf; int bufsize; QXLWorker *worker; diff --git a/trace-events b/trace-events index cd73b7f3ea..cbe7ef2876 100644 --- a/trace-events +++ b/trace-events @@ -960,6 +960,8 @@ dma_map_wait(void *dbs) "dbs=%p" # console.h displaysurface_free(void *display_state, void *display_surface) "state=%p surface=%p" displaysurface_resize(void *display_state, void *display_surface, int width, int height) "state=%p surface=%p %dx%d" +displaychangelistener_register(void *dcl, const char *name) "%p [ %s ]" +displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]" # vga.c ppm_save(const char *filename, void *display_surface) "%s surface=%p" diff --git a/ui/cocoa.m b/ui/cocoa.m index ca42413b34..b1fb30e7f9 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -969,7 +969,9 @@ int main (int argc, const char * argv[]) { #pragma mark qemu -static void cocoa_update(DisplayState *ds, int x, int y, int w, int h) +static void cocoa_update(DisplayChangeListener *dcl, + DisplayState *ds, + int x, int y, int w, int h) { COCOA_DEBUG("qemu_cocoa: cocoa_update\n"); @@ -986,14 +988,16 @@ static void cocoa_update(DisplayState *ds, int x, int y, int w, int h) [cocoaView setNeedsDisplayInRect:rect]; } -static void cocoa_resize(DisplayState *ds) +static void cocoa_resize(DisplayChangeListener *dcl, + DisplayState *ds) { COCOA_DEBUG("qemu_cocoa: cocoa_resize\n"); [cocoaView resizeContentToWidth:(int)(ds_get_width(ds)) height:(int)(ds_get_height(ds)) displayState:ds]; } -static void cocoa_refresh(DisplayState *ds) +static void cocoa_refresh(DisplayChangeListener *dcl, + DisplayState *ds) { COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n"); @@ -1030,6 +1034,14 @@ static void cocoa_cleanup(void) g_free(dcl); } +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "cocoa", + .dpy_gfx_update = cocoa_update; + .dpy_gfx_resize = cocoa_resize; + .dpy_gfx_setdata = cocoa_setdata; + .dpy_refresh = cocoa_refresh; +}; + void cocoa_display_init(DisplayState *ds, int full_screen) { COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n"); @@ -1037,12 +1049,8 @@ void cocoa_display_init(DisplayState *ds, int full_screen) dcl = g_malloc0(sizeof(DisplayChangeListener)); // register vga output callbacks - dcl->dpy_gfx_update = cocoa_update; - dcl->dpy_gfx_resize = cocoa_resize; - dcl->dpy_refresh = cocoa_refresh; - dcl->dpy_gfx_setdata = cocoa_setdata; - - register_displaychangelistener(ds, dcl); + dcl->ops = &dcl_ops; + register_displaychangelistener(ds, dcl); // register cleanup function atexit(cocoa_cleanup); diff --git a/ui/console.c b/ui/console.c index 27e87f8879..09f11859e1 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1374,6 +1374,150 @@ void qemu_free_displaysurface(DisplayState *ds) g_free(ds->surface); } +void register_displaychangelistener(DisplayState *ds, + DisplayChangeListener *dcl) +{ + 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_resize) { + dcl->ops->dpy_gfx_resize(dcl, ds); + } +} + +void unregister_displaychangelistener(DisplayChangeListener *dcl) +{ + DisplayState *ds = dcl->ds; + trace_displaychangelistener_unregister(dcl, dcl->ops->dpy_name); + QLIST_REMOVE(dcl, next); + gui_setup_refresh(ds); +} + +void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h) +{ + struct DisplayChangeListener *dcl; + int width = pixman_image_get_width(s->surface->image); + int height = pixman_image_get_height(s->surface->image); + + x = MAX(x, 0); + y = MAX(y, 0); + x = MIN(x, width); + y = MIN(y, height); + w = MIN(w, width - x); + h = MIN(h, height - y); + + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_gfx_update) { + dcl->ops->dpy_gfx_update(dcl, s, x, y, w, h); + } + } +} + +void dpy_gfx_resize(DisplayState *s) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_gfx_resize) { + dcl->ops->dpy_gfx_resize(dcl, s); + } + } +} + +void dpy_gfx_setdata(DisplayState *s) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_gfx_setdata) { + dcl->ops->dpy_gfx_setdata(dcl, s); + } + } +} + +void dpy_refresh(DisplayState *s) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_refresh) { + dcl->ops->dpy_refresh(dcl, s); + } + } +} + +void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, + int dst_x, int dst_y, int w, int h) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_gfx_copy) { + dcl->ops->dpy_gfx_copy(dcl, s, src_x, src_y, dst_x, dst_y, w, h); + } else { /* TODO */ + dcl->ops->dpy_gfx_update(dcl, s, dst_x, dst_y, w, h); + } + } +} + +void dpy_text_cursor(struct DisplayState *s, int x, int y) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_text_cursor) { + dcl->ops->dpy_text_cursor(dcl, s, x, y); + } + } +} + +void dpy_text_update(DisplayState *s, int x, int y, int w, int h) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_text_update) { + dcl->ops->dpy_text_update(dcl, s, x, y, w, h); + } + } +} + +void dpy_text_resize(DisplayState *s, int w, int h) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_text_resize) { + dcl->ops->dpy_text_resize(dcl, s, w, h); + } + } +} + +void dpy_mouse_set(struct DisplayState *s, int x, int y, int on) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_mouse_set) { + dcl->ops->dpy_mouse_set(dcl, s, x, y, on); + } + } +} + +void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_cursor_define) { + dcl->ops->dpy_cursor_define(dcl, s, cursor); + } + } +} + +bool dpy_cursor_define_supported(struct DisplayState *s) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_cursor_define) { + return true; + } + } + return false; +} + static void dumb_display_init(void) { DisplayState *ds = g_malloc0(sizeof(DisplayState)); diff --git a/ui/curses.c b/ui/curses.c index d78e378440..ca9856ccef 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -35,12 +35,15 @@ #define FONT_HEIGHT 16 #define FONT_WIDTH 8 +static DisplayChangeListener *dcl; static console_ch_t screen[160 * 100]; static WINDOW *screenpad = NULL; static int width, height, gwidth, gheight, invalidate; static int px, py, sminx, sminy, smaxx, smaxy; -static void curses_update(DisplayState *ds, int x, int y, int w, int h) +static void curses_update(DisplayChangeListener *dcl, + DisplayState *ds, + int x, int y, int w, int h) { chtype *line; @@ -91,7 +94,9 @@ static void curses_calc_pad(void) } } -static void curses_resize(DisplayState *ds, int width, int height) +static void curses_resize(DisplayChangeListener *dcl, + DisplayState *ds, + int width, int height) { if (width == gwidth && height == gheight) { return; @@ -128,7 +133,9 @@ static void curses_winch_handler(int signum) #endif #endif -static void curses_cursor_position(DisplayState *ds, int x, int y) +static void curses_cursor_position(DisplayChangeListener *dcl, + DisplayState *ds, + int x, int y) { if (x >= 0) { x = sminx + x - px; @@ -154,7 +161,8 @@ static void curses_cursor_position(DisplayState *ds, int x, int y) static kbd_layout_t *kbd_layout = NULL; -static void curses_refresh(DisplayState *ds) +static void curses_refresh(DisplayChangeListener *dcl, + DisplayState *ds) { int chr, nextchr, keysym, keycode, keycode_alt; @@ -187,7 +195,7 @@ static void curses_refresh(DisplayState *ds) clear(); refresh(); curses_calc_pad(); - curses_update(ds, 0, 0, width, height); + curses_update(dcl, ds, 0, 0, width, height); continue; } #endif @@ -323,9 +331,16 @@ static void curses_keyboard_setup(void) } } +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "curses", + .dpy_text_update = curses_update, + .dpy_text_resize = curses_resize, + .dpy_refresh = curses_refresh, + .dpy_text_cursor = curses_cursor_position, +}; + void curses_display_init(DisplayState *ds, int full_screen) { - DisplayChangeListener *dcl; #ifndef _WIN32 if (!isatty(1)) { fprintf(stderr, "We need a terminal output\n"); @@ -346,10 +361,7 @@ void curses_display_init(DisplayState *ds, int full_screen) #endif dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener)); - dcl->dpy_text_update = curses_update; - dcl->dpy_text_resize = curses_resize; - dcl->dpy_refresh = curses_refresh; - dcl->dpy_text_cursor = curses_cursor_position; + dcl->ops = &dcl_ops; register_displaychangelistener(ds, dcl); invalidate = 1; diff --git a/ui/gtk.c b/ui/gtk.c index 794dab15b1..379107f0de 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -227,7 +227,8 @@ static void gd_update_caption(GtkDisplayState *s) /** DisplayState Callbacks **/ -static void gd_update(DisplayState *ds, int x, int y, int w, int h) +static void gd_update(DisplayChangeListener *dcl, + DisplayState *ds, int x, int y, int w, int h) { GtkDisplayState *s = ds->opaque; int x1, x2, y1, y2; @@ -259,12 +260,14 @@ static void gd_update(DisplayState *ds, int x, int y, int w, int h) gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1)); } -static void gd_refresh(DisplayState *ds) +static void gd_refresh(DisplayChangeListener *dcl, + DisplayState *ds) { vga_hw_update(); } -static void gd_resize(DisplayState *ds) +static void gd_resize(DisplayChangeListener *dcl, + DisplayState *ds) { GtkDisplayState *s = ds->opaque; cairo_format_t kind; @@ -382,7 +385,7 @@ static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event, GtkDisplayState *s = opaque; if (!no_quit) { - unregister_displaychangelistener(s->ds, &s->dcl); + unregister_displaychangelistener(&s->dcl); qmp_quit(NULL); return FALSE; } @@ -735,7 +738,7 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque) s->scale_x += .25; s->scale_y += .25; - gd_resize(s->ds); + gd_resize(&s->dcl, s->ds); } static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque) @@ -751,7 +754,7 @@ static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque) s->scale_x = MAX(s->scale_x, .25); s->scale_y = MAX(s->scale_y, .25); - gd_resize(s->ds); + gd_resize(&s->dcl, s->ds); } static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque) @@ -761,7 +764,7 @@ static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque) s->scale_x = 1.0; s->scale_y = 1.0; - gd_resize(s->ds); + gd_resize(&s->dcl, s->ds); } static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque) @@ -775,7 +778,7 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque) s->free_scale = FALSE; } - gd_resize(s->ds); + gd_resize(&s->dcl, s->ds); gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh); @@ -1281,6 +1284,13 @@ static void gd_create_menus(GtkDisplayState *s) gtk_menu_shell_append(GTK_MENU_SHELL(s->menu_bar), s->view_menu_item); } +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "gtk", + .dpy_gfx_update = gd_update, + .dpy_gfx_resize = gd_resize, + .dpy_refresh = gd_refresh, +}; + void gtk_display_init(DisplayState *ds) { GtkDisplayState *s = g_malloc0(sizeof(*s)); @@ -1289,9 +1299,7 @@ void gtk_display_init(DisplayState *ds) ds->opaque = s; s->ds = ds; - s->dcl.dpy_gfx_update = gd_update; - s->dcl.dpy_gfx_resize = gd_resize; - s->dcl.dpy_refresh = gd_refresh; + s->dcl.ops = &dcl_ops; s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); #if GTK_CHECK_VERSION(3, 2, 0) diff --git a/ui/sdl.c b/ui/sdl.c index 1657848e9f..5baffa0094 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -59,7 +59,9 @@ static SDL_PixelFormat host_format; static int scaling_active = 0; static Notifier mouse_mode_notifier; -static void sdl_update(DisplayState *ds, int x, int y, int w, int h) +static void sdl_update(DisplayChangeListener *dcl, + DisplayState *ds, + int x, int y, int w, int h) { // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); SDL_Rect rec; @@ -81,7 +83,8 @@ static void sdl_update(DisplayState *ds, int x, int y, int w, int h) SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h); } -static void sdl_setdata(DisplayState *ds) +static void sdl_setdata(DisplayChangeListener *dcl, + DisplayState *ds) { if (guest_screen != NULL) SDL_FreeSurface(guest_screen); @@ -114,7 +117,8 @@ static void do_sdl_resize(int width, int height, int bpp) } } -static void sdl_resize(DisplayState *ds) +static void sdl_resize(DisplayChangeListener *dcl, + DisplayState *ds) { if (!scaling_active) { do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); @@ -122,7 +126,7 @@ static void sdl_resize(DisplayState *ds) do_sdl_resize(real_screen->w, real_screen->h, ds_get_bits_per_pixel(ds)); } - sdl_setdata(ds); + sdl_setdata(dcl, ds); } /* generic keyboard conversion */ @@ -514,7 +518,7 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev) case 0x16: /* 'u' key on US keyboard */ if (scaling_active) { scaling_active = 0; - sdl_resize(ds); + sdl_resize(dcl, ds); vga_hw_invalidate(); vga_hw_update(); } @@ -753,7 +757,8 @@ static void handle_activation(DisplayState *ds, SDL_Event *ev) } } -static void sdl_refresh(DisplayState *ds) +static void sdl_refresh(DisplayChangeListener *dcl, + DisplayState *ds) { SDL_Event ev1, *ev = &ev1; @@ -768,7 +773,7 @@ static void sdl_refresh(DisplayState *ds) while (SDL_PollEvent(ev)) { switch (ev->type) { case SDL_VIDEOEXPOSE: - sdl_update(ds, 0, 0, real_screen->w, real_screen->h); + sdl_update(dcl, ds, 0, 0, real_screen->w, real_screen->h); break; case SDL_KEYDOWN: handle_keydown(ds, ev); @@ -803,7 +808,9 @@ static void sdl_refresh(DisplayState *ds) } } -static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on) +static void sdl_mouse_warp(DisplayChangeListener *dcl, + DisplayState *ds, + int x, int y, int on) { if (on) { if (!guest_cursor) @@ -819,7 +826,9 @@ static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on) guest_x = x, guest_y = y; } -static void sdl_mouse_define(DisplayState *ds, QEMUCursor *c) +static void sdl_mouse_define(DisplayChangeListener *dcl, + DisplayState *ds, + QEMUCursor *c) { uint8_t *image, *mask; int bpl; @@ -849,6 +858,16 @@ static void sdl_cleanup(void) SDL_QuitSubSystem(SDL_INIT_VIDEO); } +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "sdl", + .dpy_gfx_update = sdl_update, + .dpy_gfx_resize = sdl_resize, + .dpy_refresh = sdl_refresh, + .dpy_gfx_setdata = sdl_setdata, + .dpy_mouse_set = sdl_mouse_warp, + .dpy_cursor_define = sdl_mouse_define, +}; + void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) { int flags; @@ -917,12 +936,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) } dcl = g_malloc0(sizeof(DisplayChangeListener)); - dcl->dpy_gfx_update = sdl_update; - dcl->dpy_gfx_resize = sdl_resize; - dcl->dpy_refresh = sdl_refresh; - dcl->dpy_gfx_setdata = sdl_setdata; - dcl->dpy_mouse_set = sdl_mouse_warp; - dcl->dpy_cursor_define = sdl_mouse_define; + dcl->ops = &dcl_ops; register_displaychangelistener(ds, dcl); mouse_mode_notifier.notify = sdl_mouse_mode_change; diff --git a/ui/spice-display.c b/ui/spice-display.c index dc7e58d0ed..b6528fae78 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -583,25 +583,30 @@ static const QXLInterface dpy_interface = { static SimpleSpiceDisplay sdpy; -static void display_update(struct DisplayState *ds, int x, int y, int w, int h) +static void display_update(DisplayChangeListener *dcl, + struct DisplayState *ds, + int x, int y, int w, int h) { qemu_spice_display_update(&sdpy, x, y, w, h); } -static void display_resize(struct DisplayState *ds) +static void display_resize(DisplayChangeListener *dcl, + struct DisplayState *ds) { qemu_spice_display_resize(&sdpy); } -static void display_refresh(struct DisplayState *ds) +static void display_refresh(DisplayChangeListener *dcl, + struct DisplayState *ds) { qemu_spice_display_refresh(&sdpy); } -static DisplayChangeListener display_listener = { +static const DisplayChangeListenerOps display_listener_ops = { + .dpy_name = "spice", .dpy_gfx_update = display_update, .dpy_gfx_resize = display_resize, - .dpy_refresh = display_refresh, + .dpy_refresh = display_refresh, }; void qemu_spice_display_init(DisplayState *ds) @@ -615,5 +620,7 @@ void qemu_spice_display_init(DisplayState *ds) qemu_spice_create_host_memslot(&sdpy); qemu_spice_create_host_primary(&sdpy); - register_displaychangelistener(ds, &display_listener); + + sdpy.dcl.ops = &display_listener_ops; + register_displaychangelistener(ds, &sdpy.dcl); } diff --git a/ui/vnc.c b/ui/vnc.c index ff4e2ae586..bdc3cd82bc 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -430,7 +430,9 @@ static void framebuffer_update_request(VncState *vs, int incremental, static void vnc_refresh(void *opaque); static int vnc_refresh_server_surface(VncDisplay *vd); -static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) +static void vnc_dpy_update(DisplayChangeListener *dcl, + DisplayState *ds, + int x, int y, int w, int h) { int i; VncDisplay *vd = ds->opaque; @@ -573,7 +575,8 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y) return ptr; } -static void vnc_dpy_resize(DisplayState *ds) +static void vnc_dpy_resize(DisplayChangeListener *dcl, + DisplayState *ds) { VncDisplay *vd = ds->opaque; VncState *vs; @@ -735,7 +738,10 @@ static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, i vnc_flush(vs); } -static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h) +static void vnc_dpy_copy(DisplayChangeListener *dcl, + DisplayState *ds, + int src_x, int src_y, + int dst_x, int dst_y, int w, int h) { VncDisplay *vd = ds->opaque; VncState *vs, *vn; @@ -806,7 +812,9 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int } } -static void vnc_mouse_set(DisplayState *ds, int x, int y, int visible) +static void vnc_mouse_set(DisplayChangeListener *dcl, + DisplayState *ds, + int x, int y, int visible) { /* can we ask the client(s) to move the pointer ??? */ } @@ -832,7 +840,9 @@ static int vnc_cursor_define(VncState *vs) return -1; } -static void vnc_dpy_cursor_define(DisplayState *ds, QEMUCursor *c) +static void vnc_dpy_cursor_define(DisplayChangeListener *dcl, + DisplayState *ds, + QEMUCursor *c) { VncDisplay *vd = vnc_display; VncState *vs; @@ -1972,14 +1982,15 @@ static void pixel_format_message (VncState *vs) { vs->write_pixels = vnc_write_pixels_copy; } -static void vnc_dpy_setdata(DisplayState *ds) +static void vnc_dpy_setdata(DisplayChangeListener *dcl, + DisplayState *ds) { VncDisplay *vd = ds->opaque; qemu_pixman_image_unref(vd->guest.fb); vd->guest.fb = pixman_image_ref(ds->surface->image); vd->guest.format = ds->surface->format; - vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); + vnc_dpy_update(dcl, ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); } static void vnc_colordepth(VncState *vs) @@ -2686,7 +2697,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); - vnc_dpy_resize(vd->ds); + vnc_dpy_resize(dcl, vd->ds); vnc_refresh(vd); } } @@ -2822,6 +2833,16 @@ static void vnc_listen_websocket_read(void *opaque) } #endif /* CONFIG_VNC_WS */ +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "vnc", + .dpy_gfx_copy = vnc_dpy_copy, + .dpy_gfx_update = vnc_dpy_update, + .dpy_gfx_resize = vnc_dpy_resize, + .dpy_gfx_setdata = vnc_dpy_setdata, + .dpy_mouse_set = vnc_mouse_set, + .dpy_cursor_define = vnc_dpy_cursor_define, +}; + void vnc_display_init(DisplayState *ds) { VncDisplay *vs = g_malloc0(sizeof(*vs)); @@ -2852,12 +2873,7 @@ void vnc_display_init(DisplayState *ds) qemu_mutex_init(&vs->mutex); vnc_start_worker_thread(); - dcl->dpy_gfx_copy = vnc_dpy_copy; - dcl->dpy_gfx_update = vnc_dpy_update; - dcl->dpy_gfx_resize = vnc_dpy_resize; - dcl->dpy_gfx_setdata = vnc_dpy_setdata; - dcl->dpy_mouse_set = vnc_mouse_set; - dcl->dpy_cursor_define = vnc_dpy_cursor_define; + dcl->ops = &dcl_ops; register_displaychangelistener(ds, dcl); } diff --git a/vl.c b/vl.c index a621aec0a4..ce51e65368 100644 --- a/vl.c +++ b/vl.c @@ -1639,13 +1639,13 @@ void gui_setup_refresh(DisplayState *ds) bool have_text = false; QLIST_FOREACH(dcl, &ds->listeners, next) { - if (dcl->dpy_refresh != NULL) { + if (dcl->ops->dpy_refresh != NULL) { need_timer = true; } - if (dcl->dpy_gfx_update != NULL) { + if (dcl->ops->dpy_gfx_update != NULL) { have_gfx = true; } - if (dcl->dpy_text_update != NULL) { + if (dcl->ops->dpy_text_update != NULL) { have_text = true; } } From 21ef45d71221b4577330fe3aacfb06afad91ad46 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 28 Feb 2013 11:34:31 +0100 Subject: [PATCH 21/37] console: kill DisplayState->opaque It's broken by design. There can be multiple DisplayChangeListener instances, so they simply can't store state in the (single) DisplayState struct. Try 'qemu -display gtk -vnc :0', watch it crash & burn. With DisplayChangeListenerOps having a more sane interface now we can simply use the DisplayChangeListener pointer to get access to our private data instead. Signed-off-by: Gerd Hoffmann --- include/ui/console.h | 1 - ui/gtk.c | 5 ++--- ui/vnc.c | 38 +++++++++++++++++--------------------- ui/vnc.h | 1 + 4 files changed, 20 insertions(+), 25 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index bf54f1ea54..91a1f63e5d 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -193,7 +193,6 @@ struct DisplayChangeListener { struct DisplayState { struct DisplaySurface *surface; - void *opaque; struct QEMUTimer *gui_timer; bool have_gfx; bool have_text; diff --git a/ui/gtk.c b/ui/gtk.c index 379107f0de..b21a94a335 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -230,7 +230,7 @@ static void gd_update_caption(GtkDisplayState *s) static void gd_update(DisplayChangeListener *dcl, DisplayState *ds, int x, int y, int w, int h) { - GtkDisplayState *s = ds->opaque; + GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); int x1, x2, y1, y2; int mx, my; int fbw, fbh; @@ -269,7 +269,7 @@ static void gd_refresh(DisplayChangeListener *dcl, static void gd_resize(DisplayChangeListener *dcl, DisplayState *ds) { - GtkDisplayState *s = ds->opaque; + GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); cairo_format_t kind; int stride; @@ -1297,7 +1297,6 @@ void gtk_display_init(DisplayState *ds) gtk_init(NULL, NULL); - ds->opaque = s; s->ds = ds; s->dcl.ops = &dcl_ops; diff --git a/ui/vnc.c b/ui/vnc.c index bdc3cd82bc..a6111d67bf 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -44,7 +44,6 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 }; #include "d3des.h" static VncDisplay *vnc_display; /* needed for info vnc */ -static DisplayChangeListener *dcl; static int vnc_cursor_define(VncState *vs); static void vnc_release_modifiers(VncState *vs); @@ -435,7 +434,7 @@ static void vnc_dpy_update(DisplayChangeListener *dcl, int x, int y, int w, int h) { int i; - VncDisplay *vd = ds->opaque; + VncDisplay *vd = container_of(dcl, VncDisplay, dcl); struct VncSurface *s = &vd->guest; int width = ds_get_width(ds); int height = ds_get_height(ds); @@ -578,7 +577,7 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y) static void vnc_dpy_resize(DisplayChangeListener *dcl, DisplayState *ds) { - VncDisplay *vd = ds->opaque; + VncDisplay *vd = container_of(dcl, VncDisplay, dcl); VncState *vs; vnc_abort_display_jobs(vd); @@ -743,7 +742,7 @@ static void vnc_dpy_copy(DisplayChangeListener *dcl, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { - VncDisplay *vd = ds->opaque; + VncDisplay *vd = container_of(dcl, VncDisplay, dcl); VncState *vs, *vn; uint8_t *src_row; uint8_t *dst_row; @@ -1069,7 +1068,7 @@ void vnc_disconnect_finish(VncState *vs) } if (QTAILQ_EMPTY(&vs->vd->clients)) { - dcl->idle = 1; + vs->vd->dcl.idle = 1; } vnc_remove_timer(vs->vd); @@ -1985,7 +1984,7 @@ static void pixel_format_message (VncState *vs) { static void vnc_dpy_setdata(DisplayChangeListener *dcl, DisplayState *ds) { - VncDisplay *vd = ds->opaque; + VncDisplay *vd = container_of(dcl, VncDisplay, dcl); qemu_pixman_image_unref(vd->guest.fb); vd->guest.fb = pixman_image_ref(ds->surface->image); @@ -2697,7 +2696,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); - vnc_dpy_resize(dcl, vd->ds); + vnc_dpy_resize(&vd->dcl, vd->ds); vnc_refresh(vd); } } @@ -2736,7 +2735,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket) } VNC_DEBUG("New client on socket %d\n", csock); - dcl->idle = 0; + vd->dcl.idle = 0; socket_set_nonblock(vs->csock); #ifdef CONFIG_VNC_WS if (websocket) { @@ -2847,10 +2846,7 @@ void vnc_display_init(DisplayState *ds) { VncDisplay *vs = g_malloc0(sizeof(*vs)); - dcl = g_malloc0(sizeof(DisplayChangeListener)); - - ds->opaque = vs; - dcl->idle = 1; + vs->dcl.idle = 1; vnc_display = vs; vs->lsock = -1; @@ -2873,14 +2869,14 @@ void vnc_display_init(DisplayState *ds) qemu_mutex_init(&vs->mutex); vnc_start_worker_thread(); - dcl->ops = &dcl_ops; - register_displaychangelistener(ds, dcl); + vs->dcl.ops = &dcl_ops; + register_displaychangelistener(ds, &vs->dcl); } static void vnc_display_close(DisplayState *ds) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; if (!vs) return; @@ -2911,7 +2907,7 @@ static void vnc_display_close(DisplayState *ds) static int vnc_display_disable_login(DisplayState *ds) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; if (!vs) { return -1; @@ -2931,7 +2927,7 @@ static int vnc_display_disable_login(DisplayState *ds) int vnc_display_password(DisplayState *ds, const char *password) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; if (!vs) { return -EINVAL; @@ -2957,7 +2953,7 @@ int vnc_display_password(DisplayState *ds, const char *password) int vnc_display_pw_expire(DisplayState *ds, time_t expires) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; if (!vs) { return -EINVAL; @@ -2969,14 +2965,14 @@ int vnc_display_pw_expire(DisplayState *ds, time_t expires) char *vnc_display_local_addr(DisplayState *ds) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; return vnc_socket_local_addr("%s:%s", vs->lsock); } void vnc_display_open(DisplayState *ds, const char *display, Error **errp) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; const char *options; int password = 0; int reverse = 0; @@ -3282,7 +3278,7 @@ fail: void vnc_display_add_client(DisplayState *ds, int csock, int skipauth) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; vnc_connect(vs, csock, skipauth, 0); } diff --git a/ui/vnc.h b/ui/vnc.h index 45d7686843..a96485b8d4 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -151,6 +151,7 @@ struct VncDisplay char *ws_display; #endif DisplayState *ds; + DisplayChangeListener dcl; kbd_layout_t *kbd_layout; int lock_key_sync; QemuMutex mutex; From 9c80a315b47a64043f6b91bd6f14352a455b323e Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 28 Feb 2013 14:47:07 +0100 Subject: [PATCH 22/37] spice: zap sdpy global DisplayChangeListener is passed now to all DisplayChangeListenerOps callbacks, so we can use that to access the spice display state and kill the sdpy global variable. Signed-off-by: Gerd Hoffmann --- ui/spice-display.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/ui/spice-display.c b/ui/spice-display.c index b6528fae78..b2bda23feb 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -581,25 +581,26 @@ static const QXLInterface dpy_interface = { .client_monitors_config = interface_client_monitors_config, }; -static SimpleSpiceDisplay sdpy; - static void display_update(DisplayChangeListener *dcl, struct DisplayState *ds, int x, int y, int w, int h) { - qemu_spice_display_update(&sdpy, x, y, w, h); + SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); + qemu_spice_display_update(ssd, x, y, w, h); } static void display_resize(DisplayChangeListener *dcl, struct DisplayState *ds) { - qemu_spice_display_resize(&sdpy); + SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); + qemu_spice_display_resize(ssd); } static void display_refresh(DisplayChangeListener *dcl, struct DisplayState *ds) { - qemu_spice_display_refresh(&sdpy); + SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); + qemu_spice_display_refresh(ssd); } static const DisplayChangeListenerOps display_listener_ops = { @@ -611,16 +612,17 @@ static const DisplayChangeListenerOps display_listener_ops = { void qemu_spice_display_init(DisplayState *ds) { - assert(sdpy.ds == NULL); - qemu_spice_display_init_common(&sdpy, ds); + SimpleSpiceDisplay *ssd = g_new0(SimpleSpiceDisplay, 1); - sdpy.qxl.base.sif = &dpy_interface.base; - qemu_spice_add_interface(&sdpy.qxl.base); - assert(sdpy.worker); + qemu_spice_display_init_common(ssd, ds); - qemu_spice_create_host_memslot(&sdpy); - qemu_spice_create_host_primary(&sdpy); + ssd->qxl.base.sif = &dpy_interface.base; + qemu_spice_add_interface(&ssd->qxl.base); + assert(ssd->worker); - sdpy.dcl.ops = &display_listener_ops; - register_displaychangelistener(ds, &sdpy.dcl); + qemu_spice_create_host_memslot(ssd); + qemu_spice_create_host_primary(ssd); + + ssd->dcl.ops = &display_listener_ops; + register_displaychangelistener(ds, &ssd->dcl); } From c6c06853d99127c03778fc1bf9bc2d96a05c108e Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 28 Feb 2013 12:15:00 +0100 Subject: [PATCH 23/37] qxl: zap qxl0 global DisplayChangeListener is passed now to all DisplayChangeListenerOps callbacks, so we can use that to access the qxl state and kill the qxl0 global variable. Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index fe1c4f1a35..54a8d91b89 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -118,8 +118,6 @@ static QXLMode qxl_modes[] = { QXL_MODE_EX(3200, 2400), }; -static PCIQXLDevice *qxl0; - static void qxl_send_events(PCIQXLDevice *d, uint32_t events); static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async); static void qxl_reset_memslots(PCIQXLDevice *d); @@ -1870,28 +1868,34 @@ static void display_update(DisplayChangeListener *dcl, struct DisplayState *ds, int x, int y, int w, int h) { - if (qxl0->mode == QXL_MODE_VGA) { - qemu_spice_display_update(&qxl0->ssd, x, y, w, h); + PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); + + if (qxl->mode == QXL_MODE_VGA) { + qemu_spice_display_update(&qxl->ssd, x, y, w, h); } } static void display_resize(DisplayChangeListener *dcl, struct DisplayState *ds) { - if (qxl0->mode == QXL_MODE_VGA) { - qemu_spice_display_resize(&qxl0->ssd); + PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); + + if (qxl->mode == QXL_MODE_VGA) { + qemu_spice_display_resize(&qxl->ssd); } } static void display_refresh(DisplayChangeListener *dcl, struct DisplayState *ds) { - if (qxl0->mode == QXL_MODE_VGA) { - qemu_spice_display_refresh(&qxl0->ssd); + PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); + + if (qxl->mode == QXL_MODE_VGA) { + qemu_spice_display_refresh(&qxl->ssd); } else { - qemu_mutex_lock(&qxl0->ssd.lock); - qemu_spice_cursor_refresh_unlocked(&qxl0->ssd); - qemu_mutex_unlock(&qxl0->ssd.lock); + qemu_mutex_lock(&qxl->ssd.lock); + qemu_spice_cursor_refresh_unlocked(&qxl->ssd); + qemu_mutex_unlock(&qxl->ssd.lock); } } @@ -2074,8 +2078,6 @@ static int qxl_init_primary(PCIDevice *dev) qxl_hw_screen_dump, qxl_hw_text_update, qxl); qemu_spice_display_init_common(&qxl->ssd, vga->ds); - qxl0 = qxl; - rc = qxl_init_common(qxl); if (rc != 0) { return rc; From c099e7aa0295678859d58e9e60b7619f6ae3bac8 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 28 Feb 2013 11:08:50 +0100 Subject: [PATCH 24/37] qxl: better vga init in enter_vga_mode Ask the vga core to update the display. Will trigger dpy_gfx_resize if needed. More complete than just calling dpy_gfx_resize. Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/qxl.c b/hw/qxl.c index 54a8d91b89..5d830f0e09 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1073,8 +1073,8 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d) trace_qxl_enter_vga_mode(d->id); qemu_spice_create_host_primary(&d->ssd); d->mode = QXL_MODE_VGA; - dpy_gfx_resize(d->ssd.ds); vga_dirty_log_start(&d->vga); + vga_hw_update(); } static void qxl_exit_vga_mode(PCIQXLDevice *d) From 468dfd6de2df3cbaed8c5cc43f8fbde6f94f9dbc Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 28 Feb 2013 10:48:36 +0100 Subject: [PATCH 25/37] sdl: drop dead code DisplayAllocator removal (commit 187cd1d9f30d13f0d0ef682e4d91cfa3e4cbd472) made this a nop. Signed-off-by: Gerd Hoffmann --- ui/sdl.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index 5baffa0094..fc4dc1b18d 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -458,11 +458,6 @@ static void sdl_scale(DisplayState *ds, int width, int height) } do_sdl_resize(width, height, bpp); scaling_active = 1; - if (!is_buffer_shared(ds->surface)) { - ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds), - ds_get_height(ds)); - dpy_gfx_resize(ds); - } } static void toggle_full_screen(DisplayState *ds) From da229ef3b3c5709b01d62e7a6e213b31bca33d16 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 28 Feb 2013 10:48:02 +0100 Subject: [PATCH 26/37] console: rework DisplaySurface handling [vga emu side] Decouple DisplaySurface allocation & deallocation from DisplayState. Replace dpy_gfx_resize + dpy_gfx_setdata with a dpy_gfx_replace_surface function. This handles the graphic hardware emulation. Signed-off-by: Gerd Hoffmann --- hw/arm/nseries.c | 7 ----- hw/arm/palm.c | 7 ----- hw/qxl-render.c | 12 ++++---- hw/vga.c | 17 +++++------ hw/xenfb.c | 8 ++--- include/ui/console.h | 11 +++---- trace-events | 5 ++-- ui/console.c | 71 ++++++++++++++++++-------------------------- 8 files changed, 54 insertions(+), 84 deletions(-) diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index c5bf9f95b3..6747c1c547 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -1290,7 +1290,6 @@ static void n8x0_init(QEMUMachineInitArgs *args, MemoryRegion *sysmem = get_system_memory(); struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s)); int sdram_size = binfo->ram_size; - DisplayState *ds; s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model); @@ -1370,12 +1369,6 @@ static void n8x0_init(QEMUMachineInitArgs *args, n800_setup_nolo_tags(nolo_tags); cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000); } - /* FIXME: We shouldn't really be doing this here. The LCD controller - will set the size once configured, so this just sets an initial - size until the guest activates the display. */ - ds = get_displaystate(); - ds->surface = qemu_resize_displaysurface(ds, 800, 480); - dpy_gfx_resize(ds); } static struct arm_boot_info n800_binfo = { diff --git a/hw/arm/palm.c b/hw/arm/palm.c index 91bc74af24..baeb585067 100644 --- a/hw/arm/palm.c +++ b/hw/arm/palm.c @@ -205,7 +205,6 @@ static void palmte_init(QEMUMachineInitArgs *args) static uint32_t cs2val = 0x0000e1a0; static uint32_t cs3val = 0xe1a0e1a0; int rom_size, rom_loaded = 0; - DisplayState *ds = get_displaystate(); MemoryRegion *flash = g_new(MemoryRegion, 1); MemoryRegion *cs = g_new(MemoryRegion, 4); @@ -268,12 +267,6 @@ static void palmte_init(QEMUMachineInitArgs *args) palmte_binfo.initrd_filename = initrd_filename; arm_load_kernel(mpu->cpu, &palmte_binfo); } - - /* FIXME: We shouldn't really be doing this here. The LCD controller - will set the size once configured, so this just sets an initial - size until the guest activates the display. */ - ds->surface = qemu_resize_displaysurface(ds, 320, 320); - dpy_gfx_resize(ds); } static QEMUMachine palmte_machine = { diff --git a/hw/qxl-render.c b/hw/qxl-render.c index d77df42b7e..8a19272dee 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -98,6 +98,7 @@ static void qxl_set_rect_to_surface(PCIQXLDevice *qxl, QXLRect *area) static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) { VGACommonState *vga = &qxl->vga; + DisplaySurface *surface; int i; if (qxl->guest_primary.resized) { @@ -112,8 +113,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) qxl->guest_primary.bytes_pp, qxl->guest_primary.bits_pp); if (qxl->guest_primary.qxl_stride > 0) { - qemu_free_displaysurface(vga->ds); - vga->ds->surface = qemu_create_displaysurface_from + surface = qemu_create_displaysurface_from (qxl->guest_primary.surface.width, qxl->guest_primary.surface.height, qxl->guest_primary.bits_pp, @@ -121,11 +121,11 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) qxl->guest_primary.data, false); } else { - qemu_resize_displaysurface(vga->ds, - qxl->guest_primary.surface.width, - qxl->guest_primary.surface.height); + surface = qemu_create_displaysurface + (qxl->guest_primary.surface.width, + qxl->guest_primary.surface.height); } - dpy_gfx_resize(vga->ds); + dpy_gfx_replace_surface(vga->ds, surface); } for (i = 0; i < qxl->num_dirty_rects; i++) { if (qemu_spice_rect_is_empty(qxl->dirty+i)) { diff --git a/hw/vga.c b/hw/vga.c index 2213bc1a88..13d5066e06 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1691,11 +1691,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) height != s->last_height || s->last_depth != depth) { if (depth == 32 || (depth == 16 && !byteswap)) { - qemu_free_displaysurface(s->ds); - s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth, - s->line_offset, + DisplaySurface *surface; + surface = qemu_create_displaysurface_from(disp_width, + height, depth, s->line_offset, s->vram_ptr + (s->start_addr * 4), byteswap); - dpy_gfx_resize(s->ds); + dpy_gfx_replace_surface(s->ds, surface); } else { qemu_console_resize(s->ds, disp_width, height); } @@ -1709,12 +1709,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) } else if (is_buffer_shared(s->ds->surface) && (full_update || ds_get_data(s->ds) != s->vram_ptr + (s->start_addr * 4))) { - qemu_free_displaysurface(s->ds); - s->ds->surface = qemu_create_displaysurface_from(disp_width, - height, depth, - s->line_offset, + DisplaySurface *surface; + surface = qemu_create_displaysurface_from(disp_width, + height, depth, s->line_offset, s->vram_ptr + (s->start_addr * 4), byteswap); - dpy_gfx_setdata(s->ds); + dpy_gfx_replace_surface(s->ds, surface); } s->rgb_to_pixel = diff --git a/hw/xenfb.c b/hw/xenfb.c index 3462ded619..7779097f50 100644 --- a/hw/xenfb.c +++ b/hw/xenfb.c @@ -703,6 +703,7 @@ static void xenfb_send_refresh_period(struct XenFB *xenfb, int period) static void xenfb_update(void *opaque) { struct XenFB *xenfb = opaque; + DisplaySurface *surface; int i; if (xenfb->c.xendev.be_state != XenbusStateConnected) @@ -753,21 +754,20 @@ static void xenfb_update(void *opaque) case 16: case 32: /* console.c supported depth -> buffer can be used directly */ - qemu_free_displaysurface(xenfb->c.ds); - xenfb->c.ds->surface = qemu_create_displaysurface_from + surface = qemu_create_displaysurface_from (xenfb->width, xenfb->height, xenfb->depth, xenfb->row_stride, xenfb->pixels + xenfb->offset, false); break; default: /* we must convert stuff */ - qemu_resize_displaysurface(xenfb->c.ds, xenfb->width, xenfb->height); + surface = qemu_create_displaysurface(xenfb->width, xenfb->height); break; } + dpy_gfx_replace_surface(xenfb->c.ds, surface); xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n", xenfb->width, xenfb->height, xenfb->depth, is_buffer_shared(xenfb->c.ds->surface) ? " (shared)" : ""); - dpy_gfx_resize(xenfb->c.ds); xenfb->up_fullscreen = 1; } diff --git a/include/ui/console.h b/include/ui/console.h index 91a1f63e5d..63e6e662c7 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -210,11 +210,8 @@ DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, PixelFormat qemu_different_endianness_pixelformat(int bpp); PixelFormat qemu_default_pixelformat(int bpp); -DisplaySurface *qemu_create_displaysurface(DisplayState *ds, - int width, int height); -DisplaySurface *qemu_resize_displaysurface(DisplayState *ds, - int width, int height); -void qemu_free_displaysurface(DisplayState *ds); +DisplaySurface *qemu_create_displaysurface(int width, int height); +void qemu_free_displaysurface(DisplaySurface *surface); static inline int is_surface_bgr(DisplaySurface *surface) { @@ -236,8 +233,8 @@ void register_displaychangelistener(DisplayState *ds, void unregister_displaychangelistener(DisplayChangeListener *dcl); void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h); -void dpy_gfx_resize(DisplayState *s); -void dpy_gfx_setdata(DisplayState *s); +void dpy_gfx_replace_surface(DisplayState *s, + DisplaySurface *surface); void dpy_refresh(DisplayState *s); void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h); diff --git a/trace-events b/trace-events index cbe7ef2876..406fe5f408 100644 --- a/trace-events +++ b/trace-events @@ -958,8 +958,9 @@ dma_bdrv_cb(void *dbs, int ret) "dbs=%p ret=%d" dma_map_wait(void *dbs) "dbs=%p" # console.h -displaysurface_free(void *display_state, void *display_surface) "state=%p surface=%p" -displaysurface_resize(void *display_state, void *display_surface, int width, int height) "state=%p surface=%p %dx%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" displaychangelistener_register(void *dcl, const char *name) "%p [ %s ]" displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]" diff --git a/ui/console.c b/ui/console.c index 09f11859e1..c2ca9e7b93 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1099,8 +1099,9 @@ void console_select(unsigned int index) } active_console = s; if (ds->have_gfx) { - ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height); - dpy_gfx_resize(ds); + DisplaySurface *surface; + surface = qemu_create_displaysurface(s->g_width, s->g_height); + dpy_gfx_replace_surface(ds, surface); } if (ds->have_text) { dpy_text_resize(ds, s->width, s->height); @@ -1316,34 +1317,24 @@ static void qemu_alloc_display(DisplaySurface *surface, int width, int height, #endif } -DisplaySurface *qemu_create_displaysurface(DisplayState *ds, - int width, int height) +DisplaySurface *qemu_create_displaysurface(int width, int height) { DisplaySurface *surface = g_new0(DisplaySurface, 1); - int linesize = width * 4; + + trace_displaysurface_create(surface, width, height); qemu_alloc_display(surface, width, height, linesize, qemu_default_pixelformat(32), 0); return surface; } -DisplaySurface *qemu_resize_displaysurface(DisplayState *ds, - int width, int height) -{ - int linesize = width * 4; - - trace_displaysurface_resize(ds, ds->surface, width, height); - qemu_alloc_display(ds->surface, width, height, linesize, - qemu_default_pixelformat(32), 0); - return ds->surface; -} - DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, int linesize, uint8_t *data, bool byteswap) { DisplaySurface *surface = g_new0(DisplaySurface, 1); + trace_displaysurface_create_from(surface, width, height, bpp, byteswap); if (byteswap) { surface->pf = qemu_different_endianness_pixelformat(bpp); } else { @@ -1364,14 +1355,14 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, return surface; } -void qemu_free_displaysurface(DisplayState *ds) +void qemu_free_displaysurface(DisplaySurface *surface) { - trace_displaysurface_free(ds, ds->surface); - if (ds->surface == NULL) { + if (surface == NULL) { return; } - qemu_pixman_image_unref(ds->surface->image); - g_free(ds->surface); + trace_displaysurface_free(surface); + qemu_pixman_image_unref(surface->image); + g_free(surface); } void register_displaychangelistener(DisplayState *ds, @@ -1414,24 +1405,19 @@ void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h) } } -void dpy_gfx_resize(DisplayState *s) +void dpy_gfx_replace_surface(DisplayState *s, + DisplaySurface *surface) { + DisplaySurface *old_surface = s->surface; struct DisplayChangeListener *dcl; + + s->surface = surface; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_gfx_resize) { dcl->ops->dpy_gfx_resize(dcl, s); } } -} - -void dpy_gfx_setdata(DisplayState *s) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->ops->dpy_gfx_setdata) { - dcl->ops->dpy_gfx_setdata(dcl, s); - } - } + qemu_free_displaysurface(old_surface); } void dpy_refresh(DisplayState *s) @@ -1521,6 +1507,7 @@ bool dpy_cursor_define_supported(struct DisplayState *s) static void dumb_display_init(void) { DisplayState *ds = g_malloc0(sizeof(DisplayState)); + DisplaySurface *surface; int width = 640; int height = 480; @@ -1528,7 +1515,9 @@ static void dumb_display_init(void) width = active_console->g_width; height = active_console->g_height; } - ds->surface = qemu_create_displaysurface(ds, width, height); + surface = qemu_create_displaysurface(width, height); + dpy_gfx_replace_surface(ds, surface); + register_displaystate(ds); } @@ -1561,22 +1550,19 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update, { QemuConsole *s; DisplayState *ds; + DisplaySurface *surface; ds = (DisplayState *) g_malloc0(sizeof(DisplayState)); - ds->surface = qemu_create_displaysurface(ds, 640, 480); - s = new_console(ds, GRAPHIC_CONSOLE); - if (s == NULL) { - qemu_free_displaysurface(ds); - g_free(ds); - return NULL; - } s->hw_update = update; s->hw_invalidate = invalidate; s->hw_screen_dump = screen_dump; s->hw_text_update = text_update; s->hw = opaque; + surface = qemu_create_displaysurface(640, 480); + dpy_gfx_replace_surface(ds, surface); + register_displaystate(ds); return ds; } @@ -1752,8 +1738,9 @@ void qemu_console_resize(DisplayState *ds, int width, int height) s->g_width = width; s->g_height = height; if (is_graphic_console()) { - ds->surface = qemu_resize_displaysurface(ds, width, height); - dpy_gfx_resize(ds); + DisplaySurface *surface; + surface = qemu_create_displaysurface(width, height); + dpy_gfx_replace_surface(ds, surface); } } From c12aeb860c63ba83190f962e2f0a1c5fe18ad3a6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 28 Feb 2013 15:03:04 +0100 Subject: [PATCH 27/37] console: rework DisplaySurface handling [dcl/ui side] Replace the dpy_gfx_resize and dpy_gfx_setdata DisplayChangeListener callbacks with a dpy_gfx_switch callback which notifies the ui code when the framebuffer backing storage changes. Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 9 +++++---- include/ui/console.h | 7 +++---- include/ui/spice-display.h | 3 ++- ui/cocoa.m | 13 ++++--------- ui/console.c | 8 ++++---- ui/gtk.c | 15 ++++++++------- ui/sdl.c | 10 +++++----- ui/spice-display.c | 12 +++++++----- ui/vnc.c | 21 +++++---------------- 9 files changed, 43 insertions(+), 55 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 5d830f0e09..fbaadde256 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1875,13 +1875,14 @@ static void display_update(DisplayChangeListener *dcl, } } -static void display_resize(DisplayChangeListener *dcl, - struct DisplayState *ds) +static void display_switch(DisplayChangeListener *dcl, + struct DisplayState *ds, + struct DisplaySurface *surface) { PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); if (qxl->mode == QXL_MODE_VGA) { - qemu_spice_display_resize(&qxl->ssd); + qemu_spice_display_switch(&qxl->ssd, surface); } } @@ -1902,7 +1903,7 @@ static void display_refresh(DisplayChangeListener *dcl, static DisplayChangeListenerOps display_listener_ops = { .dpy_name = "spice/qxl", .dpy_gfx_update = display_update, - .dpy_gfx_resize = display_resize, + .dpy_gfx_switch = display_switch, .dpy_refresh = display_refresh, }; diff --git a/include/ui/console.h b/include/ui/console.h index 63e6e662c7..c8f0050cd6 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -156,10 +156,9 @@ typedef struct DisplayChangeListenerOps { void (*dpy_gfx_update)(DisplayChangeListener *dcl, struct DisplayState *s, int x, int y, int w, int h); - void (*dpy_gfx_resize)(DisplayChangeListener *dcl, - struct DisplayState *s); - void (*dpy_gfx_setdata)(DisplayChangeListener *dcl, - struct DisplayState *s); + void (*dpy_gfx_switch)(DisplayChangeListener *dcl, + struct DisplayState *s, + struct DisplaySurface *new_surface); void (*dpy_gfx_copy)(DisplayChangeListener *dcl, struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h); diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index f2752aa25a..82f8246650 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -117,7 +117,8 @@ void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds); void qemu_spice_display_update(SimpleSpiceDisplay *ssd, int x, int y, int w, int h); -void qemu_spice_display_resize(SimpleSpiceDisplay *ssd); +void qemu_spice_display_switch(SimpleSpiceDisplay *ssd, + DisplaySurface *surface); void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd); void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd); diff --git a/ui/cocoa.m b/ui/cocoa.m index b1fb30e7f9..73843f447c 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -988,8 +988,9 @@ static void cocoa_update(DisplayChangeListener *dcl, [cocoaView setNeedsDisplayInRect:rect]; } -static void cocoa_resize(DisplayChangeListener *dcl, - DisplayState *ds) +static void cocoa_switch(DisplayChangeListener *dcl, + DisplayState *ds, + DisplaySurface *surface) { COCOA_DEBUG("qemu_cocoa: cocoa_resize\n"); @@ -1023,11 +1024,6 @@ static void cocoa_refresh(DisplayChangeListener *dcl, vga_hw_update(); } -static void cocoa_setdata(DisplayState *ds) -{ - [cocoaView updateDataOffset:ds]; -} - static void cocoa_cleanup(void) { COCOA_DEBUG("qemu_cocoa: cocoa_cleanup\n"); @@ -1037,8 +1033,7 @@ static void cocoa_cleanup(void) static const DisplayChangeListenerOps dcl_ops = { .dpy_name = "cocoa", .dpy_gfx_update = cocoa_update; - .dpy_gfx_resize = cocoa_resize; - .dpy_gfx_setdata = cocoa_setdata; + .dpy_gfx_switch = cocoa_switch; .dpy_refresh = cocoa_refresh; }; diff --git a/ui/console.c b/ui/console.c index c2ca9e7b93..4541b2c533 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1372,8 +1372,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_resize) { - dcl->ops->dpy_gfx_resize(dcl, ds); + if (dcl->ops->dpy_gfx_switch) { + dcl->ops->dpy_gfx_switch(dcl, ds, ds->surface); } } @@ -1413,8 +1413,8 @@ void dpy_gfx_replace_surface(DisplayState *s, s->surface = surface; QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->ops->dpy_gfx_resize) { - dcl->ops->dpy_gfx_resize(dcl, s); + if (dcl->ops->dpy_gfx_switch) { + dcl->ops->dpy_gfx_switch(dcl, s, surface); } } qemu_free_displaysurface(old_surface); diff --git a/ui/gtk.c b/ui/gtk.c index b21a94a335..967a36cc4e 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -266,8 +266,9 @@ static void gd_refresh(DisplayChangeListener *dcl, vga_hw_update(); } -static void gd_resize(DisplayChangeListener *dcl, - DisplayState *ds) +static void gd_switch(DisplayChangeListener *dcl, + DisplayState *ds, + DisplaySurface *surface) { GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); cairo_format_t kind; @@ -738,7 +739,7 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque) s->scale_x += .25; s->scale_y += .25; - gd_resize(&s->dcl, s->ds); + gd_switch(&s->dcl, s->ds, s->ds->surface); } static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque) @@ -754,7 +755,7 @@ static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque) s->scale_x = MAX(s->scale_x, .25); s->scale_y = MAX(s->scale_y, .25); - gd_resize(&s->dcl, s->ds); + gd_switch(&s->dcl, s->ds, s->ds->surface); } static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque) @@ -764,7 +765,7 @@ static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque) s->scale_x = 1.0; s->scale_y = 1.0; - gd_resize(&s->dcl, s->ds); + gd_switch(&s->dcl, s->ds, s->ds->surface); } static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque) @@ -778,7 +779,7 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque) s->free_scale = FALSE; } - gd_resize(&s->dcl, s->ds); + gd_switch(&s->dcl, s->ds, s->ds->surface); gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh); @@ -1287,7 +1288,7 @@ static void gd_create_menus(GtkDisplayState *s) static const DisplayChangeListenerOps dcl_ops = { .dpy_name = "gtk", .dpy_gfx_update = gd_update, - .dpy_gfx_resize = gd_resize, + .dpy_gfx_switch = gd_switch, .dpy_refresh = gd_refresh, }; diff --git a/ui/sdl.c b/ui/sdl.c index fc4dc1b18d..85eefdf4ab 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -117,8 +117,9 @@ static void do_sdl_resize(int width, int height, int bpp) } } -static void sdl_resize(DisplayChangeListener *dcl, - DisplayState *ds) +static void sdl_switch(DisplayChangeListener *dcl, + DisplayState *ds, + DisplaySurface *surface) { if (!scaling_active) { do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); @@ -513,7 +514,7 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev) case 0x16: /* 'u' key on US keyboard */ if (scaling_active) { scaling_active = 0; - sdl_resize(dcl, ds); + sdl_switch(dcl, ds, ds->surface); vga_hw_invalidate(); vga_hw_update(); } @@ -856,9 +857,8 @@ static void sdl_cleanup(void) static const DisplayChangeListenerOps dcl_ops = { .dpy_name = "sdl", .dpy_gfx_update = sdl_update, - .dpy_gfx_resize = sdl_resize, + .dpy_gfx_switch = sdl_switch, .dpy_refresh = sdl_refresh, - .dpy_gfx_setdata = sdl_setdata, .dpy_mouse_set = sdl_mouse_warp, .dpy_cursor_define = sdl_mouse_define, }; diff --git a/ui/spice-display.c b/ui/spice-display.c index b2bda23feb..cc2a78e654 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -367,7 +367,8 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, qemu_spice_rect_union(&ssd->dirty, &update_area); } -void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) +void qemu_spice_display_switch(SimpleSpiceDisplay *ssd, + DisplaySurface *surface) { SimpleSpiceUpdate *update; @@ -589,11 +590,12 @@ static void display_update(DisplayChangeListener *dcl, qemu_spice_display_update(ssd, x, y, w, h); } -static void display_resize(DisplayChangeListener *dcl, - struct DisplayState *ds) +static void display_switch(DisplayChangeListener *dcl, + struct DisplayState *ds, + struct DisplaySurface *surface) { SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); - qemu_spice_display_resize(ssd); + qemu_spice_display_switch(ssd, surface); } static void display_refresh(DisplayChangeListener *dcl, @@ -606,7 +608,7 @@ static void display_refresh(DisplayChangeListener *dcl, static const DisplayChangeListenerOps display_listener_ops = { .dpy_name = "spice", .dpy_gfx_update = display_update, - .dpy_gfx_resize = display_resize, + .dpy_gfx_switch = display_switch, .dpy_refresh = display_refresh, }; diff --git a/ui/vnc.c b/ui/vnc.c index a6111d67bf..f8398c344d 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -574,8 +574,9 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y) return ptr; } -static void vnc_dpy_resize(DisplayChangeListener *dcl, - DisplayState *ds) +static void vnc_dpy_switch(DisplayChangeListener *dcl, + DisplayState *ds, + DisplaySurface *surface) { VncDisplay *vd = container_of(dcl, VncDisplay, dcl); VncState *vs; @@ -1981,17 +1982,6 @@ static void pixel_format_message (VncState *vs) { vs->write_pixels = vnc_write_pixels_copy; } -static void vnc_dpy_setdata(DisplayChangeListener *dcl, - DisplayState *ds) -{ - VncDisplay *vd = container_of(dcl, VncDisplay, dcl); - - qemu_pixman_image_unref(vd->guest.fb); - vd->guest.fb = pixman_image_ref(ds->surface->image); - vd->guest.format = ds->surface->format; - vnc_dpy_update(dcl, ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); -} - static void vnc_colordepth(VncState *vs) { if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) { @@ -2696,7 +2686,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); - vnc_dpy_resize(&vd->dcl, vd->ds); + vnc_dpy_switch(&vd->dcl, vd->ds, vd->ds->surface); vnc_refresh(vd); } } @@ -2836,8 +2826,7 @@ static const DisplayChangeListenerOps dcl_ops = { .dpy_name = "vnc", .dpy_gfx_copy = vnc_dpy_copy, .dpy_gfx_update = vnc_dpy_update, - .dpy_gfx_resize = vnc_dpy_resize, - .dpy_gfx_setdata = vnc_dpy_setdata, + .dpy_gfx_switch = vnc_dpy_switch, .dpy_mouse_set = vnc_mouse_set, .dpy_cursor_define = vnc_dpy_cursor_define, }; From 626e3b34e30bc62d4f25f7aa4e23a346eba1a2c0 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 28 Feb 2013 15:24:14 +0100 Subject: [PATCH 28/37] console: add surface_*() getters Add convinence wrappers to query DisplaySurface properties. Simliar to ds_get_*, but operating in the DisplaySurface not the DisplayState. With this patch in place ui frontents can stop using DisplayState in the rendering code paths, they can simply operate using the DisplaySurface passed in via dpy_gfx_switch callback. Signed-off-by: Gerd Hoffmann --- include/ui/console.h | 46 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index c8f0050cd6..a35b71aba2 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -244,36 +244,66 @@ void dpy_mouse_set(struct DisplayState *s, int x, int y, int on); void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor); bool dpy_cursor_define_supported(struct DisplayState *s); +static inline int surface_stride(DisplaySurface *s) +{ + return pixman_image_get_stride(s->image); +} + +static inline void *surface_data(DisplaySurface *s) +{ + return pixman_image_get_data(s->image); +} + +static inline int surface_width(DisplaySurface *s) +{ + return pixman_image_get_width(s->image); +} + +static inline int surface_height(DisplaySurface *s) +{ + return pixman_image_get_height(s->image); +} + +static inline int surface_bits_per_pixel(DisplaySurface *s) +{ + int bits = PIXMAN_FORMAT_BPP(s->format); + return bits; +} + +static inline int surface_bytes_per_pixel(DisplaySurface *s) +{ + int bits = PIXMAN_FORMAT_BPP(s->format); + return (bits + 7) / 8; +} + static inline int ds_get_linesize(DisplayState *ds) { - return pixman_image_get_stride(ds->surface->image); + return surface_stride(ds->surface); } static inline uint8_t* ds_get_data(DisplayState *ds) { - return (void *)pixman_image_get_data(ds->surface->image); + return surface_data(ds->surface); } static inline int ds_get_width(DisplayState *ds) { - return pixman_image_get_width(ds->surface->image); + return surface_width(ds->surface); } static inline int ds_get_height(DisplayState *ds) { - return pixman_image_get_height(ds->surface->image); + return surface_height(ds->surface); } static inline int ds_get_bits_per_pixel(DisplayState *ds) { - int bits = PIXMAN_FORMAT_BPP(ds->surface->format); - return bits; + return surface_bits_per_pixel(ds->surface); } static inline int ds_get_bytes_per_pixel(DisplayState *ds) { - int bits = PIXMAN_FORMAT_BPP(ds->surface->format); - return (bits + 7) / 8; + return surface_bytes_per_pixel(ds->surface); } static inline pixman_format_code_t ds_get_format(DisplayState *ds) From 9d9801cf803cdceaa4845fe27150b24d5ab083e6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 28 Feb 2013 16:10:02 +0100 Subject: [PATCH 29/37] gtk: stop using DisplayState Rework DisplayStateListener callbacks to not use the DisplayState any more. Factor out the window size handling to a separate function, so the zoom callbacks can call that directly instead of abusing the gd_switch DisplayStateListener callback for that. Signed-off-by: Gerd Hoffmann --- ui/gtk.c | 224 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 122 insertions(+), 102 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index 967a36cc4e..d553550301 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -143,7 +143,7 @@ typedef struct GtkDisplayState GtkWidget *drawing_area; cairo_surface_t *surface; DisplayChangeListener dcl; - DisplayState *ds; + DisplaySurface *ds; int button_mask; int last_x; int last_y; @@ -225,86 +225,8 @@ static void gd_update_caption(GtkDisplayState *s) g_free(title); } -/** DisplayState Callbacks **/ - -static void gd_update(DisplayChangeListener *dcl, - DisplayState *ds, int x, int y, int w, int h) +static void gd_update_windowsize(GtkDisplayState *s) { - GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); - int x1, x2, y1, y2; - int mx, my; - int fbw, fbh; - int ww, wh; - - DPRINTF("update(x=%d, y=%d, w=%d, h=%d)\n", x, y, w, h); - - x1 = floor(x * s->scale_x); - y1 = floor(y * s->scale_y); - - x2 = ceil(x * s->scale_x + w * s->scale_x); - y2 = ceil(y * s->scale_y + h * s->scale_y); - - fbw = ds_get_width(s->ds) * s->scale_x; - fbh = ds_get_height(s->ds) * s->scale_y; - - gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); - - mx = my = 0; - if (ww > fbw) { - mx = (ww - fbw) / 2; - } - if (wh > fbh) { - my = (wh - fbh) / 2; - } - - gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1)); -} - -static void gd_refresh(DisplayChangeListener *dcl, - DisplayState *ds) -{ - vga_hw_update(); -} - -static void gd_switch(DisplayChangeListener *dcl, - DisplayState *ds, - DisplaySurface *surface) -{ - GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); - cairo_format_t kind; - int stride; - - DPRINTF("resize(width=%d, height=%d)\n", - ds_get_width(ds), ds_get_height(ds)); - - if (s->surface) { - cairo_surface_destroy(s->surface); - } - - switch (ds->surface->pf.bits_per_pixel) { - case 8: - kind = CAIRO_FORMAT_A8; - break; - case 16: - kind = CAIRO_FORMAT_RGB16_565; - break; - case 32: - kind = CAIRO_FORMAT_RGB24; - break; - default: - g_assert_not_reached(); - break; - } - - stride = cairo_format_stride_for_width(kind, ds_get_width(ds)); - g_assert(ds_get_linesize(ds) == stride); - - s->surface = cairo_image_surface_create_for_data(ds_get_data(ds), - kind, - ds_get_width(ds), - ds_get_height(ds), - ds_get_linesize(ds)); - if (!s->full_screen) { GtkRequisition req; double sx, sy; @@ -321,8 +243,8 @@ static void gd_switch(DisplayChangeListener *dcl, } gtk_widget_set_size_request(s->drawing_area, - ds_get_width(ds) * s->scale_x, - ds_get_height(ds) * s->scale_y); + surface_width(s->ds) * s->scale_x, + surface_height(s->ds) * s->scale_y); #if GTK_CHECK_VERSION(3, 0, 0) gtk_widget_get_preferred_size(s->vbox, NULL, &req); #else @@ -334,6 +256,107 @@ static void gd_switch(DisplayChangeListener *dcl, } } +static void gd_update_full_redraw(GtkDisplayState *s) +{ + int ww, wh; + gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); + gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh); +} + +/** DisplayState Callbacks **/ + +static void gd_update(DisplayChangeListener *dcl, + DisplayState *dontuse, int x, int y, int w, int h) +{ + GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); + int x1, x2, y1, y2; + int mx, my; + int fbw, fbh; + int ww, wh; + + DPRINTF("update(x=%d, y=%d, w=%d, h=%d)\n", x, y, w, h); + + x1 = floor(x * s->scale_x); + y1 = floor(y * s->scale_y); + + x2 = ceil(x * s->scale_x + w * s->scale_x); + y2 = ceil(y * s->scale_y + h * s->scale_y); + + fbw = surface_width(s->ds) * s->scale_x; + fbh = surface_height(s->ds) * s->scale_y; + + gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); + + mx = my = 0; + if (ww > fbw) { + mx = (ww - fbw) / 2; + } + if (wh > fbh) { + my = (wh - fbh) / 2; + } + + gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1)); +} + +static void gd_refresh(DisplayChangeListener *dcl, + DisplayState *dontuse) +{ + vga_hw_update(); +} + +static void gd_switch(DisplayChangeListener *dcl, + DisplayState *dontuse, + DisplaySurface *surface) +{ + GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); + cairo_format_t kind; + bool resized = true; + int stride; + + DPRINTF("resize(width=%d, height=%d)\n", + surface_width(surface), surface_height(surface)); + + if (s->surface) { + cairo_surface_destroy(s->surface); + } + + if (s->ds && + surface_width(s->ds) == surface_width(surface) && + surface_height(s->ds) == surface_height(surface)) { + resized = false; + } + s->ds = surface; + switch (surface_bits_per_pixel(surface)) { + case 8: + kind = CAIRO_FORMAT_A8; + break; + case 16: + kind = CAIRO_FORMAT_RGB16_565; + break; + case 32: + kind = CAIRO_FORMAT_RGB24; + break; + default: + g_assert_not_reached(); + break; + } + + stride = cairo_format_stride_for_width(kind, surface_width(surface)); + g_assert(surface_stride(surface) == stride); + + s->surface = cairo_image_surface_create_for_data(surface_data(surface), + kind, + surface_width(surface), + surface_height(surface), + surface_stride(surface)); + + if (resized) { + gd_update_windowsize(s); + } else { + gd_update_full_redraw(s); + } +} + /** QEMU Events **/ static void gd_change_runstate(void *opaque, int running, RunState state) @@ -405,8 +428,8 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque) return FALSE; } - fbw = ds_get_width(s->ds); - fbh = ds_get_height(s->ds); + fbw = surface_width(s->ds); + fbh = surface_height(s->ds); gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh); @@ -484,8 +507,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, int fbh, fbw; int ww, wh; - fbw = ds_get_width(s->ds) * s->scale_x; - fbh = ds_get_height(s->ds) * s->scale_y; + fbw = surface_width(s->ds) * s->scale_x; + fbh = surface_height(s->ds) * s->scale_y; gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); @@ -501,14 +524,14 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, y = (motion->y - my) / s->scale_y; if (x < 0 || y < 0 || - x >= ds_get_width(s->ds) || - y >= ds_get_height(s->ds)) { + x >= surface_width(s->ds) || + y >= surface_height(s->ds)) { return TRUE; } if (kbd_mouse_is_absolute()) { - dx = x * 0x7FFF / (ds_get_width(s->ds) - 1); - dy = y * 0x7FFF / (ds_get_height(s->ds) - 1); + dx = x * 0x7FFF / (surface_width(s->ds) - 1); + dy = y * 0x7FFF / (surface_height(s->ds) - 1); } else if (s->last_x == -1 || s->last_y == -1) { dx = 0; dy = 0; @@ -589,8 +612,8 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button, } if (kbd_mouse_is_absolute()) { - dx = s->last_x * 0x7FFF / (ds_get_width(s->ds) - 1); - dy = s->last_y * 0x7FFF / (ds_get_height(s->ds) - 1); + dx = s->last_x * 0x7FFF / (surface_width(s->ds) - 1); + dy = s->last_y * 0x7FFF / (surface_height(s->ds) - 1); } else { dx = 0; dy = 0; @@ -719,7 +742,8 @@ static void gd_menu_full_screen(GtkMenuItem *item, void *opaque) gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s); gtk_widget_set_size_request(s->menu_bar, -1, -1); gtk_widget_set_size_request(s->drawing_area, - ds_get_width(s->ds), ds_get_height(s->ds)); + surface_width(s->ds), + surface_height(s->ds)); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), FALSE); s->full_screen = FALSE; s->scale_x = 1.0; @@ -739,7 +763,7 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque) s->scale_x += .25; s->scale_y += .25; - gd_switch(&s->dcl, s->ds, s->ds->surface); + gd_update_windowsize(s); } static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque) @@ -755,7 +779,7 @@ static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque) s->scale_x = MAX(s->scale_x, .25); s->scale_y = MAX(s->scale_y, .25); - gd_switch(&s->dcl, s->ds, s->ds->surface); + gd_update_windowsize(s); } static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque) @@ -765,13 +789,12 @@ static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque) s->scale_x = 1.0; s->scale_y = 1.0; - gd_switch(&s->dcl, s->ds, s->ds->surface); + gd_update_windowsize(s); } static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque) { GtkDisplayState *s = opaque; - int ww, wh; if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item))) { s->free_scale = TRUE; @@ -779,10 +802,8 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque) s->free_scale = FALSE; } - gd_switch(&s->dcl, s->ds, s->ds->surface); - - gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); - gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh); + gd_update_windowsize(s); + gd_update_full_redraw(s); } static void gd_grab_keyboard(GtkDisplayState *s) @@ -1298,7 +1319,6 @@ void gtk_display_init(DisplayState *ds) gtk_init(NULL, NULL); - s->ds = ds; s->dcl.ops = &dcl_ops; s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); From d39fa6d86d07646e3481e5c3e45a984bff590642 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 28 Feb 2013 17:16:48 +0100 Subject: [PATCH 30/37] vnc: stop using DisplayState Rework DisplayStateListener callbacks to not use the DisplayState any more. Signed-off-by: Gerd Hoffmann --- ui/vnc-enc-tight.c | 7 +++-- ui/vnc-jobs.c | 1 - ui/vnc.c | 77 ++++++++++++++++++++++++++-------------------- ui/vnc.h | 3 +- 4 files changed, 48 insertions(+), 40 deletions(-) diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 4ddea7d4f5..e6966aebc3 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -123,7 +123,7 @@ static bool tight_can_send_png_rect(VncState *vs, int w, int h) return false; } - if (ds_get_bytes_per_pixel(vs->ds) == 1 || + if (surface_bytes_per_pixel(vs->vd->ds) == 1 || vs->client_pf.bytes_per_pixel == 1) { return false; } @@ -301,7 +301,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h) return 0; } - if (ds_get_bytes_per_pixel(vs->ds) == 1 || + if (surface_bytes_per_pixel(vs->vd->ds) == 1 || vs->client_pf.bytes_per_pixel == 1 || w < VNC_TIGHT_DETECT_MIN_WIDTH || h < VNC_TIGHT_DETECT_MIN_HEIGHT) { return 0; @@ -1184,8 +1184,9 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) uint8_t *buf; int dy; - if (ds_get_bytes_per_pixel(vs->ds) == 1) + if (surface_bytes_per_pixel(vs->vd->ds) == 1) { return send_full_color_rect(vs, x, y, w, h); + } buffer_reserve(&vs->tight.jpeg, 2048); diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index 0bfc0c5485..2d3fce8155 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -183,7 +183,6 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local) { local->vnc_encoding = orig->vnc_encoding; local->features = orig->features; - local->ds = orig->ds; local->vd = orig->vd; local->lossy_rect = orig->lossy_rect; local->write_pixels = orig->write_pixels; diff --git a/ui/vnc.c b/ui/vnc.c index f8398c344d..f38aeda3e2 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -436,8 +436,8 @@ static void vnc_dpy_update(DisplayChangeListener *dcl, int i; VncDisplay *vd = container_of(dcl, VncDisplay, dcl); struct VncSurface *s = &vd->guest; - int width = ds_get_width(ds); - int height = ds_get_height(ds); + int width = surface_width(vd->ds); + int height = surface_height(vd->ds); h += y; @@ -519,17 +519,17 @@ void buffer_advance(Buffer *buf, size_t len) static void vnc_desktop_resize(VncState *vs) { - DisplayState *ds = vs->ds; + DisplaySurface *ds = vs->vd->ds; if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) { return; } - if (vs->client_width == ds_get_width(ds) && - vs->client_height == ds_get_height(ds)) { + if (vs->client_width == surface_width(ds) && + vs->client_height == surface_height(ds)) { return; } - vs->client_width = ds_get_width(ds); - vs->client_height = ds_get_height(ds); + vs->client_width = surface_width(ds); + vs->client_height = surface_height(ds); vnc_lock_output(vs); vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); vnc_write_u8(vs, 0); @@ -575,7 +575,7 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y) } static void vnc_dpy_switch(DisplayChangeListener *dcl, - DisplayState *ds, + DisplayState *dontuse, DisplaySurface *surface) { VncDisplay *vd = container_of(dcl, VncDisplay, dcl); @@ -585,9 +585,10 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl, /* server surface */ qemu_pixman_image_unref(vd->server); + vd->ds = surface; vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT, - ds_get_width(ds), - ds_get_height(ds), + surface_width(vd->ds), + surface_height(vd->ds), NULL, 0); /* guest surface */ @@ -596,8 +597,8 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl, console_color_init(ds); #endif qemu_pixman_image_unref(vd->guest.fb); - vd->guest.fb = pixman_image_ref(ds->surface->image); - vd->guest.format = ds->surface->format; + vd->guest.fb = pixman_image_ref(surface->image); + vd->guest.format = surface->format; memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty)); QTAILQ_FOREACH(vs, &vd->clients, next) { @@ -739,7 +740,7 @@ static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, i } static void vnc_dpy_copy(DisplayChangeListener *dcl, - DisplayState *ds, + DisplayState *dontuse, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { @@ -813,7 +814,7 @@ static void vnc_dpy_copy(DisplayChangeListener *dcl, } static void vnc_mouse_set(DisplayChangeListener *dcl, - DisplayState *ds, + DisplayState *dontuse, int x, int y, int visible) { /* can we ask the client(s) to move the pointer ??? */ @@ -841,7 +842,7 @@ static int vnc_cursor_define(VncState *vs) } static void vnc_dpy_cursor_define(DisplayChangeListener *dcl, - DisplayState *ds, + DisplayState *dontuse, QEMUCursor *c) { VncDisplay *vd = vnc_display; @@ -1463,7 +1464,8 @@ static void check_pointer_type_change(Notifier *notifier, void *data) vnc_write_u8(vs, 0); vnc_write_u16(vs, 1); vnc_framebuffer_update(vs, absolute, 0, - ds_get_width(vs->ds), ds_get_height(vs->ds), + surface_width(vs->vd->ds), + surface_height(vs->vd->ds), VNC_ENCODING_POINTER_TYPE_CHANGE); vnc_unlock_output(vs); vnc_flush(vs); @@ -1475,6 +1477,8 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y) { int buttons = 0; int dz = 0; + int width = surface_width(vs->vd->ds); + int height = surface_height(vs->vd->ds); if (button_mask & 0x01) buttons |= MOUSE_EVENT_LBUTTON; @@ -1488,10 +1492,8 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y) dz = 1; if (vs->absolute) { - kbd_mouse_event(ds_get_width(vs->ds) > 1 ? - x * 0x7FFF / (ds_get_width(vs->ds) - 1) : 0x4000, - ds_get_height(vs->ds) > 1 ? - y * 0x7FFF / (ds_get_height(vs->ds) - 1) : 0x4000, + kbd_mouse_event(width > 1 ? x * 0x7FFF / (width - 1) : 0x4000, + height > 1 ? y * 0x7FFF / (height - 1) : 0x4000, dz, buttons); } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) { x -= 0x7FFF; @@ -1781,12 +1783,15 @@ static void framebuffer_update_request(VncState *vs, int incremental, int w, int h) { int i; - const size_t width = ds_get_width(vs->ds) / 16; + const size_t width = surface_width(vs->vd->ds) / 16; + const size_t height = surface_height(vs->vd->ds); - if (y_position > ds_get_height(vs->ds)) - y_position = ds_get_height(vs->ds); - if (y_position + h >= ds_get_height(vs->ds)) - h = ds_get_height(vs->ds) - y_position; + if (y_position > height) { + y_position = height; + } + if (y_position + h >= height) { + h = height - y_position; + } vs->need_update = 1; if (!incremental) { @@ -1805,7 +1810,9 @@ static void send_ext_key_event_ack(VncState *vs) vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); vnc_write_u8(vs, 0); vnc_write_u16(vs, 1); - vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), + vnc_framebuffer_update(vs, 0, 0, + surface_width(vs->vd->ds), + surface_height(vs->vd->ds), VNC_ENCODING_EXT_KEY_EVENT); vnc_unlock_output(vs); vnc_flush(vs); @@ -1817,7 +1824,9 @@ static void send_ext_audio_ack(VncState *vs) vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); vnc_write_u8(vs, 0); vnc_write_u16(vs, 1); - vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), + vnc_framebuffer_update(vs, 0, 0, + surface_width(vs->vd->ds), + surface_height(vs->vd->ds), VNC_ENCODING_AUDIO); vnc_unlock_output(vs); vnc_flush(vs); @@ -1990,8 +1999,10 @@ static void vnc_colordepth(VncState *vs) vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); vnc_write_u8(vs, 0); vnc_write_u16(vs, 1); /* number of rects */ - vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), - ds_get_height(vs->ds), VNC_ENCODING_WMVi); + vnc_framebuffer_update(vs, 0, 0, + surface_width(vs->vd->ds), + surface_height(vs->vd->ds), + VNC_ENCODING_WMVi); pixel_format_message(vs); vnc_unlock_output(vs); vnc_flush(vs); @@ -2207,8 +2218,8 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len) } vnc_set_share_mode(vs, mode); - vs->client_width = ds_get_width(vs->ds); - vs->client_height = ds_get_height(vs->ds); + vs->client_width = surface_width(vs->vd->ds); + vs->client_height = surface_height(vs->vd->ds); vnc_write_u16(vs, vs->client_width); vnc_write_u16(vs, vs->client_height); @@ -2686,7 +2697,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); - vnc_dpy_switch(&vd->dcl, vd->ds, vd->ds->surface); + vga_hw_update(); vnc_refresh(vd); } } @@ -2756,7 +2767,6 @@ void vnc_init_state(VncState *vs) vs->initialized = true; VncDisplay *vd = vs->vd; - vs->ds = vd->ds; vs->last_x = -1; vs->last_y = -1; @@ -2843,7 +2853,6 @@ void vnc_display_init(DisplayState *ds) vs->lwebsock = -1; #endif - vs->ds = ds; QTAILQ_INIT(&vs->clients); vs->expires = TIME_MAX; diff --git a/ui/vnc.h b/ui/vnc.h index a96485b8d4..58e002eed3 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -150,7 +150,7 @@ struct VncDisplay bool websocket; char *ws_display; #endif - DisplayState *ds; + DisplaySurface *ds; DisplayChangeListener dcl; kbd_layout_t *kbd_layout; int lock_key_sync; @@ -248,7 +248,6 @@ struct VncState { int csock; - DisplayState *ds; DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_DIRTY_BITS); uint8_t **lossy_rect; /* Not an Array to avoid costly memcpy in * vnc-jobs-async.c */ From 8db9bae94eadcb7d5d07af1ba0c642aafafc5498 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 1 Mar 2013 09:01:13 +0100 Subject: [PATCH 31/37] sdl: stop using DisplayState Rework DisplayStateListener callbacks to not use the DisplayState any more. Signed-off-by: Gerd Hoffmann --- ui/sdl.c | 96 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index 85eefdf4ab..58f16bc63e 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -35,6 +35,7 @@ #include "sdl_zoom.h" static DisplayChangeListener *dcl; +static DisplaySurface *surface; static SDL_Surface *real_screen; static SDL_Surface *guest_screen = NULL; static int gui_grab; /* if true, all keyboard/mouse events are grabbed */ @@ -60,7 +61,7 @@ static int scaling_active = 0; static Notifier mouse_mode_notifier; static void sdl_update(DisplayChangeListener *dcl, - DisplayState *ds, + DisplayState *dontuse, int x, int y, int w, int h) { // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); @@ -83,17 +84,6 @@ static void sdl_update(DisplayChangeListener *dcl, SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h); } -static void sdl_setdata(DisplayChangeListener *dcl, - DisplayState *ds) -{ - if (guest_screen != NULL) SDL_FreeSurface(guest_screen); - - guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds), - ds_get_bits_per_pixel(ds), ds_get_linesize(ds), - ds->surface->pf.rmask, ds->surface->pf.gmask, - ds->surface->pf.bmask, ds->surface->pf.amask); -} - static void do_sdl_resize(int width, int height, int bpp) { int flags; @@ -118,16 +108,32 @@ static void do_sdl_resize(int width, int height, int bpp) } static void sdl_switch(DisplayChangeListener *dcl, - DisplayState *ds, - DisplaySurface *surface) + DisplayState *dontuse, + DisplaySurface *new_surface) { - if (!scaling_active) { - do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); - } else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds)) { - do_sdl_resize(real_screen->w, real_screen->h, - ds_get_bits_per_pixel(ds)); + + /* temporary hack: allows to call sdl_switch to handle scaling changes */ + if (new_surface) { + surface = new_surface; } - sdl_setdata(dcl, ds); + + if (!scaling_active) { + do_sdl_resize(surface_width(surface), surface_height(surface), 0); + } else if (real_screen->format->BitsPerPixel != + surface_bits_per_pixel(surface)) { + do_sdl_resize(real_screen->w, real_screen->h, + surface_bits_per_pixel(surface)); + } + + if (guest_screen != NULL) { + SDL_FreeSurface(guest_screen); + } + guest_screen = SDL_CreateRGBSurfaceFrom + (surface_data(surface), + surface_width(surface), surface_height(surface), + surface_bits_per_pixel(surface), surface_stride(surface), + surface->pf.rmask, surface->pf.gmask, + surface->pf.bmask, surface->pf.amask); } /* generic keyboard conversion */ @@ -450,7 +456,7 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state kbd_mouse_event(dx, dy, dz, buttons); } -static void sdl_scale(DisplayState *ds, int width, int height) +static void sdl_scale(int width, int height) { int bpp = real_screen->format->BitsPerPixel; @@ -461,25 +467,28 @@ static void sdl_scale(DisplayState *ds, int width, int height) scaling_active = 1; } -static void toggle_full_screen(DisplayState *ds) +static void toggle_full_screen(void) { + int width = surface_width(surface); + int height = surface_height(surface); + int bpp = surface_bits_per_pixel(surface); + gui_fullscreen = !gui_fullscreen; if (gui_fullscreen) { gui_saved_width = real_screen->w; gui_saved_height = real_screen->h; gui_saved_scaling = scaling_active; - do_sdl_resize(ds_get_width(ds), ds_get_height(ds), - ds_get_bits_per_pixel(ds)); + do_sdl_resize(width, height, bpp); scaling_active = 0; gui_saved_grab = gui_grab; sdl_grab_start(); } else { if (gui_saved_scaling) { - sdl_scale(ds, gui_saved_width, gui_saved_height); + sdl_scale(gui_saved_width, gui_saved_height); } else { - do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); + do_sdl_resize(width, height, 0); } if (!gui_saved_grab || !is_graphic_console()) { sdl_grab_end(); @@ -489,7 +498,7 @@ static void toggle_full_screen(DisplayState *ds) vga_hw_update(); } -static void handle_keydown(DisplayState *ds, SDL_Event *ev) +static void handle_keydown(SDL_Event *ev) { int mod_state; int keycode; @@ -508,13 +517,13 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev) keycode = sdl_keyevent_to_keycode(&ev->key); switch (keycode) { case 0x21: /* 'f' key on US keyboard */ - toggle_full_screen(ds); + toggle_full_screen(); gui_keysym = 1; break; case 0x16: /* 'u' key on US keyboard */ if (scaling_active) { scaling_active = 0; - sdl_switch(dcl, ds, ds->surface); + sdl_switch(dcl, NULL, NULL); vga_hw_invalidate(); vga_hw_update(); } @@ -545,9 +554,10 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev) if (!gui_fullscreen) { int width = MAX(real_screen->w + (keycode == 0x1b ? 50 : -50), 160); - int height = (ds_get_height(ds) * width) / ds_get_width(ds); + int height = (surface_height(surface) * width) / + surface_width(surface); - sdl_scale(ds, width, height); + sdl_scale(width, height); vga_hw_invalidate(); vga_hw_update(); gui_keysym = 1; @@ -634,7 +644,7 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev) } } -static void handle_keyup(DisplayState *ds, SDL_Event *ev) +static void handle_keyup(SDL_Event *ev) { int mod_state; @@ -666,7 +676,7 @@ static void handle_keyup(DisplayState *ds, SDL_Event *ev) } } -static void handle_mousemotion(DisplayState *ds, SDL_Event *ev) +static void handle_mousemotion(SDL_Event *ev) { int max_x, max_y; @@ -690,7 +700,7 @@ static void handle_mousemotion(DisplayState *ds, SDL_Event *ev) } } -static void handle_mousebutton(DisplayState *ds, SDL_Event *ev) +static void handle_mousebutton(SDL_Event *ev) { int buttonstate = SDL_GetMouseState(NULL, NULL); SDL_MouseButtonEvent *bev; @@ -726,7 +736,7 @@ static void handle_mousebutton(DisplayState *ds, SDL_Event *ev) } } -static void handle_activation(DisplayState *ds, SDL_Event *ev) +static void handle_activation(SDL_Event *ev) { #ifdef _WIN32 /* Disable grab if the window no longer has the focus @@ -754,7 +764,7 @@ static void handle_activation(DisplayState *ds, SDL_Event *ev) } static void sdl_refresh(DisplayChangeListener *dcl, - DisplayState *ds) + DisplayState *dontuse) { SDL_Event ev1, *ev = &ev1; @@ -769,13 +779,13 @@ static void sdl_refresh(DisplayChangeListener *dcl, while (SDL_PollEvent(ev)) { switch (ev->type) { case SDL_VIDEOEXPOSE: - sdl_update(dcl, ds, 0, 0, real_screen->w, real_screen->h); + sdl_update(dcl, dontuse, 0, 0, real_screen->w, real_screen->h); break; case SDL_KEYDOWN: - handle_keydown(ds, ev); + handle_keydown(ev); break; case SDL_KEYUP: - handle_keyup(ds, ev); + handle_keyup(ev); break; case SDL_QUIT: if (!no_quit) { @@ -784,17 +794,17 @@ static void sdl_refresh(DisplayChangeListener *dcl, } break; case SDL_MOUSEMOTION: - handle_mousemotion(ds, ev); + handle_mousemotion(ev); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: - handle_mousebutton(ds, ev); + handle_mousebutton(ev); break; case SDL_ACTIVEEVENT: - handle_activation(ds, ev); + handle_activation(ev); break; case SDL_VIDEORESIZE: - sdl_scale(ds, ev->resize.w, ev->resize.h); + sdl_scale(ev->resize.w, ev->resize.h); vga_hw_invalidate(); vga_hw_update(); break; From 71874c1751ebb7368eaa023a35ac919d2c1c5e4c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 28 Feb 2013 16:42:28 +0100 Subject: [PATCH 32/37] spice: stop using DisplayState Rework DisplayStateListener callbacks to not use the DisplayState any more. Signed-off-by: Gerd Hoffmann --- hw/qxl-render.c | 2 +- hw/qxl.c | 3 ++- include/ui/spice-display.h | 2 +- ui/spice-display.c | 31 ++++++++++++++++--------------- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/hw/qxl-render.c b/hw/qxl-render.c index 8a19272dee..087679e142 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -236,7 +236,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) return 1; } - if (!dpy_cursor_define_supported(qxl->ssd.ds)) { + if (!dpy_cursor_define_supported(qxl->ssd.dcl.ds)) { return 0; } diff --git a/hw/qxl.c b/hw/qxl.c index fbaadde256..6ed61beea4 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1782,7 +1782,7 @@ static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch, case QXL_MODE_COMPAT: case QXL_MODE_NATIVE: qxl_render_update(qxl); - ppm_save(filename, qxl->ssd.ds->surface, errp); + ppm_save(filename, qxl->ssd.ds, errp); break; case QXL_MODE_VGA: vga->screen_dump(vga, filename, cswitch, errp); @@ -1881,6 +1881,7 @@ static void display_switch(DisplayChangeListener *dcl, { PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); + qxl->ssd.ds = surface; if (qxl->mode == QXL_MODE_VGA) { qemu_spice_display_switch(&qxl->ssd, surface); } diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index 82f8246650..a9e1e09b42 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -71,7 +71,7 @@ typedef struct SimpleSpiceDisplay SimpleSpiceDisplay; typedef struct SimpleSpiceUpdate SimpleSpiceUpdate; struct SimpleSpiceDisplay { - DisplayState *ds; + DisplaySurface *ds; DisplayChangeListener dcl; void *buf; int bufsize; diff --git a/ui/spice-display.c b/ui/spice-display.c index cc2a78e654..5bbe23b8ba 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -214,10 +214,10 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd, static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) { static const int blksize = 32; - int blocks = (ds_get_width(ssd->ds) + blksize - 1) / blksize; + int blocks = (surface_width(ssd->ds) + blksize - 1) / blksize; int dirty_top[blocks]; int y, yoff, x, xoff, blk, bw; - int bpp = ds_get_bytes_per_pixel(ssd->ds); + int bpp = surface_bytes_per_pixel(ssd->ds); uint8_t *guest, *mirror; if (qemu_spice_rect_is_empty(&ssd->dirty)) { @@ -225,19 +225,19 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) }; if (ssd->surface == NULL) { - ssd->surface = pixman_image_ref(ds_get_image(ssd->ds)); - ssd->mirror = qemu_pixman_mirror_create(ds_get_format(ssd->ds), - ds_get_image(ssd->ds)); + ssd->surface = pixman_image_ref(ssd->ds->image); + ssd->mirror = qemu_pixman_mirror_create(ssd->ds->format, + ssd->ds->image); } for (blk = 0; blk < blocks; blk++) { dirty_top[blk] = -1; } - guest = ds_get_data(ssd->ds); + guest = surface_data(ssd->ds); mirror = (void *)pixman_image_get_data(ssd->mirror); for (y = ssd->dirty.top; y < ssd->dirty.bottom; y++) { - yoff = y * ds_get_linesize(ssd->ds); + yoff = y * surface_stride(ssd->ds); for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) { xoff = x * bpp; blk = x / blksize; @@ -312,11 +312,11 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) memset(&surface, 0, sizeof(surface)); dprint(1, "%s: %dx%d\n", __FUNCTION__, - ds_get_width(ssd->ds), ds_get_height(ssd->ds)); + surface_width(ssd->ds), surface_height(ssd->ds)); surface.format = SPICE_SURFACE_FMT_32_xRGB; - surface.width = ds_get_width(ssd->ds); - surface.height = ds_get_height(ssd->ds); + surface.width = surface_width(ssd->ds); + surface.height = surface_height(ssd->ds); surface.stride = -surface.width * 4; surface.mouse_mode = true; surface.flags = 0; @@ -336,7 +336,6 @@ void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds) { - ssd->ds = ds; qemu_mutex_init(&ssd->lock); QTAILQ_INIT(&ssd->updates); ssd->mouse_x = -1; @@ -383,6 +382,7 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd, } qemu_mutex_lock(&ssd->lock); + ssd->ds = surface; while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) { QTAILQ_REMOVE(&ssd->updates, update, next); qemu_spice_destroy_update(ssd, update); @@ -398,12 +398,12 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd, void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd) { if (ssd->cursor) { - dpy_cursor_define(ssd->ds, ssd->cursor); + dpy_cursor_define(ssd->dcl.ds, ssd->cursor); cursor_put(ssd->cursor); ssd->cursor = NULL; } if (ssd->mouse_x != -1 && ssd->mouse_y != -1) { - dpy_mouse_set(ssd->ds, ssd->mouse_x, ssd->mouse_y, 1); + dpy_mouse_set(ssd->dcl.ds, ssd->mouse_x, ssd->mouse_y, 1); ssd->mouse_x = -1; ssd->mouse_y = -1; } @@ -415,7 +415,7 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) vga_hw_update(); qemu_mutex_lock(&ssd->lock); - if (QTAILQ_EMPTY(&ssd->updates)) { + if (QTAILQ_EMPTY(&ssd->updates) && ssd->ds) { qemu_spice_create_update(ssd); ssd->notify++; } @@ -623,8 +623,9 @@ void qemu_spice_display_init(DisplayState *ds) assert(ssd->worker); qemu_spice_create_host_memslot(ssd); - qemu_spice_create_host_primary(ssd); ssd->dcl.ops = &display_listener_ops; register_displaychangelistener(ds, &ssd->dcl); + + qemu_spice_create_host_primary(ssd); } From 5e00d3ac475fb4c9afa17612a908e933fe142f00 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 1 Mar 2013 12:52:06 +0100 Subject: [PATCH 33/37] cocoa: stop using DisplayState Rework DisplayStateListener callbacks to not use the DisplayState any more. Signed-off-by: Gerd Hoffmann --- ui/cocoa.m | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index 73843f447c..9a56fb8912 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -264,8 +264,7 @@ @interface QemuCocoaView : NSView BOOL isAbsoluteEnabled; BOOL isTabletEnabled; } -- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds; -- (void) updateDataOffset:(DisplayState *)ds; +- (void) switchSurface:(DisplaySurface *)surface; - (void) grabMouse; - (void) ungrabMouse; - (void) toggleFullScreen:(id)sender; @@ -400,19 +399,19 @@ - (void) setContentDimensions } } -- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds +- (void) switchSurface:(DisplaySurface *)surface { - COCOA_DEBUG("QemuCocoaView: resizeContent\n"); + COCOA_DEBUG("QemuCocoaView: switchSurface\n"); // update screenBuffer if (dataProviderRef) CGDataProviderRelease(dataProviderRef); //sync host window color space with guests - screen.bitsPerPixel = ds_get_bits_per_pixel(ds); - screen.bitsPerComponent = ds_get_bytes_per_pixel(ds) * 2; + screen.bitsPerPixel = surface_bits_per_pixel(surface); + screen.bitsPerComponent = surface_bytes_per_pixel(surface) * 2; - dataProviderRef = CGDataProviderCreateWithData(NULL, ds_get_data(ds), w * 4 * h, NULL); + dataProviderRef = CGDataProviderCreateWithData(NULL, surface_data(surface), w * 4 * h, NULL); // update windows if (isFullscreen) { @@ -430,20 +429,6 @@ - (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *) [self setFrame:NSMakeRect(cx, cy, cw, ch)]; } -- (void) updateDataOffset:(DisplayState *)ds -{ - COCOA_DEBUG("QemuCocoaView: UpdateDataOffset\n"); - - // update screenBuffer - if (dataProviderRef) { - CGDataProviderRelease(dataProviderRef); - } - - size_t size = ds_get_width(ds) * 4 * ds_get_height(ds); - dataProviderRef = CGDataProviderCreateWithData(NULL, ds_get_data(ds), - size, NULL); -} - - (void) toggleFullScreen:(id)sender { COCOA_DEBUG("QemuCocoaView: toggleFullScreen\n"); @@ -970,7 +955,7 @@ int main (int argc, const char * argv[]) { #pragma mark qemu static void cocoa_update(DisplayChangeListener *dcl, - DisplayState *ds, + DisplayState *dontuse, int x, int y, int w, int h) { COCOA_DEBUG("qemu_cocoa: cocoa_update\n"); @@ -989,16 +974,16 @@ static void cocoa_update(DisplayChangeListener *dcl, } static void cocoa_switch(DisplayChangeListener *dcl, - DisplayState *ds, + DisplayState *dontuse, DisplaySurface *surface) { COCOA_DEBUG("qemu_cocoa: cocoa_resize\n"); - [cocoaView resizeContentToWidth:(int)(ds_get_width(ds)) height:(int)(ds_get_height(ds)) displayState:ds]; + [cocoaView switchSurface:surface]; } static void cocoa_refresh(DisplayChangeListener *dcl, - DisplayState *ds) + DisplayState *dontuse) { COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n"); From bc2ed9704fff2c721e4056ab5281f0291718bfa6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 1 Mar 2013 13:03:04 +0100 Subject: [PATCH 34/37] console: zap displaystate from dcl callbacks Now that nobody depends on DisplayState in DisplayChangeListener callbacks any more we can remove the parameter from all callbacks. Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 5 +---- include/ui/console.h | 12 ++---------- ui/cocoa.m | 5 +---- ui/console.c | 22 +++++++++++----------- ui/curses.c | 8 ++------ ui/gtk.c | 6 ++---- ui/sdl.c | 11 +++-------- ui/spice-display.c | 5 +---- ui/vnc.c | 5 ----- 9 files changed, 23 insertions(+), 56 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 6ed61beea4..0939ace88e 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1865,7 +1865,6 @@ static void qxl_vm_change_state_handler(void *opaque, int running, /* display change listener */ static void display_update(DisplayChangeListener *dcl, - struct DisplayState *ds, int x, int y, int w, int h) { PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); @@ -1876,7 +1875,6 @@ static void display_update(DisplayChangeListener *dcl, } static void display_switch(DisplayChangeListener *dcl, - struct DisplayState *ds, struct DisplaySurface *surface) { PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); @@ -1887,8 +1885,7 @@ static void display_switch(DisplayChangeListener *dcl, } } -static void display_refresh(DisplayChangeListener *dcl, - struct DisplayState *ds) +static void display_refresh(DisplayChangeListener *dcl) { PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl); diff --git a/include/ui/console.h b/include/ui/console.h index a35b71aba2..c32c834871 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -150,34 +150,26 @@ void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask); typedef struct DisplayChangeListenerOps { const char *dpy_name; - void (*dpy_refresh)(DisplayChangeListener *dcl, - struct DisplayState *s); + void (*dpy_refresh)(DisplayChangeListener *dcl); void (*dpy_gfx_update)(DisplayChangeListener *dcl, - struct DisplayState *s, int x, int y, int w, int h); void (*dpy_gfx_switch)(DisplayChangeListener *dcl, - struct DisplayState *s, struct DisplaySurface *new_surface); void (*dpy_gfx_copy)(DisplayChangeListener *dcl, - struct DisplayState *s, int src_x, int src_y, + int src_x, int src_y, int dst_x, int dst_y, int w, int h); void (*dpy_text_cursor)(DisplayChangeListener *dcl, - struct DisplayState *s, int x, int y); void (*dpy_text_resize)(DisplayChangeListener *dcl, - struct DisplayState *s, int w, int h); void (*dpy_text_update)(DisplayChangeListener *dcl, - struct DisplayState *s, int x, int y, int w, int h); void (*dpy_mouse_set)(DisplayChangeListener *dcl, - struct DisplayState *s, int x, int y, int on); void (*dpy_cursor_define)(DisplayChangeListener *dcl, - struct DisplayState *s, QEMUCursor *cursor); } DisplayChangeListenerOps; diff --git a/ui/cocoa.m b/ui/cocoa.m index 9a56fb8912..8e0eaa2601 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -955,7 +955,6 @@ int main (int argc, const char * argv[]) { #pragma mark qemu static void cocoa_update(DisplayChangeListener *dcl, - DisplayState *dontuse, int x, int y, int w, int h) { COCOA_DEBUG("qemu_cocoa: cocoa_update\n"); @@ -974,7 +973,6 @@ static void cocoa_update(DisplayChangeListener *dcl, } static void cocoa_switch(DisplayChangeListener *dcl, - DisplayState *dontuse, DisplaySurface *surface) { COCOA_DEBUG("qemu_cocoa: cocoa_resize\n"); @@ -982,8 +980,7 @@ static void cocoa_switch(DisplayChangeListener *dcl, [cocoaView switchSurface:surface]; } -static void cocoa_refresh(DisplayChangeListener *dcl, - DisplayState *dontuse) +static void cocoa_refresh(DisplayChangeListener *dcl) { COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n"); diff --git a/ui/console.c b/ui/console.c index 4541b2c533..d690e1c58f 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1373,7 +1373,7 @@ void register_displaychangelistener(DisplayState *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, ds->surface); + dcl->ops->dpy_gfx_switch(dcl, ds->surface); } } @@ -1400,7 +1400,7 @@ void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h) QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_gfx_update) { - dcl->ops->dpy_gfx_update(dcl, s, x, y, w, h); + dcl->ops->dpy_gfx_update(dcl, x, y, w, h); } } } @@ -1414,7 +1414,7 @@ void dpy_gfx_replace_surface(DisplayState *s, s->surface = surface; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_gfx_switch) { - dcl->ops->dpy_gfx_switch(dcl, s, surface); + dcl->ops->dpy_gfx_switch(dcl, surface); } } qemu_free_displaysurface(old_surface); @@ -1425,7 +1425,7 @@ void dpy_refresh(DisplayState *s) struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_refresh) { - dcl->ops->dpy_refresh(dcl, s); + dcl->ops->dpy_refresh(dcl); } } } @@ -1436,9 +1436,9 @@ void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_gfx_copy) { - dcl->ops->dpy_gfx_copy(dcl, s, src_x, src_y, dst_x, dst_y, w, h); + dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h); } else { /* TODO */ - dcl->ops->dpy_gfx_update(dcl, s, dst_x, dst_y, w, h); + dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h); } } } @@ -1448,7 +1448,7 @@ void dpy_text_cursor(struct DisplayState *s, int x, int y) struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_text_cursor) { - dcl->ops->dpy_text_cursor(dcl, s, x, y); + dcl->ops->dpy_text_cursor(dcl, x, y); } } } @@ -1458,7 +1458,7 @@ void dpy_text_update(DisplayState *s, int x, int y, int w, int h) struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_text_update) { - dcl->ops->dpy_text_update(dcl, s, x, y, w, h); + dcl->ops->dpy_text_update(dcl, x, y, w, h); } } } @@ -1468,7 +1468,7 @@ void dpy_text_resize(DisplayState *s, int w, int h) struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_text_resize) { - dcl->ops->dpy_text_resize(dcl, s, w, h); + dcl->ops->dpy_text_resize(dcl, w, h); } } } @@ -1478,7 +1478,7 @@ void dpy_mouse_set(struct DisplayState *s, int x, int y, int on) struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_mouse_set) { - dcl->ops->dpy_mouse_set(dcl, s, x, y, on); + dcl->ops->dpy_mouse_set(dcl, x, y, on); } } } @@ -1488,7 +1488,7 @@ void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor) struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_cursor_define) { - dcl->ops->dpy_cursor_define(dcl, s, cursor); + dcl->ops->dpy_cursor_define(dcl, cursor); } } } diff --git a/ui/curses.c b/ui/curses.c index ca9856ccef..ff82307361 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -42,7 +42,6 @@ static int width, height, gwidth, gheight, invalidate; static int px, py, sminx, sminy, smaxx, smaxy; static void curses_update(DisplayChangeListener *dcl, - DisplayState *ds, int x, int y, int w, int h) { chtype *line; @@ -95,7 +94,6 @@ static void curses_calc_pad(void) } static void curses_resize(DisplayChangeListener *dcl, - DisplayState *ds, int width, int height) { if (width == gwidth && height == gheight) { @@ -134,7 +132,6 @@ static void curses_winch_handler(int signum) #endif static void curses_cursor_position(DisplayChangeListener *dcl, - DisplayState *ds, int x, int y) { if (x >= 0) { @@ -161,8 +158,7 @@ static void curses_cursor_position(DisplayChangeListener *dcl, static kbd_layout_t *kbd_layout = NULL; -static void curses_refresh(DisplayChangeListener *dcl, - DisplayState *ds) +static void curses_refresh(DisplayChangeListener *dcl) { int chr, nextchr, keysym, keycode, keycode_alt; @@ -195,7 +191,7 @@ static void curses_refresh(DisplayChangeListener *dcl, clear(); refresh(); curses_calc_pad(); - curses_update(dcl, ds, 0, 0, width, height); + curses_update(dcl, 0, 0, width, height); continue; } #endif diff --git a/ui/gtk.c b/ui/gtk.c index d553550301..305940d0ba 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -266,7 +266,7 @@ static void gd_update_full_redraw(GtkDisplayState *s) /** DisplayState Callbacks **/ static void gd_update(DisplayChangeListener *dcl, - DisplayState *dontuse, int x, int y, int w, int h) + int x, int y, int w, int h) { GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); int x1, x2, y1, y2; @@ -298,14 +298,12 @@ static void gd_update(DisplayChangeListener *dcl, gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1)); } -static void gd_refresh(DisplayChangeListener *dcl, - DisplayState *dontuse) +static void gd_refresh(DisplayChangeListener *dcl) { vga_hw_update(); } static void gd_switch(DisplayChangeListener *dcl, - DisplayState *dontuse, DisplaySurface *surface) { GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); diff --git a/ui/sdl.c b/ui/sdl.c index 58f16bc63e..8da05341bb 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -61,7 +61,6 @@ static int scaling_active = 0; static Notifier mouse_mode_notifier; static void sdl_update(DisplayChangeListener *dcl, - DisplayState *dontuse, int x, int y, int w, int h) { // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); @@ -108,7 +107,6 @@ static void do_sdl_resize(int width, int height, int bpp) } static void sdl_switch(DisplayChangeListener *dcl, - DisplayState *dontuse, DisplaySurface *new_surface) { @@ -523,7 +521,7 @@ static void handle_keydown(SDL_Event *ev) case 0x16: /* 'u' key on US keyboard */ if (scaling_active) { scaling_active = 0; - sdl_switch(dcl, NULL, NULL); + sdl_switch(dcl, NULL); vga_hw_invalidate(); vga_hw_update(); } @@ -763,8 +761,7 @@ static void handle_activation(SDL_Event *ev) } } -static void sdl_refresh(DisplayChangeListener *dcl, - DisplayState *dontuse) +static void sdl_refresh(DisplayChangeListener *dcl) { SDL_Event ev1, *ev = &ev1; @@ -779,7 +776,7 @@ static void sdl_refresh(DisplayChangeListener *dcl, while (SDL_PollEvent(ev)) { switch (ev->type) { case SDL_VIDEOEXPOSE: - sdl_update(dcl, dontuse, 0, 0, real_screen->w, real_screen->h); + sdl_update(dcl, 0, 0, real_screen->w, real_screen->h); break; case SDL_KEYDOWN: handle_keydown(ev); @@ -815,7 +812,6 @@ static void sdl_refresh(DisplayChangeListener *dcl, } static void sdl_mouse_warp(DisplayChangeListener *dcl, - DisplayState *ds, int x, int y, int on) { if (on) { @@ -833,7 +829,6 @@ static void sdl_mouse_warp(DisplayChangeListener *dcl, } static void sdl_mouse_define(DisplayChangeListener *dcl, - DisplayState *ds, QEMUCursor *c) { uint8_t *image, *mask; diff --git a/ui/spice-display.c b/ui/spice-display.c index 5bbe23b8ba..2127b3f37e 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -583,7 +583,6 @@ static const QXLInterface dpy_interface = { }; static void display_update(DisplayChangeListener *dcl, - struct DisplayState *ds, int x, int y, int w, int h) { SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); @@ -591,15 +590,13 @@ static void display_update(DisplayChangeListener *dcl, } static void display_switch(DisplayChangeListener *dcl, - struct DisplayState *ds, struct DisplaySurface *surface) { SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); qemu_spice_display_switch(ssd, surface); } -static void display_refresh(DisplayChangeListener *dcl, - struct DisplayState *ds) +static void display_refresh(DisplayChangeListener *dcl) { SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); qemu_spice_display_refresh(ssd); diff --git a/ui/vnc.c b/ui/vnc.c index f38aeda3e2..bbe1e0f179 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -430,7 +430,6 @@ static void vnc_refresh(void *opaque); static int vnc_refresh_server_surface(VncDisplay *vd); static void vnc_dpy_update(DisplayChangeListener *dcl, - DisplayState *ds, int x, int y, int w, int h) { int i; @@ -575,7 +574,6 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y) } static void vnc_dpy_switch(DisplayChangeListener *dcl, - DisplayState *dontuse, DisplaySurface *surface) { VncDisplay *vd = container_of(dcl, VncDisplay, dcl); @@ -740,7 +738,6 @@ static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, i } static void vnc_dpy_copy(DisplayChangeListener *dcl, - DisplayState *dontuse, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { @@ -814,7 +811,6 @@ static void vnc_dpy_copy(DisplayChangeListener *dcl, } static void vnc_mouse_set(DisplayChangeListener *dcl, - DisplayState *dontuse, int x, int y, int visible) { /* can we ask the client(s) to move the pointer ??? */ @@ -842,7 +838,6 @@ static int vnc_cursor_define(VncState *vs) } static void vnc_dpy_cursor_define(DisplayChangeListener *dcl, - DisplayState *dontuse, QEMUCursor *c) { VncDisplay *vd = vnc_display; From c78f71378a345ea240c288993ca1378ded5504b9 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 5 Mar 2013 15:24:14 +0100 Subject: [PATCH 35/37] console: stop using DisplayState in gfx hardware emulation Use QemuConsole instead. Updates interfaces in console.[ch] and adapts gfx hardware emulation code. Signed-off-by: Gerd Hoffmann --- hw/arm/musicpal.c | 20 +++---- hw/blizzard.c | 37 +++++++------ hw/cirrus_vga.c | 22 ++++---- hw/exynos4210_fimd.c | 17 +++--- hw/framebuffer.c | 4 +- hw/framebuffer.h | 2 +- hw/g364fb.c | 43 ++++++++------- hw/jazz_led.c | 88 +++++++++++++++++------------- hw/milkymist-vgafb.c | 17 +++--- hw/omap_lcdc.c | 47 ++++++++-------- hw/pl110.c | 24 +++++---- hw/pxa2xx_lcd.c | 39 ++++++++------ hw/qxl-render.c | 11 ++-- hw/qxl.c | 12 +++-- hw/sm501.c | 34 ++++++------ hw/ssd0303.c | 17 +++--- hw/ssd0323.c | 19 +++---- hw/tc6393xb.c | 28 ++++++---- hw/tc6393xb_template.h | 5 +- hw/tcx.c | 62 ++++++++++++--------- hw/vga-isa-mm.c | 5 +- hw/vga-isa.c | 4 +- hw/vga-pci.c | 4 +- hw/vga.c | 98 ++++++++++++++++++--------------- hw/vga_int.h | 2 +- hw/vmware_vga.c | 107 +++++++++++++++++++------------------ hw/xenfb.c | 51 ++++++++---------- include/ui/console.h | 34 ++++++------ include/ui/spice-display.h | 3 +- ui/console.c | 94 ++++++++++++++++---------------- ui/spice-display.c | 10 ++-- 31 files changed, 525 insertions(+), 435 deletions(-) diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index a37dbd7961..edd528255f 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -462,7 +462,7 @@ typedef struct musicpal_lcd_state { uint32_t irqctrl; uint32_t page; uint32_t page_off; - DisplayState *ds; + QemuConsole *con; uint8_t video_ram[128*64/8]; } musicpal_lcd_state; @@ -483,7 +483,8 @@ static inline void glue(set_lcd_pixel, depth) \ (musicpal_lcd_state *s, int x, int y, type col) \ { \ int dx, dy; \ - type *pixel = &((type *) ds_get_data(s->ds))[(y * 128 * 3 + x) * 3]; \ + DisplaySurface *surface = qemu_console_surface(s->con); \ + type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \ \ for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \ for (dx = 0; dx < 3; dx++, pixel++) \ @@ -496,9 +497,10 @@ SET_LCD_PIXEL(32, uint32_t) static void lcd_refresh(void *opaque) { musicpal_lcd_state *s = opaque; + DisplaySurface *surface = qemu_console_surface(s->con); int x, y, col; - switch (ds_get_bits_per_pixel(s->ds)) { + switch (surface_bits_per_pixel(surface)) { case 0: return; #define LCD_REFRESH(depth, func) \ @@ -518,14 +520,14 @@ static void lcd_refresh(void *opaque) break; LCD_REFRESH(8, rgb_to_pixel8) LCD_REFRESH(16, rgb_to_pixel16) - LCD_REFRESH(32, (is_surface_bgr(s->ds->surface) ? + LCD_REFRESH(32, (is_surface_bgr(surface) ? rgb_to_pixel32bgr : rgb_to_pixel32)) default: hw_error("unsupported colour depth %i\n", - ds_get_bits_per_pixel(s->ds)); + surface_bits_per_pixel(surface)); } - dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3); + dpy_gfx_update(s->con, 0, 0, 128*3, 64*3); } static void lcd_invalidate(void *opaque) @@ -609,9 +611,9 @@ static int musicpal_lcd_init(SysBusDevice *dev) "musicpal-lcd", MP_LCD_SIZE); sysbus_init_mmio(dev, &s->iomem); - s->ds = graphic_console_init(lcd_refresh, lcd_invalidate, - NULL, NULL, s); - qemu_console_resize(s->ds, 128*3, 64*3); + s->con = graphic_console_init(lcd_refresh, lcd_invalidate, + NULL, 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/blizzard.c b/hw/blizzard.c index 805f4d5558..020d3de431 100644 --- a/hw/blizzard.c +++ b/hw/blizzard.c @@ -69,7 +69,7 @@ typedef struct { uint8_t effect; uint8_t iformat; uint8_t source; - DisplayState *state; + QemuConsole *con; blizzard_fn_t *line_fn_tab[2]; void *fb; @@ -144,6 +144,7 @@ static inline void blizzard_rgb2yuv(int r, int g, int b, static void blizzard_window(BlizzardState *s) { + DisplaySurface *surface = qemu_console_surface(s->con); uint8_t *src, *dst; int bypp[2]; int bypl[3]; @@ -162,7 +163,7 @@ static void blizzard_window(BlizzardState *s) s->my[1] = s->data.y + s->data.dy; bypp[0] = s->bpp; - bypp[1] = (ds_get_bits_per_pixel(s->state) + 7) >> 3; + bypp[1] = surface_bytes_per_pixel(surface); bypl[0] = bypp[0] * s->data.pitch; bypl[1] = bypp[1] * s->x; bypl[2] = bypp[0] * s->data.dx; @@ -883,23 +884,25 @@ void s1d13745_write_block(void *opaque, int dc, static void blizzard_update_display(void *opaque) { BlizzardState *s = (BlizzardState *) opaque; + DisplaySurface *surface = qemu_console_surface(s->con); int y, bypp, bypl, bwidth; uint8_t *src, *dst; if (!s->enable) return; - if (s->x != ds_get_width(s->state) || s->y != ds_get_height(s->state)) { + if (s->x != surface_width(surface) || s->y != surface_height(surface)) { s->invalidate = 1; - qemu_console_resize(s->state, s->x, s->y); + qemu_console_resize(s->con, s->x, s->y); + surface = qemu_console_surface(s->con); } if (s->invalidate) { s->invalidate = 0; if (s->blank) { - bypp = (ds_get_bits_per_pixel(s->state) + 7) >> 3; - memset(ds_get_data(s->state), 0, bypp * s->x * s->y); + bypp = surface_bytes_per_pixel(surface); + memset(surface_data(surface), 0, bypp * s->x * s->y); return; } @@ -912,16 +915,16 @@ static void blizzard_update_display(void *opaque) if (s->mx[1] <= s->mx[0]) return; - bypp = (ds_get_bits_per_pixel(s->state) + 7) >> 3; + bypp = surface_bytes_per_pixel(surface); bypl = bypp * s->x; bwidth = bypp * (s->mx[1] - s->mx[0]); y = s->my[0]; src = s->fb + bypl * y + bypp * s->mx[0]; - dst = ds_get_data(s->state) + bypl * y + bypp * s->mx[0]; + dst = surface_data(surface) + bypl * y + bypp * s->mx[0]; for (; y < s->my[1]; y ++, src += bypl, dst += bypl) memcpy(dst, src, bwidth); - dpy_gfx_update(s->state, s->mx[0], s->my[0], + dpy_gfx_update(s->con, s->mx[0], s->my[0], s->mx[1] - s->mx[0], y - s->my[0]); s->mx[0] = s->x; @@ -934,10 +937,12 @@ 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 && ds_get_data(s->state)) - ppm_save(filename, s->state->surface, errp); + if (s && surface_data(surface)) { + ppm_save(filename, surface, errp); + } } #define DEPTH 8 @@ -954,14 +959,16 @@ static void blizzard_screen_dump(void *opaque, const char *filename, void *s1d13745_init(qemu_irq gpio_int) { BlizzardState *s = (BlizzardState *) g_malloc0(sizeof(*s)); + DisplaySurface *surface; s->fb = g_malloc(0x180000); - s->state = graphic_console_init(blizzard_update_display, - blizzard_invalidate_display, - blizzard_screen_dump, NULL, s); + s->con = graphic_console_init(blizzard_update_display, + blizzard_invalidate_display, + blizzard_screen_dump, NULL, s); + surface = qemu_console_surface(s->con); - switch (ds_get_bits_per_pixel(s->state)) { + switch (surface_bits_per_pixel(surface)) { case 0: s->line_fn_tab[0] = s->line_fn_tab[1] = g_malloc0(sizeof(blizzard_fn_t) * 0x10); diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 7babcb67c8..7a4d63436e 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -729,11 +729,12 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, s->cirrus_blt_width, s->cirrus_blt_height); - if (notify) - qemu_console_copy(s->vga.ds, + if (notify) { + qemu_console_copy(s->vga.con, sx, sy, dx, dy, s->cirrus_blt_width / depth, s->cirrus_blt_height); + } /* we don't have to notify the display that this portion has changed since qemu_console_copy implies this */ @@ -2176,6 +2177,7 @@ static void cirrus_cursor_invalidate(VGACommonState *s1) static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y) { CirrusVGAState *s = container_of(s1, CirrusVGAState, vga); + DisplaySurface *surface = qemu_console_surface(s->vga.con); int w, h, bpp, x1, x2, poffset; unsigned int color0, color1; const uint8_t *palette, *src; @@ -2228,9 +2230,9 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y) color1 = s->vga.rgb_to_pixel(c6_to_8(palette[0xf * 3]), c6_to_8(palette[0xf * 3 + 1]), c6_to_8(palette[0xf * 3 + 2])); - bpp = ((ds_get_bits_per_pixel(s->vga.ds) + 7) >> 3); + bpp = surface_bytes_per_pixel(surface); d1 += x1 * bpp; - switch(ds_get_bits_per_pixel(s->vga.ds)) { + switch (surface_bits_per_pixel(surface)) { default: break; case 8: @@ -2908,9 +2910,9 @@ 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->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, - s); + s->con = graphic_console_init(s->update, s->invalidate, + s->screen_dump, s->text_update, + s); rom_add_vga(VGABIOS_CIRRUS_FILENAME); /* XXX ISA-LFB support */ /* FIXME not qdev yet */ @@ -2957,9 +2959,9 @@ 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.ds = 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.update, s->vga.invalidate, + s->vga.screen_dump, s->vga.text_update, + &s->vga); /* setup PCI */ diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c index 6b31ae33b6..bf316c62ab 100644 --- a/hw/exynos4210_fimd.c +++ b/hw/exynos4210_fimd.c @@ -296,7 +296,7 @@ struct Exynos4210fimdWindow { typedef struct { SysBusDevice busdev; MemoryRegion iomem; - DisplayState *console; + QemuConsole *console; qemu_irq irq[3]; uint32_t vidcon[4]; /* Video main control registers 0-3 */ @@ -1221,16 +1221,18 @@ static void exynos4210_fimd_invalidate(void *opaque) static void exynos4210_update_resolution(Exynos4210fimdState *s) { + DisplaySurface *surface = qemu_console_surface(s->console); + /* LCD resolution is stored in VIDEO TIME CONTROL REGISTER 2 */ uint32_t width = ((s->vidtcon[2] >> FIMD_VIDTCON2_HOR_SHIFT) & FIMD_VIDTCON2_SIZE_MASK) + 1; uint32_t height = ((s->vidtcon[2] >> FIMD_VIDTCON2_VER_SHIFT) & FIMD_VIDTCON2_SIZE_MASK) + 1; - if (s->ifb == NULL || ds_get_width(s->console) != width || - ds_get_height(s->console) != height) { + if (s->ifb == NULL || surface_width(surface) != width || + surface_height(surface) != height) { DPRINT_L1("Resolution changed from %ux%u to %ux%u\n", - ds_get_width(s->console), ds_get_height(s->console), width, height); + surface_width(surface), surface_height(surface), width, height); qemu_console_resize(s->console, width, height); s->ifb = g_realloc(s->ifb, width * height * RGBA_SIZE + 1); memset(s->ifb, 0, width * height * RGBA_SIZE + 1); @@ -1241,6 +1243,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); Exynos4210fimdWindow *w; int i, line; hwaddr fb_line_addr, inc_size; @@ -1253,7 +1256,7 @@ 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 || !ds_get_bits_per_pixel(s->console) || + if (!s || !s->console || !surface_bits_per_pixel(surface) || !s->enabled) { return; } @@ -1299,10 +1302,10 @@ static void exynos4210_fimd_update(void *opaque) uint8_t *d; int bpp; - bpp = ds_get_bits_per_pixel(s->console); + bpp = surface_bits_per_pixel(surface); fimd_update_putpix_qemu(bpp); bpp = (bpp + 1) >> 3; - d = ds_get_data(s->console); + d = surface_data(surface); for (line = first_line; line <= last_line; line++) { fimd_copy_line_toqemu(global_width, s->ifb + global_width * line * RGBA_SIZE, d + global_width * line * bpp); diff --git a/hw/framebuffer.c b/hw/framebuffer.c index d341aa0c6b..7326a98a41 100644 --- a/hw/framebuffer.c +++ b/hw/framebuffer.c @@ -24,7 +24,7 @@ /* Render an image from a shared memory framebuffer. */ void framebuffer_update_display( - DisplayState *ds, + DisplaySurface *ds, MemoryRegion *address_space, hwaddr base, int cols, /* Width in pixels. */ @@ -73,7 +73,7 @@ void framebuffer_update_display( return; } src = src_base; - dest = ds_get_data(ds); + dest = surface_data(ds); if (dest_col_pitch < 0) dest -= dest_col_pitch * (cols - 1); if (dest_row_pitch < 0) { diff --git a/hw/framebuffer.h b/hw/framebuffer.h index 11f53edec0..6eae035b7d 100644 --- a/hw/framebuffer.h +++ b/hw/framebuffer.h @@ -8,7 +8,7 @@ typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int); void framebuffer_update_display( - DisplayState *ds, + DisplaySurface *ds, MemoryRegion *address_space, hwaddr base, int cols, diff --git a/hw/g364fb.c b/hw/g364fb.c index 7b69815bc9..f7014e9dd8 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -39,7 +39,7 @@ typedef struct G364State { uint32_t top_of_screen; uint32_t width, height; /* in pixels */ /* display refresh support */ - DisplayState *ds; + QemuConsole *con; int depth; int blanked; } G364State; @@ -77,6 +77,7 @@ static inline void reset_dirty(G364State *s, static void g364fb_draw_graphic8(G364State *s) { + DisplaySurface *surface = qemu_console_surface(s->con); int i, w; uint8_t *vram; uint8_t *data_display, *dd; @@ -87,7 +88,7 @@ static void g364fb_draw_graphic8(G364State *s) int xcursor, ycursor; unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned int b); - switch (ds_get_bits_per_pixel(s->ds)) { + switch (surface_bits_per_pixel(surface)) { case 8: rgb_to_pixel = rgb_to_pixel8; w = 1; @@ -106,7 +107,7 @@ static void g364fb_draw_graphic8(G364State *s) break; default: hw_error("g364: unknown host depth %d", - ds_get_bits_per_pixel(s->ds)); + surface_bits_per_pixel(surface)); return; } @@ -129,7 +130,7 @@ static void g364fb_draw_graphic8(G364State *s) vram = s->vram + s->top_of_screen; /* XXX: out of range in vram? */ - data_display = dd = ds_get_data(s->ds); + data_display = dd = surface_data(surface); while (y < s->height) { if (check_dirty(s, page)) { if (y < ymin) @@ -182,7 +183,7 @@ static void g364fb_draw_graphic8(G364State *s) ymax = s->height - 1; goto done; } - data_display = dd = data_display + ds_get_linesize(s->ds); + data_display = dd = data_display + surface_stride(surface); xmin = 0; x = 0; } @@ -197,7 +198,7 @@ static void g364fb_draw_graphic8(G364State *s) reset_dirty(s, page_min, page_max); page_min = (ram_addr_t)-1; page_max = 0; - dpy_gfx_update(s->ds, xmin, ymin, + dpy_gfx_update(s->con, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); xmin = s->width; xmax = 0; @@ -209,7 +210,7 @@ static void g364fb_draw_graphic8(G364State *s) x = x % s->width; y += dy; vram += G364_PAGE_SIZE; - data_display += dy * ds_get_linesize(s->ds); + data_display += dy * surface_stride(surface); dd = data_display + x * w; } page += G364_PAGE_SIZE; @@ -217,13 +218,14 @@ static void g364fb_draw_graphic8(G364State *s) done: if (page_min != (ram_addr_t)-1) { - dpy_gfx_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); + dpy_gfx_update(s->con, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); reset_dirty(s, page_min, page_max); } } static void g364fb_draw_blank(G364State *s) { + DisplaySurface *surface = qemu_console_surface(s->con); int i, w; uint8_t *d; @@ -232,28 +234,30 @@ static void g364fb_draw_blank(G364State *s) return; } - w = s->width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); - d = ds_get_data(s->ds); + w = s->width * surface_bytes_per_pixel(surface); + d = surface_data(surface); for (i = 0; i < s->height; i++) { memset(d, 0, w); - d += ds_get_linesize(s->ds); + d += surface_stride(surface); } - dpy_gfx_update(s->ds, 0, 0, s->width, s->height); + dpy_gfx_update(s->con, 0, 0, s->width, s->height); s->blanked = 1; } static void g364fb_update_display(void *opaque) { G364State *s = opaque; + DisplaySurface *surface = qemu_console_surface(s->con); qemu_flush_coalesced_mmio_buffer(); if (s->width == 0 || s->height == 0) return; - if (s->width != ds_get_width(s->ds) || s->height != ds_get_height(s->ds)) { - qemu_console_resize(s->ds, s->width, s->height); + if (s->width != surface_width(surface) || + s->height != surface_height(surface)) { + qemu_console_resize(s->con, s->width, s->height); } if (s->ctla & CTLA_FORCE_BLANK) { @@ -413,13 +417,14 @@ static void g364fb_update_depth(G364State *s) static void g364_invalidate_cursor_position(G364State *s) { + DisplaySurface *surface = qemu_console_surface(s->con); int ymin, ymax, start, end; /* invalidate only near the cursor */ ymin = s->cursor_position & 0xfff; ymax = MIN(s->height, ymin + 64); - start = ymin * ds_get_linesize(s->ds); - end = (ymax + 1) * ds_get_linesize(s->ds); + start = ymin * surface_stride(surface); + end = (ymax + 1) * surface_stride(surface); memory_region_set_dirty(&s->mem_vram, start, end - start); } @@ -545,9 +550,9 @@ static void g364fb_init(DeviceState *dev, G364State *s) { s->vram = g_malloc0(s->vram_size); - s->ds = graphic_console_init(g364fb_update_display, - g364fb_invalidate_display, - g364fb_screen_dump, NULL, s); + s->con = graphic_console_init(g364fb_update_display, + g364fb_invalidate_display, + g364fb_screen_dump, 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/jazz_led.c b/hw/jazz_led.c index a418a7d1b6..05528c7c81 100644 --- a/hw/jazz_led.c +++ b/hw/jazz_led.c @@ -36,7 +36,7 @@ typedef struct LedState { SysBusDevice busdev; MemoryRegion iomem; uint8_t segments; - DisplayState *ds; + QemuConsole *con; screen_state_t state; } LedState; @@ -75,13 +75,15 @@ static const MemoryRegionOps led_ops = { /***********************************************************/ /* jazz_led display */ -static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx2, uint32_t color) +static void draw_horizontal_line(DisplaySurface *ds, + int posy, int posx1, int posx2, + uint32_t color) { uint8_t *d; int x, bpp; - bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; - d = ds_get_data(ds) + ds_get_linesize(ds) * posy + bpp * posx1; + bpp = (surface_bits_per_pixel(ds) + 7) >> 3; + d = surface_data(ds) + surface_stride(ds) * posy + bpp * posx1; switch(bpp) { case 1: for (x = posx1; x <= posx2; x++) { @@ -104,30 +106,32 @@ static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx } } -static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2, uint32_t color) +static void draw_vertical_line(DisplaySurface *ds, + int posx, int posy1, int posy2, + uint32_t color) { uint8_t *d; int y, bpp; - bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; - d = ds_get_data(ds) + ds_get_linesize(ds) * posy1 + bpp * posx; + bpp = (surface_bits_per_pixel(ds) + 7) >> 3; + d = surface_data(ds) + surface_stride(ds) * posy1 + bpp * posx; switch(bpp) { case 1: for (y = posy1; y <= posy2; y++) { *((uint8_t *)d) = color; - d += ds_get_linesize(ds); + d += surface_stride(ds); } break; case 2: for (y = posy1; y <= posy2; y++) { *((uint16_t *)d) = color; - d += ds_get_linesize(ds); + d += surface_stride(ds); } break; case 4: for (y = posy1; y <= posy2; y++) { *((uint32_t *)d) = color; - d += ds_get_linesize(ds); + d += surface_stride(ds); } break; } @@ -136,24 +140,24 @@ static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2, static void jazz_led_update_display(void *opaque) { LedState *s = opaque; - DisplayState *ds = s->ds; + DisplaySurface *surface = qemu_console_surface(s->con); uint8_t *d1; uint32_t color_segment, color_led; int y, bpp; if (s->state & REDRAW_BACKGROUND) { /* clear screen */ - bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; - d1 = ds_get_data(ds); - for (y = 0; y < ds_get_height(ds); y++) { - memset(d1, 0x00, ds_get_width(ds) * bpp); - d1 += ds_get_linesize(ds); + bpp = (surface_bits_per_pixel(surface) + 7) >> 3; + d1 = surface_data(surface); + for (y = 0; y < surface_height(surface); y++) { + memset(d1, 0x00, surface_width(surface) * bpp); + d1 += surface_stride(surface); } } if (s->state & REDRAW_SEGMENTS) { /* set colors according to bpp */ - switch (ds_get_bits_per_pixel(ds)) { + switch (surface_bits_per_pixel(surface)) { case 8: color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa); color_led = rgb_to_pixel8(0x00, 0xff, 0x00); @@ -178,26 +182,34 @@ static void jazz_led_update_display(void *opaque) } /* display segments */ - draw_horizontal_line(ds, 40, 10, 40, (s->segments & 0x02) ? color_segment : 0); - draw_vertical_line(ds, 10, 10, 40, (s->segments & 0x04) ? color_segment : 0); - draw_vertical_line(ds, 10, 40, 70, (s->segments & 0x08) ? color_segment : 0); - draw_horizontal_line(ds, 70, 10, 40, (s->segments & 0x10) ? color_segment : 0); - draw_vertical_line(ds, 40, 40, 70, (s->segments & 0x20) ? color_segment : 0); - draw_vertical_line(ds, 40, 10, 40, (s->segments & 0x40) ? color_segment : 0); - draw_horizontal_line(ds, 10, 10, 40, (s->segments & 0x80) ? color_segment : 0); + draw_horizontal_line(surface, 40, 10, 40, + (s->segments & 0x02) ? color_segment : 0); + draw_vertical_line(surface, 10, 10, 40, + (s->segments & 0x04) ? color_segment : 0); + draw_vertical_line(surface, 10, 40, 70, + (s->segments & 0x08) ? color_segment : 0); + draw_horizontal_line(surface, 70, 10, 40, + (s->segments & 0x10) ? color_segment : 0); + draw_vertical_line(surface, 40, 40, 70, + (s->segments & 0x20) ? color_segment : 0); + draw_vertical_line(surface, 40, 10, 40, + (s->segments & 0x40) ? color_segment : 0); + draw_horizontal_line(surface, 10, 10, 40, + (s->segments & 0x80) ? color_segment : 0); /* display led */ if (!(s->segments & 0x01)) color_led = 0; /* black */ - draw_horizontal_line(ds, 68, 50, 50, color_led); - draw_horizontal_line(ds, 69, 49, 51, color_led); - draw_horizontal_line(ds, 70, 48, 52, color_led); - draw_horizontal_line(ds, 71, 49, 51, color_led); - draw_horizontal_line(ds, 72, 50, 50, color_led); + draw_horizontal_line(surface, 68, 50, 50, color_led); + draw_horizontal_line(surface, 69, 49, 51, color_led); + draw_horizontal_line(surface, 70, 48, 52, color_led); + draw_horizontal_line(surface, 71, 49, 51, color_led); + draw_horizontal_line(surface, 72, 50, 50, color_led); } s->state = REDRAW_NONE; - dpy_gfx_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); + dpy_gfx_update(s->con, 0, 0, + surface_width(surface), surface_height(surface)); } static void jazz_led_invalidate_display(void *opaque) @@ -211,15 +223,15 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata) LedState *s = opaque; char buf[2]; - dpy_text_cursor(s->ds, -1, -1); - qemu_console_resize(s->ds, 2, 1); + dpy_text_cursor(s->con, -1, -1); + qemu_console_resize(s->con, 2, 1); /* TODO: draw the segments */ snprintf(buf, 2, "%02hhx\n", s->segments); console_write_ch(chardata++, 0x00200100 | buf[0]); console_write_ch(chardata++, 0x00200100 | buf[1]); - dpy_text_update(s->ds, 0, 0, 2, 1); + dpy_text_update(s->con, 0, 0, 2, 1); } static int jazz_led_post_load(void *opaque, int version_id) @@ -249,10 +261,10 @@ 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->ds = graphic_console_init(jazz_led_update_display, - jazz_led_invalidate_display, - NULL, - jazz_led_text_update, s); + s->con = graphic_console_init(jazz_led_update_display, + jazz_led_invalidate_display, + NULL, + jazz_led_text_update, s); return 0; } @@ -263,7 +275,7 @@ static void jazz_led_reset(DeviceState *d) s->segments = 0; s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND; - qemu_console_resize(s->ds, 60, 80); + qemu_console_resize(s->con, 60, 80); } static void jazz_led_class_init(ObjectClass *klass, void *data) diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c index 85ebb851bd..98762ecd21 100644 --- a/hw/milkymist-vgafb.c +++ b/hw/milkymist-vgafb.c @@ -66,7 +66,7 @@ enum { struct MilkymistVgafbState { SysBusDevice busdev; MemoryRegion regs_region; - DisplayState *ds; + QemuConsole *con; int invalidate; uint32_t fb_offset; @@ -84,6 +84,7 @@ static int vgafb_enabled(MilkymistVgafbState *s) static void vgafb_update_display(void *opaque) { MilkymistVgafbState *s = opaque; + DisplaySurface *surface = qemu_console_surface(s->con); int first = 0; int last = 0; drawfn fn; @@ -94,7 +95,7 @@ static void vgafb_update_display(void *opaque) int dest_width = s->regs[R_HRES]; - switch (ds_get_bits_per_pixel(s->ds)) { + switch (surface_bits_per_pixel(surface)) { case 0: return; case 8: @@ -121,7 +122,7 @@ static void vgafb_update_display(void *opaque) break; } - framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev), + framebuffer_update_display(surface, sysbus_address_space(&s->busdev), s->regs[R_BASEADDRESS] + s->fb_offset, s->regs[R_HRES], s->regs[R_VRES], @@ -134,7 +135,7 @@ static void vgafb_update_display(void *opaque) &first, &last); if (first >= 0) { - dpy_gfx_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1); + dpy_gfx_update(s->con, 0, first, s->regs[R_HRES], last - first + 1); } s->invalidate = 0; } @@ -151,7 +152,7 @@ static void vgafb_resize(MilkymistVgafbState *s) return; } - qemu_console_resize(s->ds, s->regs[R_HRES], s->regs[R_VRES]); + qemu_console_resize(s->con, s->regs[R_HRES], s->regs[R_VRES]); s->invalidate = 1; } @@ -277,9 +278,9 @@ static int milkymist_vgafb_init(SysBusDevice *dev) "milkymist-vgafb", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); - s->ds = graphic_console_init(vgafb_update_display, - vgafb_invalidate_display, - NULL, NULL, s); + s->con = graphic_console_init(vgafb_update_display, + vgafb_invalidate_display, + NULL, NULL, s); return 0; } diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c index c426f3a13a..4f5b0947cf 100644 --- a/hw/omap_lcdc.c +++ b/hw/omap_lcdc.c @@ -26,7 +26,7 @@ struct omap_lcd_panel_s { MemoryRegion *sysmem; MemoryRegion iomem; qemu_irq irq; - DisplayState *state; + QemuConsole *con; int plm; int tft; @@ -113,14 +113,16 @@ static draw_line_func draw_line_table2[33] = { static void omap_update_display(void *opaque) { struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque; + DisplaySurface *surface = qemu_console_surface(omap_lcd->con); draw_line_func draw_line; int size, height, first, last; int width, linesize, step, bpp, frame_offset; hwaddr frame_base; - if (!omap_lcd || omap_lcd->plm == 1 || - !omap_lcd->enable || !ds_get_bits_per_pixel(omap_lcd->state)) + if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable || + !surface_bits_per_pixel(surface)) { return; + } frame_offset = 0; if (omap_lcd->plm != 2) { @@ -139,25 +141,25 @@ static void omap_update_display(void *opaque) /* Colour depth */ switch ((omap_lcd->palette[0] >> 12) & 7) { case 1: - draw_line = draw_line_table2[ds_get_bits_per_pixel(omap_lcd->state)]; + draw_line = draw_line_table2[surface_bits_per_pixel(surface)]; bpp = 2; break; case 2: - draw_line = draw_line_table4[ds_get_bits_per_pixel(omap_lcd->state)]; + draw_line = draw_line_table4[surface_bits_per_pixel(surface)]; bpp = 4; break; case 3: - draw_line = draw_line_table8[ds_get_bits_per_pixel(omap_lcd->state)]; + draw_line = draw_line_table8[surface_bits_per_pixel(surface)]; bpp = 8; break; case 4 ... 7: if (!omap_lcd->tft) - draw_line = draw_line_table12[ds_get_bits_per_pixel(omap_lcd->state)]; + draw_line = draw_line_table12[surface_bits_per_pixel(surface)]; else - draw_line = draw_line_table16[ds_get_bits_per_pixel(omap_lcd->state)]; + draw_line = draw_line_table16[surface_bits_per_pixel(surface)]; bpp = 16; break; @@ -168,10 +170,11 @@ static void omap_update_display(void *opaque) /* Resolution */ width = omap_lcd->width; - if (width != ds_get_width(omap_lcd->state) || - omap_lcd->height != ds_get_height(omap_lcd->state)) { - qemu_console_resize(omap_lcd->state, + if (width != surface_width(surface) || + omap_lcd->height != surface_height(surface)) { + qemu_console_resize(omap_lcd->con, omap_lcd->width, omap_lcd->height); + surface = qemu_console_surface(omap_lcd->con); omap_lcd->invalidate = 1; } @@ -196,8 +199,9 @@ static void omap_update_display(void *opaque) if (omap_lcd->dma->dual) omap_lcd->dma->current_frame ^= 1; - if (!ds_get_bits_per_pixel(omap_lcd->state)) + if (!surface_bits_per_pixel(surface)) { return; + } first = 0; height = omap_lcd->height; @@ -210,15 +214,15 @@ static void omap_update_display(void *opaque) } step = width * bpp >> 3; - linesize = ds_get_linesize(omap_lcd->state); - framebuffer_update_display(omap_lcd->state, omap_lcd->sysmem, + linesize = surface_stride(surface); + framebuffer_update_display(surface, omap_lcd->sysmem, frame_base, width, height, step, linesize, 0, omap_lcd->invalidate, draw_line, omap_lcd->palette, &first, &last); if (first >= 0) { - dpy_gfx_update(omap_lcd->state, 0, first, width, last - first + 1); + dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1); } omap_lcd->invalidate = 0; } @@ -298,12 +302,13 @@ 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 && ds_get_data(omap_lcd->state)) - omap_ppm_save(filename, ds_get_data(omap_lcd->state), + if (omap_lcd && surface_data(surface)) + omap_ppm_save(filename, surface_data(surface), omap_lcd->width, omap_lcd->height, - ds_get_linesize(omap_lcd->state), errp); + surface_stride(surface), errp); } static void omap_invalidate_display(void *opaque) { @@ -480,9 +485,9 @@ 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->state = graphic_console_init(omap_update_display, - omap_invalidate_display, - omap_screen_dump, NULL, s); + s->con = graphic_console_init(omap_update_display, + omap_invalidate_display, + omap_screen_dump, NULL, s); return s; } diff --git a/hw/pl110.c b/hw/pl110.c index 924642d697..fbef675f9c 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -42,7 +42,7 @@ enum pl110_version typedef struct { SysBusDevice busdev; MemoryRegion iomem; - DisplayState *ds; + QemuConsole *con; int version; uint32_t timing[4]; @@ -129,6 +129,7 @@ static int pl110_enabled(pl110_state *s) static void pl110_update_display(void *opaque) { pl110_state *s = (pl110_state *)opaque; + DisplaySurface *surface = qemu_console_surface(s->con); drawfn* fntable; drawfn fn; int dest_width; @@ -140,7 +141,7 @@ static void pl110_update_display(void *opaque) if (!pl110_enabled(s)) return; - switch (ds_get_bits_per_pixel(s->ds)) { + switch (surface_bits_per_pixel(surface)) { case 0: return; case 8: @@ -231,14 +232,14 @@ static void pl110_update_display(void *opaque) } dest_width *= s->cols; first = 0; - framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev), + framebuffer_update_display(surface, sysbus_address_space(&s->busdev), s->upbase, s->cols, s->rows, src_width, dest_width, 0, s->invalidate, fn, s->palette, &first, &last); if (first >= 0) { - dpy_gfx_update(s->ds, 0, first, s->cols, last - first + 1); + dpy_gfx_update(s->con, 0, first, s->cols, last - first + 1); } s->invalidate = 0; } @@ -248,12 +249,13 @@ static void pl110_invalidate_display(void * opaque) pl110_state *s = (pl110_state *)opaque; s->invalidate = 1; if (pl110_enabled(s)) { - qemu_console_resize(s->ds, s->cols, s->rows); + qemu_console_resize(s->con, s->cols, s->rows); } } static void pl110_update_palette(pl110_state *s, int n) { + DisplaySurface *surface = qemu_console_surface(s->con); int i; uint32_t raw; unsigned int r, g, b; @@ -268,7 +270,7 @@ static void pl110_update_palette(pl110_state *s, int n) b = (raw & 0x1f) << 3; /* The I bit is ignored. */ raw >>= 6; - switch (ds_get_bits_per_pixel(s->ds)) { + switch (surface_bits_per_pixel(surface)) { case 8: s->palette[n] = rgb_to_pixel8(r, g, b); break; @@ -291,7 +293,7 @@ static void pl110_resize(pl110_state *s, int width, int height) { if (width != s->cols || height != s->rows) { if (pl110_enabled(s)) { - qemu_console_resize(s->ds, width, height); + qemu_console_resize(s->con, width, height); } } s->cols = width; @@ -409,7 +411,7 @@ static void pl110_write(void *opaque, hwaddr offset, s->cr = val; s->bpp = (val >> 1) & 7; if (pl110_enabled(s)) { - qemu_console_resize(s->ds, s->cols, s->rows); + qemu_console_resize(s->con, s->cols, s->rows); } break; case 10: /* LCDICR */ @@ -450,9 +452,9 @@ 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->ds = graphic_console_init(pl110_update_display, - pl110_invalidate_display, - NULL, NULL, s); + s->con = graphic_console_init(pl110_update_display, + pl110_invalidate_display, + NULL, NULL, s); return 0; } diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index 6484d27de1..f2b0c93661 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -39,7 +39,7 @@ struct PXA2xxLCDState { int irqlevel; int invalidated; - DisplayState *ds; + QemuConsole *con; drawfn *line_fn[2]; int dest_width; int xres, yres; @@ -579,6 +579,7 @@ static const MemoryRegionOps pxa2xx_lcdc_ops = { /* Load new palette for a given DMA channel, convert to internal format */ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp) { + DisplaySurface *surface = qemu_console_surface(s->con); int i, n, format, r, g, b, alpha; uint32_t *dest; uint8_t *src; @@ -652,7 +653,7 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp) src += 4; break; } - switch (ds_get_bits_per_pixel(s->ds)) { + switch (surface_bits_per_pixel(surface)) { case 8: *dest = rgb_to_pixel8(r, g, b) | alpha; break; @@ -676,6 +677,7 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp) static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s, hwaddr addr, int *miny, int *maxy) { + DisplaySurface *surface = qemu_console_surface(s->con); int src_width, dest_width; drawfn fn = NULL; if (s->dest_width) @@ -693,7 +695,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s, dest_width = s->xres * s->dest_width; *miny = 0; - framebuffer_update_display(s->ds, s->sysmem, + framebuffer_update_display(surface, s->sysmem, addr, s->xres, s->yres, src_width, dest_width, s->dest_width, s->invalidated, @@ -703,6 +705,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s, static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s, hwaddr addr, int *miny, int *maxy) { + DisplaySurface *surface = qemu_console_surface(s->con); int src_width, dest_width; drawfn fn = NULL; if (s->dest_width) @@ -720,7 +723,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s, dest_width = s->yres * s->dest_width; *miny = 0; - framebuffer_update_display(s->ds, s->sysmem, + framebuffer_update_display(surface, s->sysmem, addr, s->xres, s->yres, src_width, s->dest_width, -dest_width, s->invalidated, @@ -731,6 +734,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s, static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s, hwaddr addr, int *miny, int *maxy) { + DisplaySurface *surface = qemu_console_surface(s->con); int src_width, dest_width; drawfn fn = NULL; if (s->dest_width) { @@ -751,7 +755,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s, dest_width = s->xres * s->dest_width; *miny = 0; - framebuffer_update_display(s->ds, s->sysmem, + framebuffer_update_display(surface, s->sysmem, addr, s->xres, s->yres, src_width, -dest_width, -s->dest_width, s->invalidated, @@ -761,6 +765,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s, static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s, hwaddr addr, int *miny, int *maxy) { + DisplaySurface *surface = qemu_console_surface(s->con); int src_width, dest_width; drawfn fn = NULL; if (s->dest_width) { @@ -781,7 +786,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s, dest_width = s->yres * s->dest_width; *miny = 0; - framebuffer_update_display(s->ds, s->sysmem, + framebuffer_update_display(surface, s->sysmem, addr, s->xres, s->yres, src_width, -s->dest_width, dest_width, s->invalidated, @@ -800,9 +805,9 @@ static void pxa2xx_lcdc_resize(PXA2xxLCDState *s) if (width != s->xres || height != s->yres) { if (s->orientation == 90 || s->orientation == 270) { - qemu_console_resize(s->ds, height, width); + qemu_console_resize(s->con, height, width); } else { - qemu_console_resize(s->ds, width, height); + qemu_console_resize(s->con, width, height); } s->invalidated = 1; s->xres = width; @@ -871,20 +876,20 @@ static void pxa2xx_update_display(void *opaque) if (miny >= 0) { switch (s->orientation) { case 0: - dpy_gfx_update(s->ds, 0, miny, s->xres, maxy - miny + 1); + dpy_gfx_update(s->con, 0, miny, s->xres, maxy - miny + 1); break; case 90: - dpy_gfx_update(s->ds, miny, 0, maxy - miny + 1, s->xres); + dpy_gfx_update(s->con, miny, 0, maxy - miny + 1, s->xres); break; case 180: maxy = s->yres - maxy - 1; miny = s->yres - miny - 1; - dpy_gfx_update(s->ds, 0, maxy, s->xres, miny - maxy + 1); + dpy_gfx_update(s->con, 0, maxy, s->xres, miny - maxy + 1); break; case 270: maxy = s->yres - maxy - 1; miny = s->yres - miny - 1; - dpy_gfx_update(s->ds, maxy, 0, miny - maxy + 1, s->xres); + dpy_gfx_update(s->con, maxy, 0, miny - maxy + 1, s->xres); break; } } @@ -990,6 +995,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, hwaddr base, qemu_irq irq) { PXA2xxLCDState *s; + DisplaySurface *surface; s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState)); s->invalidated = 1; @@ -1002,11 +1008,12 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, "pxa2xx-lcd-controller", 0x00100000); memory_region_add_subregion(sysmem, base, &s->iomem); - s->ds = graphic_console_init(pxa2xx_update_display, - pxa2xx_invalidate_display, - NULL, NULL, s); + s->con = graphic_console_init(pxa2xx_update_display, + pxa2xx_invalidate_display, + NULL, NULL, s); + surface = qemu_console_surface(s->con); - switch (ds_get_bits_per_pixel(s->ds)) { + switch (surface_bits_per_pixel(surface)) { case 0: s->dest_width = 0; break; diff --git a/hw/qxl-render.c b/hw/qxl-render.c index 087679e142..8cd9be434d 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -23,11 +23,12 @@ static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect) { + DisplaySurface *surface = qemu_console_surface(qxl->vga.con); + uint8_t *dst = surface_data(surface); uint8_t *src; - uint8_t *dst = ds_get_data(qxl->vga.ds); int len, i; - if (is_buffer_shared(qxl->vga.ds->surface)) { + if (is_buffer_shared(surface)) { return; } if (!qxl->guest_primary.data) { @@ -125,14 +126,14 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) (qxl->guest_primary.surface.width, qxl->guest_primary.surface.height); } - dpy_gfx_replace_surface(vga->ds, surface); + dpy_gfx_replace_surface(vga->con, surface); } for (i = 0; i < qxl->num_dirty_rects; i++) { if (qemu_spice_rect_is_empty(qxl->dirty+i)) { break; } qxl_blit(qxl, qxl->dirty+i); - dpy_gfx_update(vga->ds, + dpy_gfx_update(vga->con, qxl->dirty[i].left, qxl->dirty[i].top, qxl->dirty[i].right - qxl->dirty[i].left, qxl->dirty[i].bottom - qxl->dirty[i].top); @@ -236,7 +237,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) return 1; } - if (!dpy_cursor_define_supported(qxl->ssd.dcl.ds)) { + if (!dpy_cursor_define_supported(qxl->vga.con)) { return 0; } diff --git a/hw/qxl.c b/hw/qxl.c index 0939ace88e..b66b41442a 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -2063,6 +2063,7 @@ static int qxl_init_primary(PCIDevice *dev) PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev); VGACommonState *vga = &qxl->vga; PortioList *qxl_vga_port_list = g_new(PortioList, 1); + DisplayState *ds; int rc; qxl->id = 0; @@ -2073,9 +2074,11 @@ 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->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate, - qxl_hw_screen_dump, qxl_hw_text_update, qxl); - qemu_spice_display_init_common(&qxl->ssd, vga->ds); + 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, + qemu_spice_display_init_common(&qxl->ssd); rc = qxl_init_common(qxl); if (rc != 0) { @@ -2083,7 +2086,8 @@ static int qxl_init_primary(PCIDevice *dev) } qxl->ssd.dcl.ops = &display_listener_ops; - register_displaychangelistener(vga->ds, &qxl->ssd.dcl); + ds = qemu_console_displaystate(vga->con); + register_displaychangelistener(ds, &qxl->ssd.dcl); return rc; } diff --git a/hw/sm501.c b/hw/sm501.c index 0e019111bb..93a06c90b9 100644 --- a/hw/sm501.c +++ b/hw/sm501.c @@ -454,7 +454,7 @@ static const uint32_t sm501_mem_local_size[] = { typedef struct SM501State { /* graphic console status */ - DisplayState *ds; + QemuConsole *con; /* status & internal resources */ hwaddr base; @@ -1234,9 +1234,9 @@ static draw_hwc_line_func * draw_hwc_line_funcs[] = { draw_hwc_line_16bgr, }; -static inline int get_depth_index(DisplayState *s) +static inline int get_depth_index(DisplaySurface *surface) { - switch(ds_get_bits_per_pixel(s)) { + switch (surface_bits_per_pixel(surface)) { default: case 8: return 0; @@ -1245,26 +1245,28 @@ static inline int get_depth_index(DisplayState *s) case 16: return 2; case 32: - if (is_surface_bgr(s->surface)) - return 4; - else - return 3; + if (is_surface_bgr(surface)) { + return 4; + } else { + return 3; + } } } static void sm501_draw_crt(SM501State * s) { + DisplaySurface *surface = qemu_console_surface(s->con); int y; int width = (s->dc_crt_h_total & 0x00000FFF) + 1; int height = (s->dc_crt_v_total & 0x00000FFF) + 1; uint8_t * src = s->local_mem; int src_bpp = 0; - int dst_bpp = ds_get_bytes_per_pixel(s->ds) + (ds_get_bits_per_pixel(s->ds) % 8 ? 1 : 0); + int dst_bpp = surface_bytes_per_pixel(surface); uint32_t * palette = (uint32_t *)&s->dc_palette[SM501_DC_CRT_PALETTE - SM501_DC_PANEL_PALETTE]; uint8_t hwc_palette[3 * 3]; - int ds_depth_index = get_depth_index(s->ds); + int ds_depth_index = get_depth_index(surface); draw_line_func * draw_line = NULL; draw_hwc_line_func * draw_hwc_line = NULL; int full_update = 0; @@ -1312,7 +1314,8 @@ static void sm501_draw_crt(SM501State * s) /* adjust console size */ if (s->last_width != width || s->last_height != height) { - qemu_console_resize(s->ds, width, height); + qemu_console_resize(s->con, width, height); + surface = qemu_console_surface(s->con); s->last_width = width; s->last_height = height; full_update = 1; @@ -1331,7 +1334,8 @@ static void sm501_draw_crt(SM501State * s) /* draw line and change status */ if (update) { - uint8_t * d = &(ds_get_data(s->ds)[y * width * dst_bpp]); + uint8_t *d = surface_data(surface); + d += y * width * dst_bpp; /* draw graphics layer */ draw_line(d, src, width, palette); @@ -1350,7 +1354,7 @@ static void sm501_draw_crt(SM501State * s) } else { if (y_start >= 0) { /* flush to display */ - dpy_gfx_update(s->ds, 0, y_start, width, y - y_start); + dpy_gfx_update(s->con, 0, y_start, width, y - y_start); y_start = -1; } } @@ -1361,7 +1365,7 @@ static void sm501_draw_crt(SM501State * s) /* complete flush to display */ if (y_start >= 0) - dpy_gfx_update(s->ds, 0, y_start, width, y - y_start); + dpy_gfx_update(s->con, 0, y_start, width, y - y_start); /* clear dirty flags */ if (page_min != ~0l) { @@ -1441,6 +1445,6 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base, } /* create qemu graphic console */ - s->ds = graphic_console_init(sm501_update_display, NULL, - NULL, NULL, s); + s->con = graphic_console_init(sm501_update_display, NULL, + NULL, NULL, s); } diff --git a/hw/ssd0303.c b/hw/ssd0303.c index db50909734..68d1f24b06 100644 --- a/hw/ssd0303.c +++ b/hw/ssd0303.c @@ -43,7 +43,7 @@ enum ssd0303_cmd { typedef struct { I2CSlave i2c; - DisplayState *ds; + QemuConsole *con; int row; int col; int start_line; @@ -191,6 +191,7 @@ static void ssd0303_event(I2CSlave *i2c, enum i2c_event event) static void ssd0303_update_display(void *opaque) { ssd0303_state *s = (ssd0303_state *)opaque; + DisplaySurface *surface = qemu_console_surface(s->con); uint8_t *dest; uint8_t *src; int x; @@ -204,7 +205,7 @@ static void ssd0303_update_display(void *opaque) if (!s->redraw) return; - switch (ds_get_bits_per_pixel(s->ds)) { + switch (surface_bits_per_pixel(surface)) { case 0: return; case 15: @@ -236,7 +237,7 @@ static void ssd0303_update_display(void *opaque) colors[0] = colortab + dest_width; colors[1] = colortab; } - dest = ds_get_data(s->ds); + dest = surface_data(surface); for (y = 0; y < 16; y++) { line = (y + s->start_line) & 63; src = s->framebuffer + 132 * (line >> 3) + 36; @@ -252,7 +253,7 @@ static void ssd0303_update_display(void *opaque) } } s->redraw = 0; - dpy_gfx_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY); + dpy_gfx_update(s->con, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY); } static void ssd0303_invalidate_display(void * opaque) @@ -287,10 +288,10 @@ static int ssd0303_init(I2CSlave *i2c) { ssd0303_state *s = FROM_I2C_SLAVE(ssd0303_state, i2c); - s->ds = graphic_console_init(ssd0303_update_display, - ssd0303_invalidate_display, - NULL, NULL, s); - qemu_console_resize(s->ds, 96 * MAGNIFY, 16 * MAGNIFY); + s->con = graphic_console_init(ssd0303_update_display, + ssd0303_invalidate_display, + NULL, NULL, s); + qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY); return 0; } diff --git a/hw/ssd0323.c b/hw/ssd0323.c index 27b4151994..5cf2f7058f 100644 --- a/hw/ssd0323.c +++ b/hw/ssd0323.c @@ -45,7 +45,7 @@ enum ssd0323_mode typedef struct { SSISlave ssidev; - DisplayState *ds; + QemuConsole *con; int cmd_len; int cmd; @@ -175,6 +175,7 @@ static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data) static void ssd0323_update_display(void *opaque) { ssd0323_state *s = (ssd0323_state *)opaque; + DisplaySurface *surface = qemu_console_surface(s->con); uint8_t *dest; uint8_t *src; int x; @@ -189,7 +190,7 @@ static void ssd0323_update_display(void *opaque) if (!s->redraw) return; - switch (ds_get_bits_per_pixel(s->ds)) { + switch (surface_bits_per_pixel(surface)) { case 0: return; case 15: @@ -212,7 +213,7 @@ static void ssd0323_update_display(void *opaque) for (i = 0; i < 16; i++) { int n; colors[i] = p; - switch (ds_get_bits_per_pixel(s->ds)) { + switch (surface_bits_per_pixel(surface)) { case 15: n = i * 2 + (i >> 3); p[0] = n | (n << 5); @@ -235,7 +236,7 @@ static void ssd0323_update_display(void *opaque) p += dest_width; } /* TODO: Implement row/column remapping. */ - dest = ds_get_data(s->ds); + dest = surface_data(surface); for (y = 0; y < 64; y++) { line = y; src = s->framebuffer + 64 * line; @@ -260,7 +261,7 @@ static void ssd0323_update_display(void *opaque) } } s->redraw = 0; - dpy_gfx_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY); + dpy_gfx_update(s->con, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY); } static void ssd0323_invalidate_display(void * opaque) @@ -336,10 +337,10 @@ static int ssd0323_init(SSISlave *dev) s->col_end = 63; s->row_end = 79; - s->ds = graphic_console_init(ssd0323_update_display, - ssd0323_invalidate_display, - NULL, NULL, s); - qemu_console_resize(s->ds, 128 * MAGNIFY, 64 * MAGNIFY); + s->con = graphic_console_init(ssd0323_update_display, + ssd0323_invalidate_display, + NULL, NULL, s); + qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY); qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1); diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c index 0755463a1d..79c971b439 100644 --- a/hw/tc6393xb.c +++ b/hw/tc6393xb.c @@ -125,7 +125,7 @@ struct TC6393xbState { DeviceState *flash; ECCState ecc; - DisplayState *ds; + QemuConsole *con; MemoryRegion vram; uint16_t *vram_ptr; uint32_t scr_width, scr_height; /* in pixels */ @@ -433,7 +433,9 @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value) static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update) { - switch (ds_get_bits_per_pixel(s->ds)) { + DisplaySurface *surface = qemu_console_surface(s->con); + + switch (surface_bits_per_pixel(surface)) { case 8: tc6393xb_draw_graphic8(s); break; @@ -450,34 +452,37 @@ static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update) tc6393xb_draw_graphic32(s); break; default: - printf("tc6393xb: unknown depth %d\n", ds_get_bits_per_pixel(s->ds)); + printf("tc6393xb: unknown depth %d\n", + surface_bits_per_pixel(surface)); return; } - dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height); + dpy_gfx_update(s->con, 0, 0, s->scr_width, s->scr_height); } static void tc6393xb_draw_blank(TC6393xbState *s, int full_update) { + DisplaySurface *surface = qemu_console_surface(s->con); int i, w; uint8_t *d; if (!full_update) return; - w = s->scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); - d = ds_get_data(s->ds); + w = s->scr_width * surface_bytes_per_pixel(surface); + d = surface_data(surface); for(i = 0; i < s->scr_height; i++) { memset(d, 0, w); - d += ds_get_linesize(s->ds); + d += surface_stride(surface); } - dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height); + dpy_gfx_update(s->con, 0, 0, s->scr_width, s->scr_height); } static void tc6393xb_update_display(void *opaque) { TC6393xbState *s = opaque; + DisplaySurface *surface = qemu_console_surface(s->con); int full_update; if (s->scr_width == 0 || s->scr_height == 0) @@ -488,8 +493,9 @@ static void tc6393xb_update_display(void *opaque) s->blanked = s->blank; full_update = 1; } - if (s->scr_width != ds_get_width(s->ds) || s->scr_height != ds_get_height(s->ds)) { - qemu_console_resize(s->ds, s->scr_width, s->scr_height); + if (s->scr_width != surface_width(surface) || + s->scr_height != surface_height(surface)) { + qemu_console_resize(s->con, s->scr_width, s->scr_height); full_update = 1; } if (s->blanked) @@ -577,7 +583,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->ds = graphic_console_init(tc6393xb_update_display, + s->con = graphic_console_init(tc6393xb_update_display, NULL, /* invalidate */ NULL, /* screen_dump */ NULL, /* text_update */ diff --git a/hw/tc6393xb_template.h b/hw/tc6393xb_template.h index 4cbbad5dae..154aafd400 100644 --- a/hw/tc6393xb_template.h +++ b/hw/tc6393xb_template.h @@ -37,17 +37,18 @@ static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s) { + DisplaySurface *surface = qemu_console_surface(s->con); int i; uint16_t *data_buffer; uint8_t *data_display; data_buffer = s->vram_ptr; - data_display = ds_get_data(s->ds); + data_display = surface_data(surface); for(i = 0; i < s->scr_height; i++) { #if (BITS == 16) memcpy(data_display, data_buffer, s->scr_width * 2); data_buffer += s->scr_width; - data_display += ds_get_linesize(s->ds); + data_display += surface_stride(surface); #else int j; for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) { diff --git a/hw/tcx.c b/hw/tcx.c index 896407d865..f1edffd877 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -38,7 +38,7 @@ typedef struct TCXState { SysBusDevice busdev; hwaddr addr; - DisplayState *ds; + QemuConsole *con; uint8_t *vram; uint32_t *vram24, *cplane; MemoryRegion vram_mem; @@ -75,9 +75,11 @@ static void tcx24_set_dirty(TCXState *s) static void update_palette_entries(TCXState *s, int start, int end) { + DisplaySurface *surface = qemu_console_surface(s->con); int i; - for(i = start; i < end; i++) { - switch(ds_get_bits_per_pixel(s->ds)) { + + for (i = start; i < end; i++) { + switch (surface_bits_per_pixel(surface)) { default: case 8: s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]); @@ -89,10 +91,11 @@ static void update_palette_entries(TCXState *s, int start, int end) s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]); break; case 32: - if (is_surface_bgr(s->ds->surface)) + if (is_surface_bgr(surface)) { s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]); - else + } else { s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]); + } break; } } @@ -151,12 +154,13 @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d, const uint32_t *cplane, const uint32_t *s24) { + DisplaySurface *surface = qemu_console_surface(s1->con); int x, bgr, r, g, b; uint8_t val, *p8; uint32_t *p = (uint32_t *)d; uint32_t dval; - bgr = is_surface_bgr(s1->ds->surface); + bgr = is_surface_bgr(surface); for(x = 0; x < width; x++, s++, s24++) { if ((be32_to_cpu(*cplane++) & 0xff000000) == 0x03000000) { // 24-bit direct, BGR order @@ -213,23 +217,26 @@ static inline void reset_dirty(TCXState *ts, ram_addr_t page_min, static void tcx_update_display(void *opaque) { TCXState *ts = opaque; + DisplaySurface *surface = qemu_console_surface(ts->con); ram_addr_t page, page_min, page_max; int y, y_start, dd, ds; uint8_t *d, *s; void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width); - if (ds_get_bits_per_pixel(ts->ds) == 0) + if (surface_bits_per_pixel(surface) == 0) { return; + } + page = 0; y_start = -1; page_min = -1; page_max = 0; - d = ds_get_data(ts->ds); + d = surface_data(surface); s = ts->vram; - dd = ds_get_linesize(ts->ds); + dd = surface_stride(surface); ds = 1024; - switch (ds_get_bits_per_pixel(ts->ds)) { + switch (surface_bits_per_pixel(surface)) { case 32: f = tcx_draw_line32; break; @@ -269,7 +276,7 @@ static void tcx_update_display(void *opaque) } else { if (y_start >= 0) { /* flush to display */ - dpy_gfx_update(ts->ds, 0, y_start, + dpy_gfx_update(ts->con, 0, y_start, ts->width, y - y_start); y_start = -1; } @@ -279,7 +286,7 @@ static void tcx_update_display(void *opaque) } if (y_start >= 0) { /* flush to display */ - dpy_gfx_update(ts->ds, 0, y_start, + dpy_gfx_update(ts->con, 0, y_start, ts->width, y - y_start); } /* reset modified pages */ @@ -293,24 +300,27 @@ static void tcx_update_display(void *opaque) static void tcx24_update_display(void *opaque) { TCXState *ts = opaque; + DisplaySurface *surface = qemu_console_surface(ts->con); ram_addr_t page, page_min, page_max, cpage, page24; int y, y_start, dd, ds; uint8_t *d, *s; uint32_t *cptr, *s24; - if (ds_get_bits_per_pixel(ts->ds) != 32) + if (surface_bits_per_pixel(surface) != 32) { return; + } + page = 0; page24 = ts->vram24_offset; cpage = ts->cplane_offset; y_start = -1; page_min = -1; page_max = 0; - d = ds_get_data(ts->ds); + d = surface_data(surface); s = ts->vram; s24 = ts->vram24; cptr = ts->cplane; - dd = ds_get_linesize(ts->ds); + dd = surface_stride(surface); ds = 1024; for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE, @@ -345,7 +355,7 @@ static void tcx24_update_display(void *opaque) } else { if (y_start >= 0) { /* flush to display */ - dpy_gfx_update(ts->ds, 0, y_start, + dpy_gfx_update(ts->con, 0, y_start, ts->width, y - y_start); y_start = -1; } @@ -357,7 +367,7 @@ static void tcx24_update_display(void *opaque) } if (y_start >= 0) { /* flush to display */ - dpy_gfx_update(ts->ds, 0, y_start, + dpy_gfx_update(ts->con, 0, y_start, ts->width, y - y_start); } /* reset modified pages */ @@ -371,7 +381,7 @@ static void tcx_invalidate_display(void *opaque) TCXState *s = opaque; tcx_set_dirty(s); - qemu_console_resize(s->ds, s->width, s->height); + qemu_console_resize(s->con, s->width, s->height); } static void tcx24_invalidate_display(void *opaque) @@ -380,7 +390,7 @@ static void tcx24_invalidate_display(void *opaque) tcx_set_dirty(s); tcx24_set_dirty(s); - qemu_console_resize(s->ds, s->width, s->height); + qemu_console_resize(s->con, s->width, s->height); } static int vmstate_tcx_post_load(void *opaque, int version_id) @@ -558,21 +568,21 @@ static int tcx_init1(SysBusDevice *dev) &s->vram_mem, vram_offset, size); sysbus_init_mmio(dev, &s->vram_cplane); - s->ds = graphic_console_init(tcx24_update_display, - tcx24_invalidate_display, - tcx24_screen_dump, NULL, s); + s->con = graphic_console_init(tcx24_update_display, + tcx24_invalidate_display, + tcx24_screen_dump, NULL, 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->ds = graphic_console_init(tcx_update_display, - tcx_invalidate_display, - tcx_screen_dump, NULL, s); + s->con = graphic_console_init(tcx_update_display, + tcx_invalidate_display, + tcx_screen_dump, NULL, s); } - qemu_console_resize(s->ds, s->width, s->height); + qemu_console_resize(s->con, s->width, s->height); return 0; } diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c index 4aa62bf35e..02356d4d58 100644 --- a/hw/vga-isa-mm.c +++ b/hw/vga-isa-mm.c @@ -135,8 +135,9 @@ 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.ds = 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.update, s->vga.invalidate, + s->vga.screen_dump, s->vga.text_update, + s); vga_init_vbe(&s->vga, address_space); return 0; diff --git a/hw/vga-isa.c b/hw/vga-isa.c index ffad5226fd..9e293217d0 100644 --- a/hw/vga-isa.c +++ b/hw/vga-isa.c @@ -62,8 +62,8 @@ static int vga_initfn(ISADevice *dev) isa_mem_base + 0x000a0000, vga_io_memory, 1); memory_region_set_coalescing(vga_io_memory); - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); + s->con = graphic_console_init(s->update, s->invalidate, + s->screen_dump, s->text_update, s); vga_init_vbe(s, isa_address_space(dev)); /* ROM BIOS */ diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 18018ff1c3..05fa9bcb64 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -150,8 +150,8 @@ 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->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); + s->con = graphic_console_init(s->update, s->invalidate, + s->screen_dump, 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/vga.c b/hw/vga.c index 13d5066e06..59bfb220f5 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1174,9 +1174,9 @@ static int update_basic_params(VGACommonState *s) #define NB_DEPTHS 7 -static inline int get_depth_index(DisplayState *s) +static inline int get_depth_index(DisplaySurface *s) { - switch(ds_get_bits_per_pixel(s)) { + switch (surface_bits_per_pixel(s)) { default: case 8: return 0; @@ -1185,10 +1185,11 @@ static inline int get_depth_index(DisplayState *s) case 16: return 2; case 32: - if (is_surface_bgr(s->surface)) + if (is_surface_bgr(s)) { return 4; - else + } else { return 3; + } } } @@ -1294,6 +1295,7 @@ static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = { */ static void vga_draw_text(VGACommonState *s, int full_update) { + DisplaySurface *surface = qemu_console_surface(s->con); int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr; int cx_min, cx_max, linesize, x_incr, line, line1; uint32_t offset, fgcol, bgcol, v, cursor_offset; @@ -1345,8 +1347,9 @@ static void vga_draw_text(VGACommonState *s, int full_update) cw != s->last_cw || cheight != s->last_ch || s->last_depth) { s->last_scr_width = width * cw; s->last_scr_height = height * cheight; - qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height); - dpy_text_resize(s->ds, width, height); + qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height); + surface = qemu_console_surface(s->con); + dpy_text_resize(s->con, width, height); s->last_depth = 0; s->last_width = width; s->last_height = height; @@ -1355,10 +1358,10 @@ static void vga_draw_text(VGACommonState *s, int full_update) full_update = 1; } s->rgb_to_pixel = - rgb_to_pixel_dup_table[get_depth_index(s->ds)]; + rgb_to_pixel_dup_table[get_depth_index(surface)]; full_update |= update_palette16(s); palette = s->last_palette; - x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); + x_incr = cw * surface_bytes_per_pixel(surface); if (full_update) { s->full_update_text = 1; @@ -1389,15 +1392,15 @@ static void vga_draw_text(VGACommonState *s, int full_update) s->cursor_visible_phase = !s->cursor_visible_phase; } - depth_index = get_depth_index(s->ds); + depth_index = get_depth_index(surface); if (cw == 16) vga_draw_glyph8 = vga_draw_glyph16_table[depth_index]; else vga_draw_glyph8 = vga_draw_glyph8_table[depth_index]; vga_draw_glyph9 = vga_draw_glyph9_table[depth_index]; - dest = ds_get_data(s->ds); - linesize = ds_get_linesize(s->ds); + dest = surface_data(surface); + linesize = surface_stride(surface); ch_attr_ptr = s->last_ch_attr; line = 0; offset = s->start_addr * 4; @@ -1465,7 +1468,7 @@ static void vga_draw_text(VGACommonState *s, int full_update) ch_attr_ptr++; } if (cx_max != -1) { - dpy_gfx_update(s->ds, cx_min * cw, cy * cheight, + dpy_gfx_update(s->con, cx_min * cw, cy * cheight, (cx_max - cx_min + 1) * cw, cheight); } dest += linesize * cheight; @@ -1636,6 +1639,7 @@ void vga_dirty_log_stop(VGACommonState *s) */ static void vga_draw_graphic(VGACommonState *s, int full_update) { + DisplaySurface *surface = qemu_console_surface(s->con); int y1, y, update, linesize, y_start, double_scan, mask, depth; int width, height, shift_control, line_offset, bwidth, bits; ram_addr_t page0, page1, page_min, page_max; @@ -1691,13 +1695,13 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) height != s->last_height || s->last_depth != depth) { if (depth == 32 || (depth == 16 && !byteswap)) { - DisplaySurface *surface; surface = qemu_create_displaysurface_from(disp_width, height, depth, s->line_offset, s->vram_ptr + (s->start_addr * 4), byteswap); - dpy_gfx_replace_surface(s->ds, surface); + dpy_gfx_replace_surface(s->con, surface); } else { - qemu_console_resize(s->ds, disp_width, height); + qemu_console_resize(s->con, disp_width, height); + surface = qemu_console_surface(s->con); } s->last_scr_width = disp_width; s->last_scr_height = height; @@ -1706,18 +1710,18 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) s->last_line_offset = s->line_offset; s->last_depth = depth; full_update = 1; - } else if (is_buffer_shared(s->ds->surface) && - (full_update || ds_get_data(s->ds) != s->vram_ptr + } else if (is_buffer_shared(surface) && + (full_update || surface_data(surface) != s->vram_ptr + (s->start_addr * 4))) { DisplaySurface *surface; surface = qemu_create_displaysurface_from(disp_width, height, depth, s->line_offset, s->vram_ptr + (s->start_addr * 4), byteswap); - dpy_gfx_replace_surface(s->ds, surface); + dpy_gfx_replace_surface(s->con, surface); } s->rgb_to_pixel = - rgb_to_pixel_dup_table[get_depth_index(s->ds)]; + rgb_to_pixel_dup_table[get_depth_index(surface)]; if (shift_control == 0) { full_update |= update_palette16(s); @@ -1766,10 +1770,12 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) break; } } - vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)]; + vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + + get_depth_index(surface)]; - if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate) + if (!is_buffer_shared(surface) && s->cursor_invalidate) { s->cursor_invalidate(s); + } line_offset = s->line_offset; #if 0 @@ -1782,8 +1788,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) y_start = -1; page_min = -1; page_max = 0; - d = ds_get_data(s->ds); - linesize = ds_get_linesize(s->ds); + d = surface_data(surface); + linesize = surface_stride(surface); y1 = 0; for(y = 0; y < height; y++) { addr = addr1; @@ -1810,7 +1816,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) page_min = page0; if (page1 > page_max) page_max = page1; - if (!(is_buffer_shared(s->ds->surface))) { + if (!(is_buffer_shared(surface))) { vga_draw_line(s, d, s->vram_ptr + addr, width); if (s->cursor_draw_line) s->cursor_draw_line(s, d, y); @@ -1818,7 +1824,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) } else { if (y_start >= 0) { /* flush to display */ - dpy_gfx_update(s->ds, 0, y_start, + dpy_gfx_update(s->con, 0, y_start, disp_width, y - y_start); y_start = -1; } @@ -1839,7 +1845,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) } if (y_start >= 0) { /* flush to display */ - dpy_gfx_update(s->ds, 0, y_start, + dpy_gfx_update(s->con, 0, y_start, disp_width, y - y_start); } /* reset modified pages */ @@ -1854,6 +1860,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) static void vga_draw_blank(VGACommonState *s, int full_update) { + DisplaySurface *surface = qemu_console_surface(s->con); int i, w, val; uint8_t *d; @@ -1863,18 +1870,19 @@ static void vga_draw_blank(VGACommonState *s, int full_update) return; s->rgb_to_pixel = - rgb_to_pixel_dup_table[get_depth_index(s->ds)]; - if (ds_get_bits_per_pixel(s->ds) == 8) + rgb_to_pixel_dup_table[get_depth_index(surface)]; + if (surface_bits_per_pixel(surface) == 8) { val = s->rgb_to_pixel(0, 0, 0); - else + } else { val = 0; - w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); - d = ds_get_data(s->ds); + } + w = s->last_scr_width * surface_bytes_per_pixel(surface); + d = surface_data(surface); for(i = 0; i < s->last_scr_height; i++) { memset(d, val, w); - d += ds_get_linesize(s->ds); + d += surface_stride(surface); } - dpy_gfx_update(s->ds, 0, 0, + dpy_gfx_update(s->con, 0, 0, s->last_scr_width, s->last_scr_height); } @@ -1885,11 +1893,12 @@ static void vga_draw_blank(VGACommonState *s, int full_update) static void vga_update_display(void *opaque) { VGACommonState *s = opaque; + DisplaySurface *surface = qemu_console_surface(s->con); int full_update, graphic_mode; qemu_flush_coalesced_mmio_buffer(); - if (ds_get_bits_per_pixel(s->ds) == 0) { + if (surface_bits_per_pixel(surface) == 0) { /* nothing to do */ } else { full_update = 0; @@ -2063,8 +2072,8 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) cw != s->last_cw || cheight != s->last_ch) { s->last_scr_width = width * cw; s->last_scr_height = height * cheight; - qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height); - dpy_text_resize(s->ds, width, height); + qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height); + dpy_text_resize(s->con, width, height); s->last_depth = 0; s->last_width = width; s->last_height = height; @@ -2089,11 +2098,11 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) { cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20); if (cursor_visible && cursor_offset < size && cursor_offset >= 0) - dpy_text_cursor(s->ds, + dpy_text_cursor(s->con, TEXTMODE_X(cursor_offset), TEXTMODE_Y(cursor_offset)); else - dpy_text_cursor(s->ds, -1, -1); + dpy_text_cursor(s->con, -1, -1); s->cursor_offset = cursor_offset; s->cursor_start = s->cr[VGA_CRTC_CURSOR_START]; s->cursor_end = s->cr[VGA_CRTC_CURSOR_END]; @@ -2106,7 +2115,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) for (i = 0; i < size; src ++, dst ++, i ++) console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src))); - dpy_text_update(s->ds, 0, 0, width, height); + dpy_text_update(s->con, 0, 0, width, height); } else { c_max = 0; @@ -2129,7 +2138,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) if (c_min <= c_max) { i = TEXTMODE_Y(c_min); - dpy_text_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1); + dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1); } } @@ -2154,8 +2163,8 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) /* Display a message */ s->last_width = 60; s->last_height = height = 3; - dpy_text_cursor(s->ds, -1, -1); - dpy_text_resize(s->ds, s->last_width, height); + dpy_text_cursor(s->con, -1, -1); + dpy_text_resize(s->con, s->last_width, height); for (dst = chardata, i = 0; i < s->last_width * height; i ++) console_write_ch(dst ++, ' '); @@ -2166,7 +2175,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) for (i = 0; i < size; i ++) console_write_ch(dst ++, 0x00200100 | msg_buffer[i]); - dpy_text_update(s->ds, 0, 0, s->last_width, height); + dpy_text_update(s->con, 0, 0, s->last_width, height); } static uint64_t vga_mem_read(void *opaque, hwaddr addr, @@ -2438,10 +2447,11 @@ 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, s->ds->surface, errp); + ppm_save(filename, surface, errp); } diff --git a/hw/vga_int.h b/hw/vga_int.h index 8d496ea9bf..260f7d6948 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -132,7 +132,7 @@ typedef struct VGACommonState { uint32_t vbe_bank_mask; int vbe_mapped; /* display refresh support */ - DisplayState *ds; + QemuConsole *con; uint32_t font_offsets[2]; int graphic_mode; uint8_t shift_control; diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index db2f187e56..5b9ce8f96b 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -57,9 +57,6 @@ struct vmsvga_state_s { int new_height; uint32_t guest; uint32_t svgaid; - uint32_t wred; - uint32_t wgreen; - uint32_t wblue; int syncing; MemoryRegion fifo_ram; @@ -289,6 +286,7 @@ enum { static inline void vmsvga_update_rect(struct vmsvga_state_s *s, int x, int y, int w, int h) { + DisplaySurface *surface = qemu_console_surface(s->vga.con); int line; int bypl; int width; @@ -305,11 +303,11 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s, fprintf(stderr, "%s: update w was < 0 (%d)\n", __func__, w); w = 0; } - if (x + w > ds_get_width(s->vga.ds)) { + if (x + w > surface_width(surface)) { fprintf(stderr, "%s: update width too large x: %d, w: %d\n", __func__, x, w); - x = MIN(x, ds_get_width(s->vga.ds)); - w = ds_get_width(s->vga.ds) - x; + x = MIN(x, surface_width(surface)); + w = surface_width(surface) - x; } if (y < 0) { @@ -321,23 +319,23 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s, fprintf(stderr, "%s: update h was < 0 (%d)\n", __func__, h); h = 0; } - if (y + h > ds_get_height(s->vga.ds)) { + if (y + h > surface_height(surface)) { fprintf(stderr, "%s: update height too large y: %d, h: %d\n", __func__, y, h); - y = MIN(y, ds_get_height(s->vga.ds)); - h = ds_get_height(s->vga.ds) - y; + y = MIN(y, surface_height(surface)); + h = surface_height(surface) - y; } - bypl = ds_get_linesize(s->vga.ds); - width = ds_get_bytes_per_pixel(s->vga.ds) * w; - start = ds_get_bytes_per_pixel(s->vga.ds) * x + bypl * y; + bypl = surface_stride(surface); + width = surface_bytes_per_pixel(surface) * w; + start = surface_bytes_per_pixel(surface) * x + bypl * y; src = s->vga.vram_ptr + start; - dst = ds_get_data(s->vga.ds) + start; + dst = surface_data(surface) + start; for (line = h; line > 0; line--, src += bypl, dst += bypl) { memcpy(dst, src, width); } - dpy_gfx_update(s->vga.ds, x, y, w, h); + dpy_gfx_update(s->vga.con, x, y, w, h); } static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s, @@ -373,9 +371,10 @@ static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s) static inline void vmsvga_copy_rect(struct vmsvga_state_s *s, int x0, int y0, int x1, int y1, int w, int h) { + DisplaySurface *surface = qemu_console_surface(s->vga.con); uint8_t *vram = s->vga.vram_ptr; - int bypl = ds_get_linesize(s->vga.ds); - int bypp = ds_get_bytes_per_pixel(s->vga.ds); + int bypl = surface_stride(surface); + int bypp = surface_bytes_per_pixel(surface); int width = bypp * w; int line = h; uint8_t *ptr[2]; @@ -402,8 +401,9 @@ static inline void vmsvga_copy_rect(struct vmsvga_state_s *s, static inline void vmsvga_fill_rect(struct vmsvga_state_s *s, uint32_t c, int x, int y, int w, int h) { - int bypl = ds_get_linesize(s->vga.ds); - int width = ds_get_bytes_per_pixel(s->vga.ds) * w; + DisplaySurface *surface = qemu_console_surface(s->vga.con); + int bypl = surface_stride(surface); + int width = surface_bytes_per_pixel(surface) * w; int line = h; int column; uint8_t *fst; @@ -416,14 +416,14 @@ static inline void vmsvga_fill_rect(struct vmsvga_state_s *s, col[2] = c >> 16; col[3] = c >> 24; - fst = s->vga.vram_ptr + ds_get_bytes_per_pixel(s->vga.ds) * x + bypl * y; + fst = s->vga.vram_ptr + surface_bytes_per_pixel(surface) * x + bypl * y; if (line--) { dst = fst; src = col; for (column = width; column > 0; column--) { *(dst++) = *(src++); - if (src - col == ds_get_bytes_per_pixel(s->vga.ds)) { + if (src - col == surface_bytes_per_pixel(surface)) { src = col; } } @@ -490,7 +490,7 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s, qc = cursor_builtin_left_ptr(); } - dpy_cursor_define(s->vga.ds, qc); + dpy_cursor_define(s->vga.con, qc); cursor_put(qc); } #endif @@ -720,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); switch (s->index) { case SVGA_REG_ID: @@ -729,10 +730,10 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) return s->enable; case SVGA_REG_WIDTH: - return ds_get_width(s->vga.ds); + return surface_width(surface); case SVGA_REG_HEIGHT: - return ds_get_height(s->vga.ds); + return surface_height(surface); case SVGA_REG_MAX_WIDTH: return SVGA_MAX_WIDTH; @@ -750,13 +751,13 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) return 0x0; case SVGA_REG_RED_MASK: - return s->wred; + return surface->pf.rmask; case SVGA_REG_GREEN_MASK: - return s->wgreen; + return surface->pf.gmask; case SVGA_REG_BLUE_MASK: - return s->wblue; + return surface->pf.bmask; case SVGA_REG_BYTES_PER_LINE: return s->bypp * s->new_width; @@ -785,7 +786,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) caps |= SVGA_CAP_RECT_FILL; #endif #ifdef HW_MOUSE_ACCEL - if (dpy_cursor_define_supported(s->vga.ds)) { + if (dpy_cursor_define_supported(s->vga.con)) { caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 | SVGA_CAP_CURSOR_BYPASS; } @@ -947,7 +948,7 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value) s->cursor.on &= (value != SVGA_CURSOR_ON_HIDE); #ifdef HW_MOUSE_ACCEL if (value <= SVGA_CURSOR_ON_SHOW) { - dpy_mouse_set(s->vga.ds, s->cursor.x, s->cursor.y, s->cursor.on); + dpy_mouse_set(s->vga.con, s->cursor.x, s->cursor.y, s->cursor.on); } #endif break; @@ -982,9 +983,11 @@ static void vmsvga_bios_write(void *opaque, uint32_t address, uint32_t data) static inline void vmsvga_check_size(struct vmsvga_state_s *s) { - if (s->new_width != ds_get_width(s->vga.ds) || - s->new_height != ds_get_height(s->vga.ds)) { - qemu_console_resize(s->vga.ds, s->new_width, s->new_height); + 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->invalidated = 1; } } @@ -992,6 +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); bool dirty = false; if (!s->enable) { @@ -1011,19 +1015,19 @@ static void vmsvga_update_display(void *opaque) if (memory_region_is_logging(&s->vga.vram)) { vga_sync_dirty_bitmap(&s->vga); dirty = memory_region_get_dirty(&s->vga.vram, 0, - ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds), + surface_stride(surface) * surface_height(surface), DIRTY_MEMORY_VGA); } if (s->invalidated || dirty) { s->invalidated = 0; - memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr, - ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds)); - dpy_gfx_update(s->vga.ds, 0, 0, - ds_get_width(s->vga.ds), ds_get_height(s->vga.ds)); + 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)); } if (dirty) { memory_region_reset_dirty(&s->vga.vram, 0, - ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds), + surface_stride(surface) * surface_height(surface), DIRTY_MEMORY_VGA); } } @@ -1063,17 +1067,19 @@ 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 (ds_get_bits_per_pixel(s->vga.ds) == 32) { + if (surface_bits_per_pixel(surface) == 32) { DisplaySurface *ds = qemu_create_displaysurface_from( - ds_get_width(s->vga.ds), - ds_get_height(s->vga.ds), + surface_width(surface), + surface_height(surface), 32, - ds_get_linesize(s->vga.ds), + surface_stride(surface), s->vga.vram_ptr, false); ppm_save(filename, ds, errp); g_free(ds); @@ -1143,14 +1149,16 @@ 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); - s->vga.ds = graphic_console_init(vmsvga_update_display, - vmsvga_invalidate_display, - vmsvga_screen_dump, - vmsvga_text_update, s); - + 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->fifo_size = SVGA_FIFO_SIZE; memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size); @@ -1162,11 +1170,8 @@ static void vmsvga_init(struct vmsvga_state_s *s, 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 = ds_get_bits_per_pixel(s->vga.ds); - s->bypp = ds_get_bytes_per_pixel(s->vga.ds); - s->wred = ds_get_rmask(s->vga.ds); - s->wgreen = ds_get_gmask(s->vga.ds); - s->wblue = ds_get_bmask(s->vga.ds); + s->depth = surface_bits_per_pixel(surface); + s->bypp = surface_bytes_per_pixel(surface); } static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, unsigned size) diff --git a/hw/xenfb.c b/hw/xenfb.c index 7779097f50..7c46a2fa1e 100644 --- a/hw/xenfb.c +++ b/hw/xenfb.c @@ -54,7 +54,7 @@ struct common { struct XenDevice xendev; /* must be first */ void *page; - DisplayState *ds; + QemuConsole *con; }; struct XenInput { @@ -318,8 +318,9 @@ static void xenfb_mouse_event(void *opaque, int dx, int dy, int dz, int button_state) { struct XenInput *xenfb = opaque; - int dw = ds_get_width(xenfb->c.ds); - int dh = ds_get_height(xenfb->c.ds); + DisplaySurface *surface = qemu_console_surface(xenfb->c.con); + int dw = surface_width(surface); + int dh = surface_height(surface); int i; if (xenfb->abs_pointer_wanted) @@ -353,16 +354,9 @@ static int input_initialise(struct XenDevice *xendev) struct XenInput *in = container_of(xendev, struct XenInput, c.xendev); int rc; - if (!in->c.ds) { - char *vfb = xenstore_read_str(NULL, "device/vfb"); - if (vfb == NULL) { - /* there is no vfb, run vkbd on its own */ - in->c.ds = get_displaystate(); - } else { - g_free(vfb); - xen_be_printf(xendev, 1, "ds not set (yet)\n"); - return -1; - } + if (!in->c.con) { + xen_be_printf(xendev, 1, "ds not set (yet)\n"); + return -1; } rc = common_bind(&in->c); @@ -615,12 +609,13 @@ static int xenfb_configure_fb(struct XenFB *xenfb, size_t fb_len_lim, */ static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h) { + DisplaySurface *surface = qemu_console_surface(xenfb->c.con); int line, oops = 0; - int bpp = ds_get_bits_per_pixel(xenfb->c.ds); - int linesize = ds_get_linesize(xenfb->c.ds); - uint8_t *data = ds_get_data(xenfb->c.ds); + int bpp = surface_bits_per_pixel(surface); + int linesize = surface_stride(surface); + uint8_t *data = surface_data(surface); - if (!is_buffer_shared(xenfb->c.ds->surface)) { + if (!is_buffer_shared(surface)) { switch (xenfb->depth) { case 8: if (bpp == 16) { @@ -648,10 +643,10 @@ static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h) xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n", __FUNCTION__, xenfb->depth, bpp); - dpy_gfx_update(xenfb->c.ds, x, y, w, h); + dpy_gfx_update(xenfb->c.con, x, y, w, h); } -#ifdef XENFB_TYPE_REFRESH_PERIOD +#if 0 /* def XENFB_TYPE_REFRESH_PERIOD */ static int xenfb_queue_full(struct XenFB *xenfb) { struct xenfb_page *page = xenfb->c.page; @@ -710,7 +705,7 @@ static void xenfb_update(void *opaque) return; if (xenfb->feature_update) { -#ifdef XENFB_TYPE_REFRESH_PERIOD +#if 0 /* XENFB_TYPE_REFRESH_PERIOD */ struct DisplayChangeListener *l; int period = 99999999; int idle = 1; @@ -764,10 +759,10 @@ static void xenfb_update(void *opaque) surface = qemu_create_displaysurface(xenfb->width, xenfb->height); break; } - dpy_gfx_replace_surface(xenfb->c.ds, surface); + dpy_gfx_replace_surface(xenfb->c.con, surface); xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n", xenfb->width, xenfb->height, xenfb->depth, - is_buffer_shared(xenfb->c.ds->surface) ? " (shared)" : ""); + is_buffer_shared(surface) ? " (shared)" : ""); xenfb->up_fullscreen = 1; } @@ -1009,16 +1004,16 @@ wait_more: /* vfb */ fb = container_of(xfb, struct XenFB, c.xendev); - fb->c.ds = graphic_console_init(xenfb_update, - xenfb_invalidate, - NULL, - NULL, - fb); + fb->c.con = graphic_console_init(xenfb_update, + xenfb_invalidate, + NULL, + NULL, + fb); fb->have_console = 1; /* vkbd */ in = container_of(xin, struct XenInput, c.xendev); - in->c.ds = fb->c.ds; + in->c.con = fb->c.con; /* retry ->init() */ xen_be_check_state(xin); diff --git a/include/ui/console.h b/include/ui/console.h index c32c834871..92c31a9cfe 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -223,18 +223,18 @@ void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl); void unregister_displaychangelistener(DisplayChangeListener *dcl); -void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h); -void dpy_gfx_replace_surface(DisplayState *s, +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(struct DisplayState *s, int src_x, int src_y, +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(struct DisplayState *s, int x, int y); -void dpy_text_update(DisplayState *s, int x, int y, int w, int h); -void dpy_text_resize(DisplayState *s, int w, int h); -void dpy_mouse_set(struct DisplayState *s, int x, int y, int on); -void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor); -bool dpy_cursor_define_supported(struct DisplayState *s); +void dpy_text_cursor(QemuConsole *con, int x, int y); +void dpy_text_update(QemuConsole *con, int x, int y, int w, int h); +void dpy_text_resize(QemuConsole *con, int w, int h); +void dpy_mouse_set(QemuConsole *con, int x, int y, int on); +void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor); +bool dpy_cursor_define_supported(QemuConsole *con); static inline int surface_stride(DisplaySurface *s) { @@ -347,11 +347,11 @@ 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 *); -DisplayState *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, - void *opaque); +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, + void *opaque); void vga_hw_update(void); void vga_hw_invalidate(void); @@ -362,9 +362,11 @@ int is_fixedsize_console(void); void text_consoles_set_display(DisplayState *ds); void console_select(unsigned int index); void console_color_init(DisplayState *ds); -void qemu_console_resize(DisplayState *ds, int width, int height); -void qemu_console_copy(DisplayState *ds, int src_x, int src_y, +void qemu_console_resize(QemuConsole *con, int width, int height); +void qemu_console_copy(QemuConsole *con, int src_x, int src_y, int dst_x, int dst_y, int w, int h); +DisplaySurface *qemu_console_surface(QemuConsole *con); +DisplayState *qemu_console_displaystate(QemuConsole *console); typedef CharDriverState *(VcHandler)(ChardevVC *vc); diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index a9e1e09b42..7a20fc43ff 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -71,6 +71,7 @@ typedef struct SimpleSpiceDisplay SimpleSpiceDisplay; typedef struct SimpleSpiceUpdate SimpleSpiceUpdate; struct SimpleSpiceDisplay { + QemuConsole *con; DisplaySurface *ds; DisplayChangeListener dcl; void *buf; @@ -113,7 +114,7 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd); void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd); void qemu_spice_vm_change_state_handler(void *opaque, int running, RunState state); -void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds); +void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd); void qemu_spice_display_update(SimpleSpiceDisplay *ssd, int x, int y, int w, int h); diff --git a/ui/console.c b/ui/console.c index d690e1c58f..d5ec2715d3 100644 --- a/ui/console.c +++ b/ui/console.c @@ -664,7 +664,7 @@ static void console_refresh(QemuConsole *s) } } console_show_cursor(s, 1); - dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds)); + dpy_gfx_update(s, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds)); } } @@ -1101,10 +1101,10 @@ void console_select(unsigned int index) if (ds->have_gfx) { DisplaySurface *surface; surface = qemu_create_displaysurface(s->g_width, s->g_height); - dpy_gfx_replace_surface(ds, surface); + dpy_gfx_replace_surface(s, surface); } if (ds->have_text) { - dpy_text_resize(ds, s->width, s->height); + dpy_text_resize(s, s->width, s->height); } if (s->cursor_timer) { qemu_mod_timer(s->cursor_timer, @@ -1129,7 +1129,7 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len) } console_show_cursor(s, 1); if (s->ds->have_gfx && s->update_x0 < s->update_x1) { - dpy_gfx_update(s->ds, s->update_x0, s->update_y0, + dpy_gfx_update(s, s->update_x0, s->update_y0, s->update_x1 - s->update_x0, s->update_y1 - s->update_y0); } @@ -1239,7 +1239,7 @@ static void text_console_update(void *opaque, console_ch_t *chardata) (s->cells[src].t_attrib.fgcol << 12) | (s->cells[src].t_attrib.bgcol << 8) | (s->cells[src].t_attrib.bold << 21)); - dpy_text_update(s->ds, s->text_x[0], s->text_y[0], + dpy_text_update(s, s->text_x[0], s->text_y[0], s->text_x[1] - s->text_x[0], i - s->text_y[0]); s->text_x[0] = s->width; s->text_y[0] = s->height; @@ -1247,23 +1247,11 @@ static void text_console_update(void *opaque, console_ch_t *chardata) s->text_y[1] = 0; } if (s->cursor_invalidate) { - dpy_text_cursor(s->ds, s->x, s->y); + dpy_text_cursor(s, s->x, s->y); s->cursor_invalidate = 0; } } -static QemuConsole *get_graphic_console(DisplayState *ds) -{ - int i; - QemuConsole *s; - for (i = 0; i < nb_consoles; i++) { - s = consoles[i]; - if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds) - return s; - } - return NULL; -} - static QemuConsole *new_console(DisplayState *ds, console_type_t console_type) { QemuConsole *s; @@ -1385,8 +1373,9 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl) gui_setup_refresh(ds); } -void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h) +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); @@ -1405,9 +1394,10 @@ void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h) } } -void dpy_gfx_replace_surface(DisplayState *s, +void dpy_gfx_replace_surface(QemuConsole *con, DisplaySurface *surface) { + DisplayState *s = con->ds; DisplaySurface *old_surface = s->surface; struct DisplayChangeListener *dcl; @@ -1430,9 +1420,10 @@ void dpy_refresh(DisplayState *s) } } -void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, - int dst_x, int dst_y, int w, int h) +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; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_gfx_copy) { @@ -1443,8 +1434,9 @@ void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, } } -void dpy_text_cursor(struct DisplayState *s, int x, int y) +void dpy_text_cursor(QemuConsole *con, int x, int y) { + DisplayState *s = con->ds; struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_text_cursor) { @@ -1453,8 +1445,9 @@ void dpy_text_cursor(struct DisplayState *s, int x, int y) } } -void dpy_text_update(DisplayState *s, int x, int y, int w, int h) +void dpy_text_update(QemuConsole *con, int x, int y, int w, int h) { + DisplayState *s = con->ds; struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_text_update) { @@ -1463,8 +1456,9 @@ void dpy_text_update(DisplayState *s, int x, int y, int w, int h) } } -void dpy_text_resize(DisplayState *s, int w, int h) +void dpy_text_resize(QemuConsole *con, int w, int h) { + DisplayState *s = con->ds; struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_text_resize) { @@ -1473,8 +1467,9 @@ void dpy_text_resize(DisplayState *s, int w, int h) } } -void dpy_mouse_set(struct DisplayState *s, int x, int y, int on) +void dpy_mouse_set(QemuConsole *con, int x, int y, int on) { + DisplayState *s = con->ds; struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_mouse_set) { @@ -1483,8 +1478,9 @@ void dpy_mouse_set(struct DisplayState *s, int x, int y, int on) } } -void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor) +void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor) { + DisplayState *s = con->ds; struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_cursor_define) { @@ -1493,8 +1489,9 @@ void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor) } } -bool dpy_cursor_define_supported(struct DisplayState *s) +bool dpy_cursor_define_supported(QemuConsole *con) { + DisplayState *s = con->ds; struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { if (dcl->ops->dpy_cursor_define) { @@ -1507,7 +1504,6 @@ bool dpy_cursor_define_supported(struct DisplayState *s) static void dumb_display_init(void) { DisplayState *ds = g_malloc0(sizeof(DisplayState)); - DisplaySurface *surface; int width = 640; int height = 480; @@ -1515,8 +1511,7 @@ static void dumb_display_init(void) width = active_console->g_width; height = active_console->g_height; } - surface = qemu_create_displaysurface(width, height); - dpy_gfx_replace_surface(ds, surface); + ds->surface = qemu_create_displaysurface(width, height); register_displaystate(ds); } @@ -1542,15 +1537,14 @@ DisplayState *get_displaystate(void) return display_state; } -DisplayState *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, - void *opaque) +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, + void *opaque) { QemuConsole *s; DisplayState *ds; - DisplaySurface *surface; ds = (DisplayState *) g_malloc0(sizeof(DisplayState)); s = new_console(ds, GRAPHIC_CONSOLE); @@ -1560,11 +1554,10 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update, s->hw_text_update = text_update; s->hw = opaque; - surface = qemu_create_displaysurface(640, 480); - dpy_gfx_replace_surface(ds, surface); + ds->surface = qemu_create_displaysurface(640, 480); register_displaystate(ds); - return ds; + return s; } int is_graphic_console(void) @@ -1730,28 +1723,35 @@ void text_consoles_set_display(DisplayState *ds) } } -void qemu_console_resize(DisplayState *ds, int width, int height) +void qemu_console_resize(QemuConsole *s, int width, int height) { - QemuConsole *s = get_graphic_console(ds); - if (!s) return; - s->g_width = width; s->g_height = height; if (is_graphic_console()) { DisplaySurface *surface; surface = qemu_create_displaysurface(width, height); - dpy_gfx_replace_surface(ds, surface); + dpy_gfx_replace_surface(s, surface); } } -void qemu_console_copy(DisplayState *ds, int src_x, int src_y, +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(ds, src_x, src_y, dst_x, dst_y, w, h); + dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h); } } +DisplaySurface *qemu_console_surface(QemuConsole *console) +{ + return console->ds->surface; +} + +DisplayState *qemu_console_displaystate(QemuConsole *console) +{ + return console->ds; +} + PixelFormat qemu_different_endianness_pixelformat(int bpp) { PixelFormat pf; diff --git a/ui/spice-display.c b/ui/spice-display.c index 2127b3f37e..eaab19d9bd 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -334,7 +334,7 @@ void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) qemu_spice_destroy_primary_surface(ssd, 0, QXL_SYNC); } -void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds) +void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd) { qemu_mutex_init(&ssd->lock); QTAILQ_INIT(&ssd->updates); @@ -398,12 +398,14 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd, void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd) { if (ssd->cursor) { - dpy_cursor_define(ssd->dcl.ds, ssd->cursor); + assert(ssd->con); + dpy_cursor_define(ssd->con, ssd->cursor); cursor_put(ssd->cursor); ssd->cursor = NULL; } if (ssd->mouse_x != -1 && ssd->mouse_y != -1) { - dpy_mouse_set(ssd->dcl.ds, ssd->mouse_x, ssd->mouse_y, 1); + assert(ssd->con); + dpy_mouse_set(ssd->con, ssd->mouse_x, ssd->mouse_y, 1); ssd->mouse_x = -1; ssd->mouse_y = -1; } @@ -613,7 +615,7 @@ void qemu_spice_display_init(DisplayState *ds) { SimpleSpiceDisplay *ssd = g_new0(SimpleSpiceDisplay, 1); - qemu_spice_display_init_common(ssd, ds); + qemu_spice_display_init_common(ssd); ssd->qxl.base.sif = &dpy_interface.base; qemu_spice_add_interface(&ssd->qxl.base); From cf6f05481affb600da22dba3c0bc2564e918e8f1 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 6 Mar 2013 09:50:51 +0100 Subject: [PATCH 36/37] console: zap color_table qemu_create_surface hands out 32bpp surfaces. So we can just use color_table_rgb directly. Signed-off-by: Gerd Hoffmann --- ui/console.c | 83 ++++------------------------------------------------ 1 file changed, 6 insertions(+), 77 deletions(-) diff --git a/ui/console.c b/ui/console.c index d5ec2715d3..27b165975b 100644 --- a/ui/console.c +++ b/ui/console.c @@ -208,42 +208,6 @@ void vga_hw_text_update(console_ch_t *chardata) active_console->hw_text_update(active_console->hw, chardata); } -/* convert a RGBA color to a color index usable in graphic primitives */ -static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba) -{ - unsigned int r, g, b, color; - - switch(ds_get_bits_per_pixel(ds)) { -#if 0 - case 8: - r = (rgba >> 16) & 0xff; - g = (rgba >> 8) & 0xff; - b = (rgba) & 0xff; - color = (rgb_to_index[r] * 6 * 6) + - (rgb_to_index[g] * 6) + - (rgb_to_index[b]); - break; -#endif - case 15: - r = (rgba >> 16) & 0xff; - g = (rgba >> 8) & 0xff; - b = (rgba) & 0xff; - color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); - break; - case 16: - r = (rgba >> 16) & 0xff; - g = (rgba >> 8) & 0xff; - b = (rgba) & 0xff; - color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); - break; - case 32: - default: - color = rgba; - break; - } - return color; -} - static void vga_fill_rect (DisplayState *ds, int posx, int posy, int width, int height, uint32_t color) { @@ -358,8 +322,6 @@ static const uint32_t dmask4[4] = { PAT(0xffffffff), }; -static uint32_t color_table[2][8]; - #ifndef CONFIG_CURSES enum color_names { COLOR_BLACK = 0, @@ -396,23 +358,6 @@ static const uint32_t color_table_rgb[2][8] = { } }; -static inline unsigned int col_expand(DisplayState *ds, unsigned int col) -{ - switch(ds_get_bits_per_pixel(ds)) { - case 8: - col |= col << 8; - col |= col << 16; - break; - case 15: - case 16: - col |= col << 16; - break; - default: - break; - } - - return col; -} #ifdef DEBUG_CONSOLE static void console_print_text_attributes(TextAttributes *t_attrib, char ch) { @@ -461,11 +406,11 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, #endif if (t_attrib->invers) { - bgcol = color_table[t_attrib->bold][t_attrib->fgcol]; - fgcol = color_table[t_attrib->bold][t_attrib->bgcol]; + bgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol]; + fgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol]; } else { - fgcol = color_table[t_attrib->bold][t_attrib->fgcol]; - bgcol = color_table[t_attrib->bold][t_attrib->bgcol]; + fgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol]; + bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol]; } bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; @@ -650,7 +595,7 @@ static void console_refresh(QemuConsole *s) if (s->ds->have_gfx) { vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds), - color_table[0][COLOR_BLACK]); + color_table_rgb[0][COLOR_BLACK]); y1 = s->y_displayed; for (y = 0; y < s->height; y++) { c = s->cells + y1 * s->width; @@ -740,7 +685,7 @@ static void console_put_lf(QemuConsole *s) (s->height - 1) * FONT_HEIGHT); vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT, s->width * FONT_WIDTH, FONT_HEIGHT, - color_table[0][s->t_attrib_default.bgcol]); + color_table_rgb[0][s->t_attrib_default.bgcol]); s->update_x0 = 0; s->update_y0 = 0; s->update_x1 = s->width * FONT_WIDTH; @@ -1570,17 +1515,6 @@ int is_fixedsize_console(void) return active_console && active_console->console_type != TEXT_CONSOLE; } -void console_color_init(DisplayState *ds) -{ - int i, j; - for (j = 0; j < 2; j++) { - for (i = 0; i < 8; i++) { - color_table[j][i] = col_expand(ds, - vga_get_color(ds, color_table_rgb[j][i])); - } - } -} - static void text_console_set_echo(CharDriverState *chr, bool echo) { QemuConsole *s = chr->opaque; @@ -1601,7 +1535,6 @@ static void text_console_update_cursor(void *opaque) static void text_console_do_init(CharDriverState *chr, DisplayState *ds) { QemuConsole *s; - static int color_inited; s = chr->opaque; @@ -1612,10 +1545,6 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds) s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s); s->ds = ds; - if (!color_inited) { - color_inited = 1; - console_color_init(s->ds); - } s->y_displayed = 0; s->y_base = 0; s->total_height = DEFAULT_BACKSCROLL; From 1562e53112fd1082c656a06d953a7447ab17e6e1 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 6 Mar 2013 13:40:47 +0100 Subject: [PATCH 37/37] console: remove ds_get_* helper functions Switch the few remaining ds_get_* uses in console.c over to the new surface_* accessors. While doing so tripped over a few leftovers from commit a93a4a226a2afba147ba5df688b85d844f537c68 (code using depth == 0 as indicator for textmode rendering). Fixed them up. Finally dropped ds_get_* helper helpers. Signed-off-by: Gerd Hoffmann --- include/ui/console.h | 60 ------------------ ui/console.c | 142 ++++++++++++++++++++++++------------------- 2 files changed, 79 insertions(+), 123 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 92c31a9cfe..a234c72d2e 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -268,66 +268,6 @@ static inline int surface_bytes_per_pixel(DisplaySurface *s) return (bits + 7) / 8; } -static inline int ds_get_linesize(DisplayState *ds) -{ - return surface_stride(ds->surface); -} - -static inline uint8_t* ds_get_data(DisplayState *ds) -{ - return surface_data(ds->surface); -} - -static inline int ds_get_width(DisplayState *ds) -{ - return surface_width(ds->surface); -} - -static inline int ds_get_height(DisplayState *ds) -{ - return surface_height(ds->surface); -} - -static inline int ds_get_bits_per_pixel(DisplayState *ds) -{ - return surface_bits_per_pixel(ds->surface); -} - -static inline int ds_get_bytes_per_pixel(DisplayState *ds) -{ - return surface_bytes_per_pixel(ds->surface); -} - -static inline pixman_format_code_t ds_get_format(DisplayState *ds) -{ - return ds->surface->format; -} - -static inline pixman_image_t *ds_get_image(DisplayState *ds) -{ - return ds->surface->image; -} - -static inline int ds_get_depth(DisplayState *ds) -{ - return ds->surface->pf.depth; -} - -static inline int ds_get_rmask(DisplayState *ds) -{ - return ds->surface->pf.rmask; -} - -static inline int ds_get_gmask(DisplayState *ds) -{ - return ds->surface->pf.gmask; -} - -static inline int ds_get_bmask(DisplayState *ds) -{ - return ds->surface->pf.bmask; -} - #ifdef CONFIG_CURSES #include typedef chtype console_ch_t; diff --git a/ui/console.c b/ui/console.c index 27b165975b..eb7a2bc1bf 100644 --- a/ui/console.c +++ b/ui/console.c @@ -208,15 +208,17 @@ void vga_hw_text_update(console_ch_t *chardata) active_console->hw_text_update(active_console->hw, chardata); } -static void vga_fill_rect (DisplayState *ds, - int posx, int posy, int width, int height, uint32_t color) +static void vga_fill_rect(QemuConsole *con, + int posx, int posy, int width, int height, + uint32_t color) { + DisplaySurface *surface = qemu_console_surface(con); uint8_t *d, *d1; int x, y, bpp; - bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; - d1 = ds_get_data(ds) + - ds_get_linesize(ds) * posy + bpp * posx; + 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) { @@ -239,38 +241,40 @@ static void vga_fill_rect (DisplayState *ds, } break; } - d1 += ds_get_linesize(ds); + d1 += surface_stride(surface); } } /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */ -static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h) +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 = (ds_get_bits_per_pixel(ds) + 7) >> 3; + bpp = surface_bytes_per_pixel(surface); wb = w * bpp; if (yd <= ys) { - s = ds_get_data(ds) + - ds_get_linesize(ds) * ys + bpp * xs; - d = ds_get_data(ds) + - ds_get_linesize(ds) * yd + bpp * xd; + 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 += ds_get_linesize(ds); - s += ds_get_linesize(ds); + d += surface_stride(surface); + s += surface_stride(surface); } } else { - s = ds_get_data(ds) + - ds_get_linesize(ds) * (ys + h - 1) + bpp * xs; - d = ds_get_data(ds) + - ds_get_linesize(ds) * (yd + h - 1) + bpp * xd; + 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 -= ds_get_linesize(ds); - s -= ds_get_linesize(ds); + d -= surface_stride(surface); + s -= surface_stride(surface); } } } @@ -391,9 +395,10 @@ static void console_print_text_attributes(TextAttributes *t_attrib, char ch) } #endif -static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, +static void vga_putcharxy(QemuConsole *s, int x, int y, int ch, TextAttributes *t_attrib) { + DisplaySurface *surface = qemu_console_surface(s); uint8_t *d; const uint8_t *font_ptr; unsigned int font_data, linesize, xorcol, bpp; @@ -413,13 +418,13 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol]; } - bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; - d = ds_get_data(ds) + - ds_get_linesize(ds) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH; - linesize = ds_get_linesize(ds); + 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(ds_get_bits_per_pixel(ds)) { + switch (surface_bits_per_pixel(surface)) { case 8: for(i = 0; i < FONT_HEIGHT; i++) { font_data = *font_ptr++; @@ -524,19 +529,22 @@ static void update_xy(QemuConsole *s, int x, int y) TextCell *c; int y1, y2; - if (s == active_console) { - if (!ds_get_bits_per_pixel(s->ds)) { - text_update_xy(s, x, y); - return; - } + if (s != active_console) { + return; + } + if (s->ds->have_text) { + text_update_xy(s, x, y); + } + + if (s->ds->have_gfx) { y1 = (s->y_base + y) % s->total_height; y2 = y1 - s->y_displayed; if (y2 < 0) y2 += s->total_height; if (y2 < s->height) { c = &s->cells[y1 * s->width + x]; - vga_putcharxy(s->ds, x, y2, c->ch, + vga_putcharxy(s, x, y2, c->ch, &(c->t_attrib)); invalidate_xy(s, x, y2); } @@ -547,15 +555,17 @@ static void console_show_cursor(QemuConsole *s, int show) { TextCell *c; int y, y1; + int x = s->x; - if (s == active_console) { - int x = s->x; + if (s != active_console) { + return; + } - if (!ds_get_bits_per_pixel(s->ds)) { - s->cursor_invalidate = 1; - return; - } + if (s->ds->have_text) { + s->cursor_invalidate = 1; + } + if (s->ds->have_gfx) { if (x >= s->width) { x = s->width - 1; } @@ -568,9 +578,9 @@ static void console_show_cursor(QemuConsole *s, int show) if (show && s->cursor_visible_phase) { TextAttributes t_attrib = s->t_attrib_default; t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */ - vga_putcharxy(s->ds, x, y, c->ch, &t_attrib); + vga_putcharxy(s, x, y, c->ch, &t_attrib); } else { - vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib)); + vga_putcharxy(s, x, y, c->ch, &(c->t_attrib)); } invalidate_xy(s, x, y); } @@ -579,6 +589,7 @@ static void console_show_cursor(QemuConsole *s, int show) static void console_refresh(QemuConsole *s) { + DisplaySurface *surface = qemu_console_surface(s); TextCell *c; int x, y, y1; @@ -594,13 +605,13 @@ static void console_refresh(QemuConsole *s) } if (s->ds->have_gfx) { - vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds), + vga_fill_rect(s, 0, 0, surface_width(surface), surface_height(surface), color_table_rgb[0][COLOR_BLACK]); y1 = s->y_displayed; for (y = 0; y < s->height; y++) { c = s->cells + y1 * s->width; for (x = 0; x < s->width; x++) { - vga_putcharxy(s->ds, x, y, c->ch, + vga_putcharxy(s, x, y, c->ch, &(c->t_attrib)); c++; } @@ -609,7 +620,8 @@ static void console_refresh(QemuConsole *s) } } console_show_cursor(s, 1); - dpy_gfx_update(s, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds)); + dpy_gfx_update(s, 0, 0, + surface_width(surface), surface_height(surface)); } } @@ -672,24 +684,25 @@ static void console_put_lf(QemuConsole *s) c++; } if (s == active_console && s->y_displayed == s->y_base) { - if (!ds_get_bits_per_pixel(s->ds)) { + if (s->ds->have_text) { s->text_x[0] = 0; s->text_y[0] = 0; s->text_x[1] = s->width - 1; s->text_y[1] = s->height - 1; - return; } - vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0, - s->width * FONT_WIDTH, - (s->height - 1) * FONT_HEIGHT); - vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT, - s->width * FONT_WIDTH, FONT_HEIGHT, - color_table_rgb[0][s->t_attrib_default.bgcol]); - s->update_x0 = 0; - s->update_y0 = 0; - s->update_x1 = s->width * FONT_WIDTH; - s->update_y1 = s->height * FONT_HEIGHT; + if (s->ds->have_gfx) { + vga_bitblt(s, 0, FONT_HEIGHT, 0, 0, + s->width * FONT_WIDTH, + (s->height - 1) * FONT_HEIGHT); + vga_fill_rect(s, 0, (s->height - 1) * FONT_HEIGHT, + s->width * FONT_WIDTH, FONT_HEIGHT, + color_table_rgb[0][s->t_attrib_default.bgcol]); + s->update_x0 = 0; + s->update_y0 = 0; + s->update_x1 = s->width * FONT_WIDTH; + s->update_y1 = s->height * FONT_HEIGHT; + } } } } @@ -1027,13 +1040,15 @@ static void console_putchar(QemuConsole *s, int ch) void console_select(unsigned int index) { + DisplaySurface *surface; QemuConsole *s; if (index >= MAX_CONSOLES) return; if (active_console) { - active_console->g_width = ds_get_width(active_console->ds); - active_console->g_height = ds_get_height(active_console->ds); + 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) { @@ -1044,7 +1059,6 @@ void console_select(unsigned int index) } active_console = s; if (ds->have_gfx) { - DisplaySurface *surface; surface = qemu_create_displaysurface(s->g_width, s->g_height); dpy_gfx_replace_surface(s, surface); } @@ -1162,9 +1176,11 @@ void kbd_put_keysym(int keysym) static void text_console_invalidate(void *opaque) { QemuConsole *s = (QemuConsole *) opaque; - if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) { - s->g_width = ds_get_width(s->ds); - s->g_height = ds_get_height(s->ds); + 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); @@ -1551,8 +1567,8 @@ 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 = ds_get_width(s->ds); - s->g_height = ds_get_height(s->ds); + s->g_width = surface_width(s->ds->surface); + s->g_height = surface_height(s->ds->surface); } s->cursor_timer =