summaryrefslogtreecommitdiffstats
path: root/qemu/hw/display
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/hw/display')
-rw-r--r--qemu/hw/display/Makefile.objs7
-rw-r--r--qemu/hw/display/ads7846.c3
-rw-r--r--qemu/hw/display/bcm2835_fb.c425
-rw-r--r--qemu/hw/display/blizzard.c1
-rw-r--r--qemu/hw/display/cg3.c10
-rw-r--r--qemu/hw/display/cirrus_vga.c6
-rw-r--r--qemu/hw/display/exynos4210_fimd.c5
-rw-r--r--qemu/hw/display/framebuffer.c1
-rw-r--r--qemu/hw/display/g364fb.c1
-rw-r--r--qemu/hw/display/jazz_led.c7
-rw-r--r--qemu/hw/display/milkymist-tmu2.c5
-rw-r--r--qemu/hw/display/milkymist-vgafb.c1
-rw-r--r--qemu/hw/display/omap_dss.c4
-rw-r--r--qemu/hw/display/omap_lcd_template.h4
-rw-r--r--qemu/hw/display/omap_lcdc.c4
-rw-r--r--qemu/hw/display/pl110.c1
-rw-r--r--qemu/hw/display/pxa2xx_lcd.c9
-rw-r--r--qemu/hw/display/qxl-logger.c1
-rw-r--r--qemu/hw/display/qxl-render.c3
-rw-r--r--qemu/hw/display/qxl.c12
-rw-r--r--qemu/hw/display/sm501.c7
-rw-r--r--qemu/hw/display/ssd0303.c1
-rw-r--r--qemu/hw/display/ssd0323.c3
-rw-r--r--qemu/hw/display/tc6393xb.c4
-rw-r--r--qemu/hw/display/tcx.c33
-rw-r--r--qemu/hw/display/vga-isa-mm.c1
-rw-r--r--qemu/hw/display/vga-isa.c1
-rw-r--r--qemu/hw/display/vga-pci.c1
-rw-r--r--qemu/hw/display/vga.c135
-rw-r--r--qemu/hw/display/vga_int.h1
-rw-r--r--qemu/hw/display/virtio-gpu-3d.c606
-rw-r--r--qemu/hw/display/virtio-gpu-pci.c5
-rw-r--r--qemu/hw/display/virtio-gpu.c226
-rw-r--r--qemu/hw/display/virtio-vga.c11
-rw-r--r--qemu/hw/display/vmware_vga.c15
-rw-r--r--qemu/hw/display/xenfb.c58
36 files changed, 1447 insertions, 171 deletions
diff --git a/qemu/hw/display/Makefile.objs b/qemu/hw/display/Makefile.objs
index dd8ea76d1..d99780eeb 100644
--- a/qemu/hw/display/Makefile.objs
+++ b/qemu/hw/display/Makefile.objs
@@ -27,6 +27,7 @@ endif
obj-$(CONFIG_OMAP) += omap_dss.o
obj-$(CONFIG_OMAP) += omap_lcdc.o
obj-$(CONFIG_PXA2XX) += pxa2xx_lcd.o
+obj-$(CONFIG_RASPI) += bcm2835_fb.o
obj-$(CONFIG_SM501) += sm501.o
obj-$(CONFIG_TCX) += tcx.o
obj-$(CONFIG_CG3) += cg3.o
@@ -35,6 +36,10 @@ obj-$(CONFIG_VGA) += vga.o
common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
-obj-$(CONFIG_VIRTIO) += virtio-gpu.o
+obj-$(CONFIG_VIRTIO) += virtio-gpu.o virtio-gpu-3d.o
obj-$(CONFIG_VIRTIO_PCI) += virtio-gpu-pci.o
obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o
+virtio-gpu.o-cflags := $(VIRGL_CFLAGS)
+virtio-gpu.o-libs += $(VIRGL_LIBS)
+virtio-gpu-3d.o-cflags := $(VIRGL_CFLAGS)
+virtio-gpu-3d.o-libs += $(VIRGL_LIBS)
diff --git a/qemu/hw/display/ads7846.c b/qemu/hw/display/ads7846.c
index 3f35369bb..05aa2d1e6 100644
--- a/qemu/hw/display/ads7846.c
+++ b/qemu/hw/display/ads7846.c
@@ -10,7 +10,8 @@
* GNU GPL, version 2 or (at your option) any later version.
*/
-#include "hw/ssi.h"
+#include "qemu/osdep.h"
+#include "hw/ssi/ssi.h"
#include "ui/console.h"
typedef struct {
diff --git a/qemu/hw/display/bcm2835_fb.c b/qemu/hw/display/bcm2835_fb.c
new file mode 100644
index 000000000..506f1d3d9
--- /dev/null
+++ b/qemu/hw/display/bcm2835_fb.c
@@ -0,0 +1,425 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Refactoring for Pi2 Copyright (c) 2015, Microsoft. Written by Andrew Baumann.
+ * This code is licensed under the GNU GPLv2 and later.
+ *
+ * Heavily based on milkymist-vgafb.c, copyright terms below:
+ * QEMU model of the Milkymist VGA framebuffer.
+ *
+ * Copyright (c) 2010-2012 Michael Walle <michael@walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/display/bcm2835_fb.h"
+#include "hw/display/framebuffer.h"
+#include "ui/pixel_ops.h"
+#include "hw/misc/bcm2835_mbox_defs.h"
+
+#define DEFAULT_VCRAM_SIZE 0x4000000
+#define BCM2835_FB_OFFSET 0x00100000
+
+static void fb_invalidate_display(void *opaque)
+{
+ BCM2835FBState *s = BCM2835_FB(opaque);
+
+ s->invalidate = true;
+}
+
+static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src,
+ int width, int deststep)
+{
+ BCM2835FBState *s = opaque;
+ uint16_t rgb565;
+ uint32_t rgb888;
+ uint8_t r, g, b;
+ DisplaySurface *surface = qemu_console_surface(s->con);
+ int bpp = surface_bits_per_pixel(surface);
+
+ while (width--) {
+ switch (s->bpp) {
+ case 8:
+ /* lookup palette starting at video ram base
+ * TODO: cache translation, rather than doing this each time!
+ */
+ rgb888 = ldl_le_phys(&s->dma_as, s->vcram_base + (*src << 2));
+ r = (rgb888 >> 0) & 0xff;
+ g = (rgb888 >> 8) & 0xff;
+ b = (rgb888 >> 16) & 0xff;
+ src++;
+ break;
+ case 16:
+ rgb565 = lduw_le_p(src);
+ r = ((rgb565 >> 11) & 0x1f) << 3;
+ g = ((rgb565 >> 5) & 0x3f) << 2;
+ b = ((rgb565 >> 0) & 0x1f) << 3;
+ src += 2;
+ break;
+ case 24:
+ rgb888 = ldl_le_p(src);
+ r = (rgb888 >> 0) & 0xff;
+ g = (rgb888 >> 8) & 0xff;
+ b = (rgb888 >> 16) & 0xff;
+ src += 3;
+ break;
+ case 32:
+ rgb888 = ldl_le_p(src);
+ r = (rgb888 >> 0) & 0xff;
+ g = (rgb888 >> 8) & 0xff;
+ b = (rgb888 >> 16) & 0xff;
+ src += 4;
+ break;
+ default:
+ r = 0;
+ g = 0;
+ b = 0;
+ break;
+ }
+
+ if (s->pixo == 0) {
+ /* swap to BGR pixel format */
+ uint8_t tmp = r;
+ r = b;
+ b = tmp;
+ }
+
+ switch (bpp) {
+ case 8:
+ *dst++ = rgb_to_pixel8(r, g, b);
+ break;
+ case 15:
+ *(uint16_t *)dst = rgb_to_pixel15(r, g, b);
+ dst += 2;
+ break;
+ case 16:
+ *(uint16_t *)dst = rgb_to_pixel16(r, g, b);
+ dst += 2;
+ break;
+ case 24:
+ rgb888 = rgb_to_pixel24(r, g, b);
+ *dst++ = rgb888 & 0xff;
+ *dst++ = (rgb888 >> 8) & 0xff;
+ *dst++ = (rgb888 >> 16) & 0xff;
+ break;
+ case 32:
+ *(uint32_t *)dst = rgb_to_pixel32(r, g, b);
+ dst += 4;
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+static void fb_update_display(void *opaque)
+{
+ BCM2835FBState *s = opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
+ int first = 0;
+ int last = 0;
+ int src_width = 0;
+ int dest_width = 0;
+
+ if (s->lock || !s->xres) {
+ return;
+ }
+
+ src_width = s->xres * (s->bpp >> 3);
+ dest_width = s->xres;
+
+ switch (surface_bits_per_pixel(surface)) {
+ case 0:
+ return;
+ case 8:
+ break;
+ case 15:
+ dest_width *= 2;
+ break;
+ case 16:
+ dest_width *= 2;
+ break;
+ case 24:
+ dest_width *= 3;
+ break;
+ case 32:
+ dest_width *= 4;
+ break;
+ default:
+ hw_error("bcm2835_fb: bad color depth\n");
+ break;
+ }
+
+ if (s->invalidate) {
+ framebuffer_update_memory_section(&s->fbsection, s->dma_mr, s->base,
+ s->yres, src_width);
+ }
+
+ framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
+ src_width, dest_width, 0, s->invalidate,
+ draw_line_src16, s, &first, &last);
+
+ if (first >= 0) {
+ dpy_gfx_update(s->con, 0, first, s->xres, last - first + 1);
+ }
+
+ s->invalidate = false;
+}
+
+static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
+{
+ value &= ~0xf;
+
+ s->lock = true;
+
+ s->xres = ldl_le_phys(&s->dma_as, value);
+ s->yres = ldl_le_phys(&s->dma_as, value + 4);
+ s->xres_virtual = ldl_le_phys(&s->dma_as, value + 8);
+ s->yres_virtual = ldl_le_phys(&s->dma_as, value + 12);
+ s->bpp = ldl_le_phys(&s->dma_as, value + 20);
+ s->xoffset = ldl_le_phys(&s->dma_as, value + 24);
+ s->yoffset = ldl_le_phys(&s->dma_as, value + 28);
+
+ s->base = s->vcram_base | (value & 0xc0000000);
+ s->base += BCM2835_FB_OFFSET;
+
+ /* TODO - Manage properly virtual resolution */
+
+ s->pitch = s->xres * (s->bpp >> 3);
+ s->size = s->yres * s->pitch;
+
+ stl_le_phys(&s->dma_as, value + 16, s->pitch);
+ stl_le_phys(&s->dma_as, value + 32, s->base);
+ stl_le_phys(&s->dma_as, value + 36, s->size);
+
+ s->invalidate = true;
+ qemu_console_resize(s->con, s->xres, s->yres);
+ s->lock = false;
+}
+
+void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
+ uint32_t *xoffset, uint32_t *yoffset, uint32_t *bpp,
+ uint32_t *pixo, uint32_t *alpha)
+{
+ s->lock = true;
+
+ /* TODO: input validation! */
+ if (xres) {
+ s->xres = *xres;
+ }
+ if (yres) {
+ s->yres = *yres;
+ }
+ if (xoffset) {
+ s->xoffset = *xoffset;
+ }
+ if (yoffset) {
+ s->yoffset = *yoffset;
+ }
+ if (bpp) {
+ s->bpp = *bpp;
+ }
+ if (pixo) {
+ s->pixo = *pixo;
+ }
+ if (alpha) {
+ s->alpha = *alpha;
+ }
+
+ /* TODO - Manage properly virtual resolution */
+
+ s->pitch = s->xres * (s->bpp >> 3);
+ s->size = s->yres * s->pitch;
+
+ s->invalidate = true;
+ qemu_console_resize(s->con, s->xres, s->yres);
+ s->lock = false;
+}
+
+static uint64_t bcm2835_fb_read(void *opaque, hwaddr offset, unsigned size)
+{
+ BCM2835FBState *s = opaque;
+ uint32_t res = 0;
+
+ switch (offset) {
+ case MBOX_AS_DATA:
+ res = MBOX_CHAN_FB;
+ s->pending = false;
+ qemu_set_irq(s->mbox_irq, 0);
+ break;
+
+ case MBOX_AS_PENDING:
+ res = s->pending;
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ return 0;
+ }
+
+ return res;
+}
+
+static void bcm2835_fb_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ BCM2835FBState *s = opaque;
+
+ switch (offset) {
+ case MBOX_AS_DATA:
+ /* bcm2835_mbox should check our pending status before pushing */
+ assert(!s->pending);
+ s->pending = true;
+ bcm2835_fb_mbox_push(s, value);
+ qemu_set_irq(s->mbox_irq, 1);
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ return;
+ }
+}
+
+static const MemoryRegionOps bcm2835_fb_ops = {
+ .read = bcm2835_fb_read,
+ .write = bcm2835_fb_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
+static const VMStateDescription vmstate_bcm2835_fb = {
+ .name = TYPE_BCM2835_FB,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_BOOL(lock, BCM2835FBState),
+ VMSTATE_BOOL(invalidate, BCM2835FBState),
+ VMSTATE_BOOL(pending, BCM2835FBState),
+ VMSTATE_UINT32(xres, BCM2835FBState),
+ VMSTATE_UINT32(yres, BCM2835FBState),
+ VMSTATE_UINT32(xres_virtual, BCM2835FBState),
+ VMSTATE_UINT32(yres_virtual, BCM2835FBState),
+ VMSTATE_UINT32(xoffset, BCM2835FBState),
+ VMSTATE_UINT32(yoffset, BCM2835FBState),
+ VMSTATE_UINT32(bpp, BCM2835FBState),
+ VMSTATE_UINT32(base, BCM2835FBState),
+ VMSTATE_UINT32(pitch, BCM2835FBState),
+ VMSTATE_UINT32(size, BCM2835FBState),
+ VMSTATE_UINT32(pixo, BCM2835FBState),
+ VMSTATE_UINT32(alpha, BCM2835FBState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const GraphicHwOps vgafb_ops = {
+ .invalidate = fb_invalidate_display,
+ .gfx_update = fb_update_display,
+};
+
+static void bcm2835_fb_init(Object *obj)
+{
+ BCM2835FBState *s = BCM2835_FB(obj);
+
+ memory_region_init_io(&s->iomem, obj, &bcm2835_fb_ops, s, TYPE_BCM2835_FB,
+ 0x10);
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->mbox_irq);
+}
+
+static void bcm2835_fb_reset(DeviceState *dev)
+{
+ BCM2835FBState *s = BCM2835_FB(dev);
+
+ s->pending = false;
+
+ s->xres_virtual = s->xres;
+ s->yres_virtual = s->yres;
+ s->xoffset = 0;
+ s->yoffset = 0;
+ s->base = s->vcram_base + BCM2835_FB_OFFSET;
+ s->pitch = s->xres * (s->bpp >> 3);
+ s->size = s->yres * s->pitch;
+
+ s->invalidate = true;
+ s->lock = false;
+}
+
+static void bcm2835_fb_realize(DeviceState *dev, Error **errp)
+{
+ BCM2835FBState *s = BCM2835_FB(dev);
+ Error *err = NULL;
+ Object *obj;
+
+ if (s->vcram_base == 0) {
+ error_setg(errp, "%s: required vcram-base property not set", __func__);
+ return;
+ }
+
+ obj = object_property_get_link(OBJECT(dev), "dma-mr", &err);
+ if (obj == NULL) {
+ error_setg(errp, "%s: required dma-mr link not found: %s",
+ __func__, error_get_pretty(err));
+ return;
+ }
+
+ s->dma_mr = MEMORY_REGION(obj);
+ address_space_init(&s->dma_as, s->dma_mr, NULL);
+
+ bcm2835_fb_reset(dev);
+
+ s->con = graphic_console_init(dev, 0, &vgafb_ops, s);
+ qemu_console_resize(s->con, s->xres, s->yres);
+}
+
+static Property bcm2835_fb_props[] = {
+ DEFINE_PROP_UINT32("vcram-base", BCM2835FBState, vcram_base, 0),/*required*/
+ DEFINE_PROP_UINT32("vcram-size", BCM2835FBState, vcram_size,
+ DEFAULT_VCRAM_SIZE),
+ DEFINE_PROP_UINT32("xres", BCM2835FBState, xres, 640),
+ DEFINE_PROP_UINT32("yres", BCM2835FBState, yres, 480),
+ DEFINE_PROP_UINT32("bpp", BCM2835FBState, bpp, 16),
+ DEFINE_PROP_UINT32("pixo", BCM2835FBState, pixo, 1), /* 1=RGB, 0=BGR */
+ DEFINE_PROP_UINT32("alpha", BCM2835FBState, alpha, 2), /* alpha ignored */
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void bcm2835_fb_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->props = bcm2835_fb_props;
+ dc->realize = bcm2835_fb_realize;
+ dc->reset = bcm2835_fb_reset;
+ dc->vmsd = &vmstate_bcm2835_fb;
+}
+
+static TypeInfo bcm2835_fb_info = {
+ .name = TYPE_BCM2835_FB,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BCM2835FBState),
+ .class_init = bcm2835_fb_class_init,
+ .instance_init = bcm2835_fb_init,
+};
+
+static void bcm2835_fb_register_types(void)
+{
+ type_register_static(&bcm2835_fb_info);
+}
+
+type_init(bcm2835_fb_register_types)
diff --git a/qemu/hw/display/blizzard.c b/qemu/hw/display/blizzard.c
index 5019bbbef..c231960d9 100644
--- a/qemu/hw/display/blizzard.c
+++ b/qemu/hw/display/blizzard.c
@@ -18,6 +18,7 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "qemu-common.h"
#include "ui/console.h"
#include "hw/devices.h"
diff --git a/qemu/hw/display/cg3.c b/qemu/hw/display/cg3.c
index 34dcbc311..fc0d97fa4 100644
--- a/qemu/hw/display/cg3.c
+++ b/qemu/hw/display/cg3.c
@@ -23,6 +23,8 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qemu-common.h"
#include "qemu/error-report.h"
#include "ui/console.h"
@@ -280,12 +282,12 @@ static void cg3_initfn(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
CG3State *s = CG3(obj);
- memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE,
- &error_abort);
+ memory_region_init_ram(&s->rom, obj, "cg3.prom", FCODE_MAX_ROM_SIZE,
+ &error_fatal);
memory_region_set_readonly(&s->rom, true);
sysbus_init_mmio(sbd, &s->rom);
- memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
+ memory_region_init_io(&s->reg, obj, &cg3_reg_ops, s, "cg3.reg",
CG3_REG_SIZE);
sysbus_init_mmio(sbd, &s->reg);
}
@@ -310,7 +312,7 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
}
memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size,
- &error_abort);
+ &error_fatal);
memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA);
vmstate_register_ram_global(&s->vram_mem);
sysbus_init_mmio(sbd, &s->vram_mem);
diff --git a/qemu/hw/display/cirrus_vga.c b/qemu/hw/display/cirrus_vga.c
index 5198037d8..3d712d592 100644
--- a/qemu/hw/display/cirrus_vga.c
+++ b/qemu/hw/display/cirrus_vga.c
@@ -26,6 +26,8 @@
* Reference: Finn Thogersons' VGADOC4b
* available at http://home.worldonline.dk/~finth/
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/hw.h"
#include "hw/pci/pci.h"
#include "ui/console.h"
@@ -275,14 +277,14 @@ static bool blit_region_is_unsafe(struct CirrusVGAState *s,
+ ((int64_t)s->cirrus_blt_height-1) * pitch;
int32_t max = addr
+ s->cirrus_blt_width;
- if (min < 0 || max >= s->vga.vram_size) {
+ if (min < 0 || max > s->vga.vram_size) {
return true;
}
} else {
int64_t max = addr
+ ((int64_t)s->cirrus_blt_height-1) * pitch
+ s->cirrus_blt_width;
- if (max >= s->vga.vram_size) {
+ if (max > s->vga.vram_size) {
return true;
}
}
diff --git a/qemu/hw/display/exynos4210_fimd.c b/qemu/hw/display/exynos4210_fimd.c
index 603ef5056..728eb214a 100644
--- a/qemu/hw/display/exynos4210_fimd.c
+++ b/qemu/hw/display/exynos4210_fimd.c
@@ -22,6 +22,7 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "qemu-common.h"
#include "hw/sysbus.h"
#include "ui/console.h"
@@ -1354,9 +1355,7 @@ static void exynos4210_fimd_reset(DeviceState *d)
fimd_update_get_alpha(s, w);
}
- if (s->ifb != NULL) {
- g_free(s->ifb);
- }
+ g_free(s->ifb);
s->ifb = NULL;
exynos4210_fimd_invalidate(s);
diff --git a/qemu/hw/display/framebuffer.c b/qemu/hw/display/framebuffer.c
index 7f075ce77..df51358e7 100644
--- a/qemu/hw/display/framebuffer.c
+++ b/qemu/hw/display/framebuffer.c
@@ -17,6 +17,7 @@
- Remove all DisplayState knowledge from devices.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "ui/console.h"
#include "framebuffer.h"
diff --git a/qemu/hw/display/g364fb.c b/qemu/hw/display/g364fb.c
index 7f83a007b..70ef2c745 100644
--- a/qemu/hw/display/g364fb.c
+++ b/qemu/hw/display/g364fb.c
@@ -17,6 +17,7 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "qemu/error-report.h"
#include "ui/console.h"
diff --git a/qemu/hw/display/jazz_led.c b/qemu/hw/display/jazz_led.c
index 12b1707cb..09dcdb46a 100644
--- a/qemu/hw/display/jazz_led.c
+++ b/qemu/hw/display/jazz_led.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "qemu-common.h"
#include "ui/console.h"
#include "ui/pixel_ops.h"
@@ -233,8 +234,10 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
/* 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]);
+ console_write_ch(chardata++, ATTR2CHTYPE(buf[0], QEMU_COLOR_BLUE,
+ QEMU_COLOR_BLACK, 1));
+ console_write_ch(chardata++, ATTR2CHTYPE(buf[1], QEMU_COLOR_BLUE,
+ QEMU_COLOR_BLACK, 1));
dpy_text_update(s->con, 0, 0, 2, 1);
}
diff --git a/qemu/hw/display/milkymist-tmu2.c b/qemu/hw/display/milkymist-tmu2.c
index 3e1d0b9c2..9bc88f93b 100644
--- a/qemu/hw/display/milkymist-tmu2.c
+++ b/qemu/hw/display/milkymist-tmu2.c
@@ -24,14 +24,15 @@
*
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "trace.h"
#include "qemu/error-report.h"
#include <X11/Xlib.h>
-#include <GL/gl.h>
-#include <GL/glx.h>
+#include <epoxy/gl.h>
+#include <epoxy/glx.h>
enum {
R_CTL = 0,
diff --git a/qemu/hw/display/milkymist-vgafb.c b/qemu/hw/display/milkymist-vgafb.c
index ab3074fad..19ca25647 100644
--- a/qemu/hw/display/milkymist-vgafb.c
+++ b/qemu/hw/display/milkymist-vgafb.c
@@ -22,6 +22,7 @@
* http://www.milkymist.org/socdoc/vgafb.pdf
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "trace.h"
diff --git a/qemu/hw/display/omap_dss.c b/qemu/hw/display/omap_dss.c
index f1fef2767..783e9e131 100644
--- a/qemu/hw/display/omap_dss.c
+++ b/qemu/hw/display/omap_dss.c
@@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "ui/console.h"
#include "hw/arm/omap.h"
@@ -1051,8 +1052,7 @@ struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
omap_clk fck1, omap_clk fck2, omap_clk ck54m,
omap_clk ick1, omap_clk ick2)
{
- struct omap_dss_s *s = (struct omap_dss_s *)
- g_malloc0(sizeof(struct omap_dss_s));
+ struct omap_dss_s *s = g_new0(struct omap_dss_s, 1);
s->irq = irq;
s->drq = drq;
diff --git a/qemu/hw/display/omap_lcd_template.h b/qemu/hw/display/omap_lcd_template.h
index e5dd44716..f0ce71fd6 100644
--- a/qemu/hw/display/omap_lcd_template.h
+++ b/qemu/hw/display/omap_lcd_template.h
@@ -136,7 +136,7 @@ static void glue(draw_line12_, DEPTH)(void *opaque,
uint8_t r, g, b;
do {
- v = lduw_p((void *) s);
+ v = lduw_le_p((void *) s);
r = (v >> 4) & 0xf0;
g = v & 0xf0;
b = (v << 4) & 0xf0;
@@ -159,7 +159,7 @@ static void glue(draw_line16_, DEPTH)(void *opaque,
uint8_t r, g, b;
do {
- v = lduw_p((void *) s);
+ v = lduw_le_p((void *) s);
r = (v >> 8) & 0xf8;
g = (v >> 3) & 0xfc;
b = (v << 3) & 0xf8;
diff --git a/qemu/hw/display/omap_lcdc.c b/qemu/hw/display/omap_lcdc.c
index a7c6cd79b..ce1058bf8 100644
--- a/qemu/hw/display/omap_lcdc.c
+++ b/qemu/hw/display/omap_lcdc.c
@@ -16,6 +16,7 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "ui/console.h"
#include "hw/arm/omap.h"
@@ -403,8 +404,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
struct omap_dma_lcd_channel_s *dma,
omap_clk clk)
{
- struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *)
- g_malloc0(sizeof(struct omap_lcd_panel_s));
+ struct omap_lcd_panel_s *s = g_new0(struct omap_lcd_panel_s, 1);
s->irq = irq;
s->dma = dma;
diff --git a/qemu/hw/display/pl110.c b/qemu/hw/display/pl110.c
index ef1a7b1a5..d589959f1 100644
--- a/qemu/hw/display/pl110.c
+++ b/qemu/hw/display/pl110.c
@@ -7,6 +7,7 @@
* This code is licensed under the GNU LGPL
*/
+#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "ui/console.h"
#include "framebuffer.h"
diff --git a/qemu/hw/display/pxa2xx_lcd.c b/qemu/hw/display/pxa2xx_lcd.c
index 494700d07..845521c5b 100644
--- a/qemu/hw/display/pxa2xx_lcd.c
+++ b/qemu/hw/display/pxa2xx_lcd.c
@@ -10,6 +10,7 @@
* GNU GPL, version 2 or (at your option) any later version.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "ui/console.h"
#include "hw/arm/pxa.h"
@@ -309,10 +310,10 @@ static void pxa2xx_descriptor_load(PXA2xxLCDState *s)
}
cpu_physical_memory_read(descptr, &desc, sizeof(desc));
- s->dma_ch[i].descriptor = tswap32(desc.fdaddr);
- s->dma_ch[i].source = tswap32(desc.fsaddr);
- s->dma_ch[i].id = tswap32(desc.fidr);
- s->dma_ch[i].command = tswap32(desc.ldcmd);
+ s->dma_ch[i].descriptor = le32_to_cpu(desc.fdaddr);
+ s->dma_ch[i].source = le32_to_cpu(desc.fsaddr);
+ s->dma_ch[i].id = le32_to_cpu(desc.fidr);
+ s->dma_ch[i].command = le32_to_cpu(desc.ldcmd);
}
}
diff --git a/qemu/hw/display/qxl-logger.c b/qemu/hw/display/qxl-logger.c
index d944d3fdb..2ec6d8fa3 100644
--- a/qemu/hw/display/qxl-logger.c
+++ b/qemu/hw/display/qxl-logger.c
@@ -19,6 +19,7 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "qemu/timer.h"
#include "qxl.h"
diff --git a/qemu/hw/display/qxl-render.c b/qemu/hw/display/qxl-render.c
index a542087fc..9ad9d9e0f 100644
--- a/qemu/hw/display/qxl-render.c
+++ b/qemu/hw/display/qxl-render.c
@@ -19,6 +19,7 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "qxl.h"
#include "trace.h"
@@ -159,7 +160,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
/*
* use ssd.lock to protect render_update_cookie_num.
* qxl_render_update is called by io thread or vcpu thread, and the completion
- * callbacks are called by spice_server thread, defering to bh called from the
+ * callbacks are called by spice_server thread, deferring to bh called from the
* io thread.
*/
void qxl_render_update(PCIQXLDevice *qxl)
diff --git a/qemu/hw/display/qxl.c b/qemu/hw/display/qxl.c
index 2288238d0..919dc5cd3 100644
--- a/qemu/hw/display/qxl.c
+++ b/qemu/hw/display/qxl.c
@@ -18,8 +18,8 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include <zlib.h>
-#include <stdint.h>
#include "qemu-common.h"
#include "qemu/timer.h"
@@ -1156,7 +1156,9 @@ static void qxl_soft_reset(PCIQXLDevice *d)
trace_qxl_soft_reset(d->id);
qxl_check_state(d);
qxl_clear_guest_bug(d);
+ qemu_mutex_lock(&d->async_lock);
d->current_async = QXL_UNDEFINED_IO;
+ qemu_mutex_unlock(&d->async_lock);
if (d->id == 0) {
qxl_enter_vga_mode(d);
@@ -1970,14 +1972,14 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp)
qxl->rom_size = qxl_rom_size();
memory_region_init_ram(&qxl->rom_bar, OBJECT(qxl), "qxl.vrom",
- qxl->rom_size, &error_abort);
+ qxl->rom_size, &error_fatal);
vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev);
init_qxl_rom(qxl);
init_qxl_ram(qxl);
qxl->guest_surfaces.cmds = g_new0(QXLPHYSICAL, qxl->ssd.num_surfaces);
memory_region_init_ram(&qxl->vram_bar, OBJECT(qxl), "qxl.vram",
- qxl->vram_size, &error_abort);
+ qxl->vram_size, &error_fatal);
vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev);
memory_region_init_alias(&qxl->vram32_bar, OBJECT(qxl), "qxl.vram32",
&qxl->vram_bar, 0, qxl->vram32_size);
@@ -2079,7 +2081,7 @@ static void qxl_realize_secondary(PCIDevice *dev, Error **errp)
qxl->id = device_id++;
qxl_init_ramsize(qxl);
memory_region_init_ram(&qxl->vga.vram, OBJECT(dev), "qxl.vgavram",
- qxl->vga.vram_size, &error_abort);
+ qxl->vga.vram_size, &error_fatal);
vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev);
qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
qxl->vga.con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl);
@@ -2156,7 +2158,7 @@ static int qxl_post_load(void *opaque, int version)
qxl_create_guest_primary(d, 1, QXL_SYNC);
/* replay surface-create and cursor-set commands */
- cmds = g_malloc0(sizeof(QXLCommandExt) * (d->ssd.num_surfaces + 1));
+ cmds = g_new0(QXLCommandExt, d->ssd.num_surfaces + 1);
for (in = 0, out = 0; in < d->ssd.num_surfaces; in++) {
if (d->guest_surfaces.cmds[in] == 0) {
continue;
diff --git a/qemu/hw/display/sm501.c b/qemu/hw/display/sm501.c
index 15a5ba800..5f7101210 100644
--- a/qemu/hw/display/sm501.c
+++ b/qemu/hw/display/sm501.c
@@ -22,7 +22,10 @@
* THE SOFTWARE.
*/
-#include <stdio.h>
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
#include "hw/hw.h"
#include "hw/char/serial.h"
#include "ui/console.h"
@@ -1411,7 +1414,7 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
/* allocate local memory */
memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local",
- local_mem_bytes, &error_abort);
+ local_mem_bytes, &error_fatal);
vmstate_register_ram_global(&s->local_mem_region);
memory_region_set_log(&s->local_mem_region, true, DIRTY_MEMORY_VGA);
s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region);
diff --git a/qemu/hw/display/ssd0303.c b/qemu/hw/display/ssd0303.c
index f6804fb51..d3017563f 100644
--- a/qemu/hw/display/ssd0303.c
+++ b/qemu/hw/display/ssd0303.c
@@ -10,6 +10,7 @@
/* The controller can support a variety of different displays, but we only
implement one. Most of the commends relating to brightness and geometry
setup are ignored. */
+#include "qemu/osdep.h"
#include "hw/i2c/i2c.h"
#include "ui/console.h"
diff --git a/qemu/hw/display/ssd0323.c b/qemu/hw/display/ssd0323.c
index 97270077e..14c1bf339 100644
--- a/qemu/hw/display/ssd0323.c
+++ b/qemu/hw/display/ssd0323.c
@@ -10,7 +10,8 @@
/* The controller can support a variety of different displays, but we only
implement one. Most of the commends relating to brightness and geometry
setup are ignored. */
-#include "hw/ssi.h"
+#include "qemu/osdep.h"
+#include "hw/ssi/ssi.h"
#include "ui/console.h"
//#define DEBUG_SSD0323 1
diff --git a/qemu/hw/display/tc6393xb.c b/qemu/hw/display/tc6393xb.c
index f5f3f3e69..da3ceceb0 100644
--- a/qemu/hw/display/tc6393xb.c
+++ b/qemu/hw/display/tc6393xb.c
@@ -10,6 +10,8 @@
* 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/osdep.h"
+#include "qapi/error.h"
#include "hw/hw.h"
#include "hw/devices.h"
#include "hw/block/flash.h"
@@ -584,7 +586,7 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
memory_region_add_subregion(sysmem, base, &s->iomem);
memory_region_init_ram(&s->vram, NULL, "tc6393xb.vram", 0x100000,
- &error_abort);
+ &error_fatal);
vmstate_register_ram_global(&s->vram);
s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
memory_region_add_subregion(sysmem, base + 0x100000, &s->vram);
diff --git a/qemu/hw/display/tcx.c b/qemu/hw/display/tcx.c
index 6acdc2d28..8e26aae80 100644
--- a/qemu/hw/display/tcx.c
+++ b/qemu/hw/display/tcx.c
@@ -22,7 +22,10 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qemu-common.h"
+#include "cpu.h" /* FIXME shouldn't use TARGET_PAGE_SIZE */
#include "ui/console.h"
#include "ui/pixel_ops.h"
#include "hw/loader.h"
@@ -944,57 +947,55 @@ static void tcx_initfn(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
TCXState *s = TCX(obj);
- memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE,
- &error_abort);
+ memory_region_init_ram(&s->rom, obj, "tcx.prom", FCODE_MAX_ROM_SIZE,
+ &error_fatal);
memory_region_set_readonly(&s->rom, true);
sysbus_init_mmio(sbd, &s->rom);
/* 2/STIP : Stippler */
- memory_region_init_io(&s->stip, OBJECT(s), &tcx_stip_ops, s, "tcx.stip",
+ memory_region_init_io(&s->stip, obj, &tcx_stip_ops, s, "tcx.stip",
TCX_STIP_NREGS);
sysbus_init_mmio(sbd, &s->stip);
/* 3/BLIT : Blitter */
- memory_region_init_io(&s->blit, OBJECT(s), &tcx_blit_ops, s, "tcx.blit",
+ memory_region_init_io(&s->blit, obj, &tcx_blit_ops, s, "tcx.blit",
TCX_BLIT_NREGS);
sysbus_init_mmio(sbd, &s->blit);
/* 5/RSTIP : Raw Stippler */
- memory_region_init_io(&s->rstip, OBJECT(s), &tcx_rstip_ops, s, "tcx.rstip",
+ memory_region_init_io(&s->rstip, obj, &tcx_rstip_ops, s, "tcx.rstip",
TCX_RSTIP_NREGS);
sysbus_init_mmio(sbd, &s->rstip);
/* 6/RBLIT : Raw Blitter */
- memory_region_init_io(&s->rblit, OBJECT(s), &tcx_rblit_ops, s, "tcx.rblit",
+ memory_region_init_io(&s->rblit, obj, &tcx_rblit_ops, s, "tcx.rblit",
TCX_RBLIT_NREGS);
sysbus_init_mmio(sbd, &s->rblit);
/* 7/TEC : ??? */
- memory_region_init_io(&s->tec, OBJECT(s), &tcx_dummy_ops, s,
- "tcx.tec", TCX_TEC_NREGS);
+ memory_region_init_io(&s->tec, obj, &tcx_dummy_ops, s, "tcx.tec",
+ TCX_TEC_NREGS);
sysbus_init_mmio(sbd, &s->tec);
/* 8/CMAP : DAC */
- memory_region_init_io(&s->dac, OBJECT(s), &tcx_dac_ops, s,
- "tcx.dac", TCX_DAC_NREGS);
+ memory_region_init_io(&s->dac, obj, &tcx_dac_ops, s, "tcx.dac",
+ TCX_DAC_NREGS);
sysbus_init_mmio(sbd, &s->dac);
/* 9/THC : Cursor */
- memory_region_init_io(&s->thc, OBJECT(s), &tcx_thc_ops, s, "tcx.thc",
+ memory_region_init_io(&s->thc, obj, &tcx_thc_ops, s, "tcx.thc",
TCX_THC_NREGS);
sysbus_init_mmio(sbd, &s->thc);
/* 11/DHC : ??? */
- memory_region_init_io(&s->dhc, OBJECT(s), &tcx_dummy_ops, s, "tcx.dhc",
+ memory_region_init_io(&s->dhc, obj, &tcx_dummy_ops, s, "tcx.dhc",
TCX_DHC_NREGS);
sysbus_init_mmio(sbd, &s->dhc);
/* 12/ALT : ??? */
- memory_region_init_io(&s->alt, OBJECT(s), &tcx_dummy_ops, s, "tcx.alt",
+ memory_region_init_io(&s->alt, obj, &tcx_dummy_ops, s, "tcx.alt",
TCX_ALT_NREGS);
sysbus_init_mmio(sbd, &s->alt);
-
- return;
}
static void tcx_realizefn(DeviceState *dev, Error **errp)
@@ -1007,7 +1008,7 @@ static void tcx_realizefn(DeviceState *dev, Error **errp)
char *fcode_filename;
memory_region_init_ram(&s->vram_mem, OBJECT(s), "tcx.vram",
- s->vram_size * (1 + 4 + 4), &error_abort);
+ s->vram_size * (1 + 4 + 4), &error_fatal);
vmstate_register_ram_global(&s->vram_mem);
memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA);
vram_base = memory_region_get_ram_ptr(&s->vram_mem);
diff --git a/qemu/hw/display/vga-isa-mm.c b/qemu/hw/display/vga-isa-mm.c
index 4efc22278..51ccbccc4 100644
--- a/qemu/hw/display/vga-isa-mm.c
+++ b/qemu/hw/display/vga-isa-mm.c
@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "ui/console.h"
#include "hw/i386/pc.h"
diff --git a/qemu/hw/display/vga-isa.c b/qemu/hw/display/vga-isa.c
index 7f3c98941..f5aff1cbe 100644
--- a/qemu/hw/display/vga-isa.c
+++ b/qemu/hw/display/vga-isa.c
@@ -23,6 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "ui/console.h"
#include "hw/i386/pc.h"
diff --git a/qemu/hw/display/vga-pci.c b/qemu/hw/display/vga-pci.c
index 1dfa331e6..ac9a76499 100644
--- a/qemu/hw/display/vga-pci.c
+++ b/qemu/hw/display/vga-pci.c
@@ -23,6 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "ui/console.h"
#include "hw/pci/pci.h"
diff --git a/qemu/hw/display/vga.c b/qemu/hw/display/vga.c
index b35d523e6..4a55ec6db 100644
--- a/qemu/hw/display/vga.c
+++ b/qemu/hw/display/vga.c
@@ -21,6 +21,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/hw.h"
#include "vga.h"
#include "ui/console.h"
@@ -140,6 +142,13 @@ static uint32_t expand4[256];
static uint16_t expand2[256];
static uint8_t expand4to8[16];
+static void vbe_update_vgaregs(VGACommonState *s);
+
+static inline bool vbe_enabled(VGACommonState *s)
+{
+ return s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED;
+}
+
static void vga_update_memory_access(VGACommonState *s)
{
hwaddr base, offset, size;
@@ -177,6 +186,7 @@ static void vga_update_memory_access(VGACommonState *s)
size = 0x8000;
break;
}
+ assert(offset + size <= s->vram_size);
memory_region_init_alias(&s->chain4_alias, memory_region_owner(&s->vram),
"vga.chain4", &s->vram, offset, size);
memory_region_add_subregion_overlap(s->legacy_address_space, base,
@@ -234,9 +244,9 @@ static void vga_precise_update_retrace_info(VGACommonState *s)
r->total_chars = vtotal_lines * htotal_chars;
if (r->freq) {
- r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
+ r->ticks_per_char = NANOSECONDS_PER_SECOND / (r->total_chars * r->freq);
} else {
- r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
+ r->ticks_per_char = NANOSECONDS_PER_SECOND / chars_per_sec;
}
r->vstart = vretr_start_line;
@@ -264,7 +274,7 @@ static void vga_precise_update_retrace_info(VGACommonState *s)
"dots = %d\n"
"ticks/char = %" PRId64 "\n"
"\n",
- (double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
+ (double) NANOSECONDS_PER_SECOND / (r->ticks_per_char * r->total_chars),
htotal_chars,
hretr_start_char,
hretr_skew_chars,
@@ -476,6 +486,7 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
#endif
s->sr[s->sr_index] = val & sr_mask[s->sr_index];
+ vbe_update_vgaregs(s);
if (s->sr_index == VGA_SEQ_CLOCK_MODE) {
s->update_retrace_info(s);
}
@@ -507,6 +518,7 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
#endif
s->gr[s->gr_index] = val & gr_mask[s->gr_index];
+ vbe_update_vgaregs(s);
vga_update_memory_access(s);
break;
case VGA_CRT_IM:
@@ -525,10 +537,12 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
if (s->cr_index == VGA_CRTC_OVERFLOW) {
s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) |
(val & 0x10);
+ vbe_update_vgaregs(s);
}
return;
}
s->cr[s->cr_index] = val;
+ vbe_update_vgaregs(s);
switch(s->cr_index) {
case VGA_CRTC_H_TOTAL:
@@ -561,7 +575,7 @@ static void vbe_fixup_regs(VGACommonState *s)
uint16_t *r = s->vbe_regs;
uint32_t bits, linelength, maxy, offset;
- if (!(r[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
+ if (!vbe_enabled(s)) {
/* vbe is turned off -- nothing to do */
return;
}
@@ -636,6 +650,49 @@ static void vbe_fixup_regs(VGACommonState *s)
s->vbe_start_addr = offset / 4;
}
+/* we initialize the VGA graphic mode */
+static void vbe_update_vgaregs(VGACommonState *s)
+{
+ int h, shift_control;
+
+ if (!vbe_enabled(s)) {
+ /* vbe is turned off -- nothing to do */
+ return;
+ }
+
+ /* graphic mode + memory map 1 */
+ s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
+ VGA_GR06_GRAPHICS_MODE;
+ s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */
+ s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
+ /* width */
+ s->cr[VGA_CRTC_H_DISP] =
+ (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
+ /* height (only meaningful if < 1024) */
+ h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
+ s->cr[VGA_CRTC_V_DISP_END] = h;
+ s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
+ ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
+ /* line compare to 1023 */
+ s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
+ s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
+ s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
+
+ if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
+ shift_control = 0;
+ s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
+ } else {
+ shift_control = 2;
+ /* set chain 4 mode */
+ s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
+ /* activate all planes */
+ s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
+ }
+ s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
+ (shift_control << 5);
+ s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
+}
+
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
{
VGACommonState *s = opaque;
@@ -712,13 +769,10 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
case VBE_DISPI_INDEX_Y_OFFSET:
s->vbe_regs[s->vbe_index] = val;
vbe_fixup_regs(s);
+ vbe_update_vgaregs(s);
break;
case VBE_DISPI_INDEX_BANK:
- if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
- val &= (s->vbe_bank_mask >> 2);
- } else {
- val &= s->vbe_bank_mask;
- }
+ val &= s->vbe_bank_mask;
s->vbe_regs[s->vbe_index] = val;
s->bank_offset = (val << 16);
vga_update_memory_access(s);
@@ -726,52 +780,19 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
case VBE_DISPI_INDEX_ENABLE:
if ((val & VBE_DISPI_ENABLED) &&
!(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
- int h, shift_control;
s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 0;
s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
s->vbe_regs[VBE_DISPI_INDEX_ENABLE] |= VBE_DISPI_ENABLED;
vbe_fixup_regs(s);
+ vbe_update_vgaregs(s);
/* clear the screen */
if (!(val & VBE_DISPI_NOCLEARMEM)) {
memset(s->vram_ptr, 0,
s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
}
-
- /* we initialize the VGA graphic mode */
- /* graphic mode + memory map 1 */
- s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
- VGA_GR06_GRAPHICS_MODE;
- s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */
- s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
- /* width */
- s->cr[VGA_CRTC_H_DISP] =
- (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
- /* height (only meaningful if < 1024) */
- h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
- s->cr[VGA_CRTC_V_DISP_END] = h;
- s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
- ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
- /* line compare to 1023 */
- s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
- s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
- s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
-
- if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
- shift_control = 0;
- s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
- } else {
- shift_control = 2;
- /* set chain 4 mode */
- s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
- /* activate all planes */
- s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
- }
- s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
- (shift_control << 5);
- s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
} else {
s->bank_offset = 0;
}
@@ -817,13 +838,21 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)
if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
/* chain 4 mode : simplest access */
+ assert(addr < s->vram_size);
ret = s->vram_ptr[addr];
} else if (s->gr[VGA_GFX_MODE] & 0x10) {
/* odd/even mode (aka text mode mapping) */
plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
- ret = s->vram_ptr[((addr & ~1) << 1) | plane];
+ addr = ((addr & ~1) << 1) | plane;
+ if (addr >= s->vram_size) {
+ return 0xff;
+ }
+ ret = s->vram_ptr[addr];
} else {
/* standard VGA latched access */
+ if (addr * sizeof(uint32_t) >= s->vram_size) {
+ return 0xff;
+ }
s->latch = ((uint32_t *)s->vram_ptr)[addr];
if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
@@ -880,6 +909,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
plane = addr & 3;
mask = (1 << plane);
if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
+ assert(addr < s->vram_size);
s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM
printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
@@ -893,6 +923,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
mask = (1 << plane);
if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
addr = ((addr & ~1) << 1) | plane;
+ if (addr >= s->vram_size) {
+ return;
+ }
s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM
printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
@@ -966,6 +999,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
mask = s->sr[VGA_SEQ_PLANE_WRITE];
s->plane_updated |= mask; /* only used to detect font change */
write_mask = mask16[mask];
+ if (addr * sizeof(uint32_t) >= s->vram_size) {
+ return;
+ }
((uint32_t *)s->vram_ptr)[addr] =
(((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
(val & write_mask);
@@ -1044,7 +1080,7 @@ static void vga_get_offsets(VGACommonState *s,
{
uint32_t start_addr, line_offset, line_compare;
- if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
+ if (vbe_enabled(s)) {
line_offset = s->vbe_line_offset;
start_addr = s->vbe_start_addr;
line_compare = 65535;
@@ -1369,7 +1405,7 @@ static int vga_get_bpp(VGACommonState *s)
{
int ret;
- if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
+ if (vbe_enabled(s)) {
ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
} else {
ret = 0;
@@ -1381,7 +1417,7 @@ static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
{
int width, height;
- if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
+ if (vbe_enabled(s)) {
width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
} else {
@@ -1979,7 +2015,8 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
width = (s->last_width - size) / 2;
dst = chardata + s->last_width + width;
for (i = 0; i < size; i ++)
- console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
+ console_write_ch(dst ++, ATTR2CHTYPE(msg_buffer[i], QEMU_COLOR_BLUE,
+ QEMU_COLOR_BLACK, 1));
dpy_text_update(s->con, 0, 0, s->last_width, height);
}
@@ -2139,7 +2176,7 @@ void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate)
s->is_vbe_vmstate = 1;
memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size,
- &error_abort);
+ &error_fatal);
vmstate_register_ram(&s->vram, global_vmstate ? NULL : DEVICE(obj));
xen_register_framebuffer(&s->vram);
s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
diff --git a/qemu/hw/display/vga_int.h b/qemu/hw/display/vga_int.h
index 40ba6a420..bdb43a5a3 100644
--- a/qemu/hw/display/vga_int.h
+++ b/qemu/hw/display/vga_int.h
@@ -25,7 +25,6 @@
#define HW_VGA_INT_H 1
#include <hw/hw.h>
-#include "qapi/error.h"
#include "exec/memory.h"
#define ST01_V_RETRACE 0x08
diff --git a/qemu/hw/display/virtio-gpu-3d.c b/qemu/hw/display/virtio-gpu-3d.c
new file mode 100644
index 000000000..fa192946a
--- /dev/null
+++ b/qemu/hw/display/virtio-gpu-3d.c
@@ -0,0 +1,606 @@
+/*
+ * Virtio GPU Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ * Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/iov.h"
+#include "trace.h"
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-gpu.h"
+
+#ifdef CONFIG_VIRGL
+
+#include "virglrenderer.h"
+
+static struct virgl_renderer_callbacks virtio_gpu_3d_cbs;
+
+static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_resource_create_2d c2d;
+ struct virgl_renderer_resource_create_args args;
+
+ VIRTIO_GPU_FILL_CMD(c2d);
+ trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
+ c2d.width, c2d.height);
+
+ args.handle = c2d.resource_id;
+ args.target = 2;
+ args.format = c2d.format;
+ args.bind = (1 << 1);
+ args.width = c2d.width;
+ args.height = c2d.height;
+ args.depth = 1;
+ args.array_size = 1;
+ args.last_level = 0;
+ args.nr_samples = 0;
+ args.flags = VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP;
+ virgl_renderer_resource_create(&args, NULL, 0);
+}
+
+static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_resource_create_3d c3d;
+ struct virgl_renderer_resource_create_args args;
+
+ VIRTIO_GPU_FILL_CMD(c3d);
+ trace_virtio_gpu_cmd_res_create_3d(c3d.resource_id, c3d.format,
+ c3d.width, c3d.height, c3d.depth);
+
+ args.handle = c3d.resource_id;
+ args.target = c3d.target;
+ args.format = c3d.format;
+ args.bind = c3d.bind;
+ args.width = c3d.width;
+ args.height = c3d.height;
+ args.depth = c3d.depth;
+ args.array_size = c3d.array_size;
+ args.last_level = c3d.last_level;
+ args.nr_samples = c3d.nr_samples;
+ args.flags = c3d.flags;
+ virgl_renderer_resource_create(&args, NULL, 0);
+}
+
+static void virgl_cmd_resource_unref(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_resource_unref unref;
+
+ VIRTIO_GPU_FILL_CMD(unref);
+ trace_virtio_gpu_cmd_res_unref(unref.resource_id);
+
+ virgl_renderer_resource_unref(unref.resource_id);
+}
+
+static void virgl_cmd_context_create(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_ctx_create cc;
+
+ VIRTIO_GPU_FILL_CMD(cc);
+ trace_virtio_gpu_cmd_ctx_create(cc.hdr.ctx_id,
+ cc.debug_name);
+
+ virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen,
+ cc.debug_name);
+}
+
+static void virgl_cmd_context_destroy(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_ctx_destroy cd;
+
+ VIRTIO_GPU_FILL_CMD(cd);
+ trace_virtio_gpu_cmd_ctx_destroy(cd.hdr.ctx_id);
+
+ virgl_renderer_context_destroy(cd.hdr.ctx_id);
+}
+
+static void virtio_gpu_rect_update(VirtIOGPU *g, int idx, int x, int y,
+ int width, int height)
+{
+ if (!g->scanout[idx].con) {
+ return;
+ }
+
+ dpy_gl_update(g->scanout[idx].con, x, y, width, height);
+}
+
+static void virgl_cmd_resource_flush(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_resource_flush rf;
+ int i;
+
+ VIRTIO_GPU_FILL_CMD(rf);
+ trace_virtio_gpu_cmd_res_flush(rf.resource_id,
+ rf.r.width, rf.r.height, rf.r.x, rf.r.y);
+
+ for (i = 0; i < VIRTIO_GPU_MAX_SCANOUT; i++) {
+ if (g->scanout[i].resource_id != rf.resource_id) {
+ continue;
+ }
+ virtio_gpu_rect_update(g, i, rf.r.x, rf.r.y, rf.r.width, rf.r.height);
+ }
+}
+
+static void virgl_cmd_set_scanout(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_set_scanout ss;
+ struct virgl_renderer_resource_info info;
+ int ret;
+
+ VIRTIO_GPU_FILL_CMD(ss);
+ trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id,
+ ss.r.width, ss.r.height, ss.r.x, ss.r.y);
+
+ if (ss.scanout_id >= VIRTIO_GPU_MAX_SCANOUT) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
+ __func__, ss.scanout_id);
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+ return;
+ }
+ g->enable = 1;
+
+ memset(&info, 0, sizeof(info));
+
+ if (ss.resource_id && ss.r.width && ss.r.height) {
+ ret = virgl_renderer_resource_get_info(ss.resource_id, &info);
+ if (ret == -1) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: illegal resource specified %d\n",
+ __func__, ss.resource_id);
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+ return;
+ }
+ qemu_console_resize(g->scanout[ss.scanout_id].con,
+ ss.r.width, ss.r.height);
+ virgl_renderer_force_ctx_0();
+ dpy_gl_scanout(g->scanout[ss.scanout_id].con, info.tex_id,
+ info.flags & 1 /* FIXME: Y_0_TOP */,
+ ss.r.x, ss.r.y, ss.r.width, ss.r.height);
+ } else {
+ if (ss.scanout_id != 0) {
+ dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, NULL);
+ }
+ dpy_gl_scanout(g->scanout[ss.scanout_id].con, 0, false,
+ 0, 0, 0, 0);
+ }
+ g->scanout[ss.scanout_id].resource_id = ss.resource_id;
+}
+
+static void virgl_cmd_submit_3d(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_cmd_submit cs;
+ void *buf;
+ size_t s;
+
+ VIRTIO_GPU_FILL_CMD(cs);
+ trace_virtio_gpu_cmd_ctx_submit(cs.hdr.ctx_id, cs.size);
+
+ buf = g_malloc(cs.size);
+ s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
+ sizeof(cs), buf, cs.size);
+ if (s != cs.size) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: size mismatch (%zd/%d)",
+ __func__, s, cs.size);
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ if (virtio_gpu_stats_enabled(g->conf)) {
+ g->stats.req_3d++;
+ g->stats.bytes_3d += cs.size;
+ }
+
+ virgl_renderer_submit_cmd(buf, cs.hdr.ctx_id, cs.size / 4);
+
+out:
+ g_free(buf);
+}
+
+static void virgl_cmd_transfer_to_host_2d(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_transfer_to_host_2d t2d;
+ struct virtio_gpu_box box;
+
+ VIRTIO_GPU_FILL_CMD(t2d);
+ trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id);
+
+ box.x = t2d.r.x;
+ box.y = t2d.r.y;
+ box.z = 0;
+ box.w = t2d.r.width;
+ box.h = t2d.r.height;
+ box.d = 1;
+
+ virgl_renderer_transfer_write_iov(t2d.resource_id,
+ 0,
+ 0,
+ 0,
+ 0,
+ (struct virgl_box *)&box,
+ t2d.offset, NULL, 0);
+}
+
+static void virgl_cmd_transfer_to_host_3d(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_transfer_host_3d t3d;
+
+ VIRTIO_GPU_FILL_CMD(t3d);
+ trace_virtio_gpu_cmd_res_xfer_toh_3d(t3d.resource_id);
+
+ virgl_renderer_transfer_write_iov(t3d.resource_id,
+ t3d.hdr.ctx_id,
+ t3d.level,
+ t3d.stride,
+ t3d.layer_stride,
+ (struct virgl_box *)&t3d.box,
+ t3d.offset, NULL, 0);
+}
+
+static void
+virgl_cmd_transfer_from_host_3d(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_transfer_host_3d tf3d;
+
+ VIRTIO_GPU_FILL_CMD(tf3d);
+ trace_virtio_gpu_cmd_res_xfer_fromh_3d(tf3d.resource_id);
+
+ virgl_renderer_transfer_read_iov(tf3d.resource_id,
+ tf3d.hdr.ctx_id,
+ tf3d.level,
+ tf3d.stride,
+ tf3d.layer_stride,
+ (struct virgl_box *)&tf3d.box,
+ tf3d.offset, NULL, 0);
+}
+
+
+static void virgl_resource_attach_backing(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_resource_attach_backing att_rb;
+ struct iovec *res_iovs;
+ int ret;
+
+ VIRTIO_GPU_FILL_CMD(att_rb);
+ trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id);
+
+ ret = virtio_gpu_create_mapping_iov(&att_rb, cmd, &res_iovs);
+ if (ret != 0) {
+ cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+ return;
+ }
+
+ virgl_renderer_resource_attach_iov(att_rb.resource_id,
+ res_iovs, att_rb.nr_entries);
+}
+
+static void virgl_resource_detach_backing(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_resource_detach_backing detach_rb;
+ struct iovec *res_iovs = NULL;
+ int num_iovs = 0;
+
+ VIRTIO_GPU_FILL_CMD(detach_rb);
+ trace_virtio_gpu_cmd_res_back_detach(detach_rb.resource_id);
+
+ virgl_renderer_resource_detach_iov(detach_rb.resource_id,
+ &res_iovs,
+ &num_iovs);
+ if (res_iovs == NULL || num_iovs == 0) {
+ return;
+ }
+ virtio_gpu_cleanup_mapping_iov(res_iovs, num_iovs);
+}
+
+
+static void virgl_cmd_ctx_attach_resource(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_ctx_resource att_res;
+
+ VIRTIO_GPU_FILL_CMD(att_res);
+ trace_virtio_gpu_cmd_ctx_res_attach(att_res.hdr.ctx_id,
+ att_res.resource_id);
+
+ virgl_renderer_ctx_attach_resource(att_res.hdr.ctx_id, att_res.resource_id);
+}
+
+static void virgl_cmd_ctx_detach_resource(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_ctx_resource det_res;
+
+ VIRTIO_GPU_FILL_CMD(det_res);
+ trace_virtio_gpu_cmd_ctx_res_detach(det_res.hdr.ctx_id,
+ det_res.resource_id);
+
+ virgl_renderer_ctx_detach_resource(det_res.hdr.ctx_id, det_res.resource_id);
+}
+
+static void virgl_cmd_get_capset_info(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_get_capset_info info;
+ struct virtio_gpu_resp_capset_info resp;
+
+ VIRTIO_GPU_FILL_CMD(info);
+
+ if (info.capset_index == 0) {
+ resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
+ virgl_renderer_get_cap_set(resp.capset_id,
+ &resp.capset_max_version,
+ &resp.capset_max_size);
+ } else {
+ resp.capset_max_version = 0;
+ resp.capset_max_size = 0;
+ }
+ resp.hdr.type = VIRTIO_GPU_RESP_OK_CAPSET_INFO;
+ virtio_gpu_ctrl_response(g, cmd, &resp.hdr, sizeof(resp));
+}
+
+static void virgl_cmd_get_capset(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_get_capset gc;
+ struct virtio_gpu_resp_capset *resp;
+ uint32_t max_ver, max_size;
+ VIRTIO_GPU_FILL_CMD(gc);
+
+ virgl_renderer_get_cap_set(gc.capset_id, &max_ver,
+ &max_size);
+ resp = g_malloc(sizeof(*resp) + max_size);
+
+ resp->hdr.type = VIRTIO_GPU_RESP_OK_CAPSET;
+ virgl_renderer_fill_caps(gc.capset_id,
+ gc.capset_version,
+ (void *)resp->capset_data);
+ virtio_gpu_ctrl_response(g, cmd, &resp->hdr, sizeof(*resp) + max_size);
+ g_free(resp);
+}
+
+void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr);
+
+ cmd->waiting = g->renderer_blocked;
+ if (cmd->waiting) {
+ return;
+ }
+
+ virgl_renderer_force_ctx_0();
+ switch (cmd->cmd_hdr.type) {
+ case VIRTIO_GPU_CMD_CTX_CREATE:
+ virgl_cmd_context_create(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_CTX_DESTROY:
+ virgl_cmd_context_destroy(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D:
+ virgl_cmd_create_resource_2d(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_RESOURCE_CREATE_3D:
+ virgl_cmd_create_resource_3d(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_SUBMIT_3D:
+ virgl_cmd_submit_3d(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D:
+ virgl_cmd_transfer_to_host_2d(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D:
+ virgl_cmd_transfer_to_host_3d(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D:
+ virgl_cmd_transfer_from_host_3d(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING:
+ virgl_resource_attach_backing(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING:
+ virgl_resource_detach_backing(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_SET_SCANOUT:
+ virgl_cmd_set_scanout(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_RESOURCE_FLUSH:
+ virgl_cmd_resource_flush(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_RESOURCE_UNREF:
+ virgl_cmd_resource_unref(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE:
+ /* TODO add security */
+ virgl_cmd_ctx_attach_resource(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE:
+ /* TODO add security */
+ virgl_cmd_ctx_detach_resource(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_GET_CAPSET_INFO:
+ virgl_cmd_get_capset_info(g, cmd);
+ break;
+ case VIRTIO_GPU_CMD_GET_CAPSET:
+ virgl_cmd_get_capset(g, cmd);
+ break;
+
+ case VIRTIO_GPU_CMD_GET_DISPLAY_INFO:
+ virtio_gpu_get_display_info(g, cmd);
+ break;
+ default:
+ cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+ break;
+ }
+
+ if (cmd->finished) {
+ return;
+ }
+ if (cmd->error) {
+ fprintf(stderr, "%s: ctrl 0x%x, error 0x%x\n", __func__,
+ cmd->cmd_hdr.type, cmd->error);
+ virtio_gpu_ctrl_response_nodata(g, cmd, cmd->error);
+ return;
+ }
+ if (!(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) {
+ virtio_gpu_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA);
+ return;
+ }
+
+ trace_virtio_gpu_fence_ctrl(cmd->cmd_hdr.fence_id, cmd->cmd_hdr.type);
+ virgl_renderer_create_fence(cmd->cmd_hdr.fence_id, cmd->cmd_hdr.type);
+}
+
+static void virgl_write_fence(void *opaque, uint32_t fence)
+{
+ VirtIOGPU *g = opaque;
+ struct virtio_gpu_ctrl_command *cmd, *tmp;
+
+ QTAILQ_FOREACH_SAFE(cmd, &g->fenceq, next, tmp) {
+ /*
+ * the guest can end up emitting fences out of order
+ * so we should check all fenced cmds not just the first one.
+ */
+ if (cmd->cmd_hdr.fence_id > fence) {
+ continue;
+ }
+ trace_virtio_gpu_fence_resp(cmd->cmd_hdr.fence_id);
+ virtio_gpu_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA);
+ QTAILQ_REMOVE(&g->fenceq, cmd, next);
+ g_free(cmd);
+ g->inflight--;
+ if (virtio_gpu_stats_enabled(g->conf)) {
+ fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
+ }
+ }
+}
+
+static virgl_renderer_gl_context
+virgl_create_context(void *opaque, int scanout_idx,
+ struct virgl_renderer_gl_ctx_param *params)
+{
+ VirtIOGPU *g = opaque;
+ QEMUGLContext ctx;
+ QEMUGLParams qparams;
+
+ qparams.major_ver = params->major_ver;
+ qparams.minor_ver = params->minor_ver;
+
+ ctx = dpy_gl_ctx_create(g->scanout[scanout_idx].con, &qparams);
+ return (virgl_renderer_gl_context)ctx;
+}
+
+static void virgl_destroy_context(void *opaque, virgl_renderer_gl_context ctx)
+{
+ VirtIOGPU *g = opaque;
+ QEMUGLContext qctx = (QEMUGLContext)ctx;
+
+ dpy_gl_ctx_destroy(g->scanout[0].con, qctx);
+}
+
+static int virgl_make_context_current(void *opaque, int scanout_idx,
+ virgl_renderer_gl_context ctx)
+{
+ VirtIOGPU *g = opaque;
+ QEMUGLContext qctx = (QEMUGLContext)ctx;
+
+ return dpy_gl_ctx_make_current(g->scanout[scanout_idx].con, qctx);
+}
+
+static struct virgl_renderer_callbacks virtio_gpu_3d_cbs = {
+ .version = 1,
+ .write_fence = virgl_write_fence,
+ .create_gl_context = virgl_create_context,
+ .destroy_gl_context = virgl_destroy_context,
+ .make_current = virgl_make_context_current,
+};
+
+static void virtio_gpu_print_stats(void *opaque)
+{
+ VirtIOGPU *g = opaque;
+
+ if (g->stats.requests) {
+ fprintf(stderr, "stats: vq req %4d, %3d -- 3D %4d (%5d)\n",
+ g->stats.requests,
+ g->stats.max_inflight,
+ g->stats.req_3d,
+ g->stats.bytes_3d);
+ g->stats.requests = 0;
+ g->stats.max_inflight = 0;
+ g->stats.req_3d = 0;
+ g->stats.bytes_3d = 0;
+ } else {
+ fprintf(stderr, "stats: idle\r");
+ }
+ timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
+}
+
+static void virtio_gpu_fence_poll(void *opaque)
+{
+ VirtIOGPU *g = opaque;
+
+ virgl_renderer_poll();
+ virtio_gpu_process_cmdq(g);
+ if (!QTAILQ_EMPTY(&g->cmdq) || !QTAILQ_EMPTY(&g->fenceq)) {
+ timer_mod(g->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
+ }
+}
+
+void virtio_gpu_virgl_fence_poll(VirtIOGPU *g)
+{
+ virtio_gpu_fence_poll(g);
+}
+
+void virtio_gpu_virgl_reset(VirtIOGPU *g)
+{
+ int i;
+
+ /* virgl_renderer_reset() ??? */
+ for (i = 0; i < g->conf.max_outputs; i++) {
+ if (i != 0) {
+ dpy_gfx_replace_surface(g->scanout[i].con, NULL);
+ }
+ dpy_gl_scanout(g->scanout[i].con, 0, false, 0, 0, 0, 0);
+ }
+}
+
+int virtio_gpu_virgl_init(VirtIOGPU *g)
+{
+ int ret;
+
+ ret = virgl_renderer_init(g, 0, &virtio_gpu_3d_cbs);
+ if (ret != 0) {
+ return ret;
+ }
+
+ g->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+ virtio_gpu_fence_poll, g);
+
+ if (virtio_gpu_stats_enabled(g->conf)) {
+ g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+ virtio_gpu_print_stats, g);
+ timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
+ }
+ return 0;
+}
+
+#endif /* CONFIG_VIRGL */
diff --git a/qemu/hw/display/virtio-gpu-pci.c b/qemu/hw/display/virtio-gpu-pci.c
index 5bc62cf34..a71b230d3 100644
--- a/qemu/hw/display/virtio-gpu-pci.c
+++ b/qemu/hw/display/virtio-gpu-pci.c
@@ -6,10 +6,11 @@
* Authors:
* Dave Airlie
*
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
*
*/
+#include "qemu/osdep.h"
#include "hw/pci/pci.h"
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-bus.h"
diff --git a/qemu/hw/display/virtio-gpu.c b/qemu/hw/display/virtio-gpu.c
index a67d927f5..c181fb364 100644
--- a/qemu/hw/display/virtio-gpu.c
+++ b/qemu/hw/display/virtio-gpu.c
@@ -7,10 +7,11 @@
* Dave Airlie <airlied@redhat.com>
* Gerd Hoffmann <kraxel@redhat.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2.
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/iov.h"
#include "ui/console.h"
@@ -22,6 +23,23 @@
static struct virtio_gpu_simple_resource*
virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
+#ifdef CONFIG_VIRGL
+#include "virglrenderer.h"
+#define VIRGL(_g, _virgl, _simple, ...) \
+ do { \
+ if (_g->use_virgl_renderer) { \
+ _virgl(__VA_ARGS__); \
+ } else { \
+ _simple(__VA_ARGS__); \
+ } \
+ } while (0)
+#else
+#define VIRGL(_g, _virgl, _simple, ...) \
+ do { \
+ _simple(__VA_ARGS__); \
+ } while (0)
+#endif
+
static void update_cursor_data_simple(VirtIOGPU *g,
struct virtio_gpu_scanout *s,
uint32_t resource_id)
@@ -45,16 +63,49 @@ static void update_cursor_data_simple(VirtIOGPU *g,
pixels * sizeof(uint32_t));
}
+#ifdef CONFIG_VIRGL
+
+static void update_cursor_data_virgl(VirtIOGPU *g,
+ struct virtio_gpu_scanout *s,
+ uint32_t resource_id)
+{
+ uint32_t width, height;
+ uint32_t pixels, *data;
+
+ data = virgl_renderer_get_cursor_data(resource_id, &width, &height);
+ if (!data) {
+ return;
+ }
+
+ if (width != s->current_cursor->width ||
+ height != s->current_cursor->height) {
+ return;
+ }
+
+ pixels = s->current_cursor->width * s->current_cursor->height;
+ memcpy(s->current_cursor->data, data, pixels * sizeof(uint32_t));
+ free(data);
+}
+
+#endif
+
static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
{
struct virtio_gpu_scanout *s;
+ bool move = cursor->hdr.type != VIRTIO_GPU_CMD_MOVE_CURSOR;
if (cursor->pos.scanout_id >= g->conf.max_outputs) {
return;
}
s = &g->scanout[cursor->pos.scanout_id];
- if (cursor->hdr.type != VIRTIO_GPU_CMD_MOVE_CURSOR) {
+ trace_virtio_gpu_update_cursor(cursor->pos.scanout_id,
+ cursor->pos.x,
+ cursor->pos.y,
+ move ? "move" : "update",
+ cursor->resource_id);
+
+ if (move) {
if (!s->current_cursor) {
s->current_cursor = cursor_alloc(64, 64);
}
@@ -63,7 +114,8 @@ static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
s->current_cursor->hot_y = cursor->hot_y;
if (cursor->resource_id > 0) {
- update_cursor_data_simple(g, s, cursor->resource_id);
+ VIRGL(g, update_cursor_data_virgl, update_cursor_data_simple,
+ g, s, cursor->resource_id);
}
dpy_cursor_define(s->con, s->current_cursor);
}
@@ -92,9 +144,23 @@ static void virtio_gpu_set_config(VirtIODevice *vdev, const uint8_t *config)
static uint64_t virtio_gpu_get_features(VirtIODevice *vdev, uint64_t features,
Error **errp)
{
+ VirtIOGPU *g = VIRTIO_GPU(vdev);
+
+ if (virtio_gpu_virgl_enabled(g->conf)) {
+ features |= (1 << VIRTIO_GPU_F_VIRGL);
+ }
return features;
}
+static void virtio_gpu_set_features(VirtIODevice *vdev, uint64_t features)
+{
+ static const uint32_t virgl = (1 << VIRTIO_GPU_F_VIRGL);
+ VirtIOGPU *g = VIRTIO_GPU(vdev);
+
+ g->use_virgl_renderer = ((features & virgl) == virgl);
+ trace_virtio_gpu_features(g->use_virgl_renderer);
+}
+
static void virtio_gpu_notify_event(VirtIOGPU *g, uint32_t event_type)
{
g->virtio_config.events_read |= event_type;
@@ -506,10 +572,7 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
scanout->width != ss.r.width ||
scanout->height != ss.r.height) {
/* realloc the surface ptr */
- scanout->ds = qemu_create_displaysurface_from
- (ss.r.width, ss.r.height, format,
- pixman_image_get_stride(res->image),
- (uint8_t *)pixman_image_get_data(res->image) + offset);
+ scanout->ds = qemu_create_displaysurface_pixman(res->image);
if (!scanout->ds) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
@@ -563,7 +626,6 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
__func__, ab->resource_id, i);
virtio_gpu_cleanup_mapping_iov(*iov, i);
g_free(ents);
- g_free(*iov);
*iov = NULL;
return -1;
}
@@ -580,12 +642,12 @@ void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count)
cpu_physical_memory_unmap(iov[i].iov_base, iov[i].iov_len, 1,
iov[i].iov_len);
}
+ g_free(iov);
}
static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res)
{
virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt);
- g_free(res->iov);
res->iov = NULL;
res->iov_cnt = 0;
}
@@ -690,6 +752,39 @@ static void virtio_gpu_handle_cursor_cb(VirtIODevice *vdev, VirtQueue *vq)
qemu_bh_schedule(g->cursor_bh);
}
+void virtio_gpu_process_cmdq(VirtIOGPU *g)
+{
+ struct virtio_gpu_ctrl_command *cmd;
+
+ while (!QTAILQ_EMPTY(&g->cmdq)) {
+ cmd = QTAILQ_FIRST(&g->cmdq);
+
+ /* process command */
+ VIRGL(g, virtio_gpu_virgl_process_cmd, virtio_gpu_simple_process_cmd,
+ g, cmd);
+ if (cmd->waiting) {
+ break;
+ }
+ QTAILQ_REMOVE(&g->cmdq, cmd, next);
+ if (virtio_gpu_stats_enabled(g->conf)) {
+ g->stats.requests++;
+ }
+
+ if (!cmd->finished) {
+ QTAILQ_INSERT_TAIL(&g->fenceq, cmd, next);
+ g->inflight++;
+ if (virtio_gpu_stats_enabled(g->conf)) {
+ if (g->stats.max_inflight < g->inflight) {
+ g->stats.max_inflight = g->inflight;
+ }
+ fprintf(stderr, "inflight: %3d (+)\r", g->inflight);
+ }
+ } else {
+ g_free(cmd);
+ }
+ }
+}
+
static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
@@ -699,25 +794,30 @@ static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
return;
}
- cmd = g_new(struct virtio_gpu_ctrl_command, 1);
- while (virtqueue_pop(vq, &cmd->elem)) {
+#ifdef CONFIG_VIRGL
+ if (!g->renderer_inited && g->use_virgl_renderer) {
+ virtio_gpu_virgl_init(g);
+ g->renderer_inited = true;
+ }
+#endif
+
+ cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
+ while (cmd) {
cmd->vq = vq;
cmd->error = 0;
cmd->finished = false;
- g->stats.requests++;
+ cmd->waiting = false;
+ QTAILQ_INSERT_TAIL(&g->cmdq, cmd, next);
+ cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
+ }
- virtio_gpu_simple_process_cmd(g, cmd);
- if (!cmd->finished) {
- QTAILQ_INSERT_TAIL(&g->fenceq, cmd, next);
- g->stats.inflight++;
- if (g->stats.max_inflight < g->stats.inflight) {
- g->stats.max_inflight = g->stats.inflight;
- }
- fprintf(stderr, "inflight: %3d (+)\r", g->stats.inflight);
- cmd = g_new(struct virtio_gpu_ctrl_command, 1);
- }
+ virtio_gpu_process_cmdq(g);
+
+#ifdef CONFIG_VIRGL
+ if (g->use_virgl_renderer) {
+ virtio_gpu_virgl_fence_poll(g);
}
- g_free(cmd);
+#endif
}
static void virtio_gpu_ctrl_bh(void *opaque)
@@ -729,15 +829,20 @@ static void virtio_gpu_ctrl_bh(void *opaque)
static void virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
- VirtQueueElement elem;
+ VirtQueueElement *elem;
size_t s;
struct virtio_gpu_update_cursor cursor_info;
if (!virtio_queue_ready(vq)) {
return;
}
- while (virtqueue_pop(vq, &elem)) {
- s = iov_to_buf(elem.out_sg, elem.out_num, 0,
+ for (;;) {
+ elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ if (!elem) {
+ break;
+ }
+
+ s = iov_to_buf(elem->out_sg, elem->out_num, 0,
&cursor_info, sizeof(cursor_info));
if (s != sizeof(cursor_info)) {
qemu_log_mask(LOG_GUEST_ERROR,
@@ -746,8 +851,9 @@ static void virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq)
} else {
update_cursor(g, &cursor_info);
}
- virtqueue_push(vq, &elem, 0);
+ virtqueue_push(vq, elem, 0);
virtio_notify(vdev, vq);
+ g_free(elem);
}
}
@@ -793,17 +899,34 @@ static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
return 0;
}
+static void virtio_gpu_gl_block(void *opaque, bool block)
+{
+ VirtIOGPU *g = opaque;
+
+ g->renderer_blocked = block;
+ if (!block) {
+ virtio_gpu_process_cmdq(g);
+ }
+}
+
const GraphicHwOps virtio_gpu_ops = {
.invalidate = virtio_gpu_invalidate_display,
.gfx_update = virtio_gpu_update_display,
.text_update = virtio_gpu_text_update,
.ui_info = virtio_gpu_ui_info,
+ .gl_block = virtio_gpu_gl_block,
+};
+
+static const VMStateDescription vmstate_virtio_gpu_unmigratable = {
+ .name = "virtio-gpu",
+ .unmigratable = 1,
};
static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
VirtIOGPU *g = VIRTIO_GPU(qdev);
+ bool have_virgl;
int i;
g->config_size = sizeof(struct virtio_gpu_config);
@@ -814,12 +937,30 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
g->req_state[0].width = 1024;
g->req_state[0].height = 768;
- g->ctrl_vq = virtio_add_queue(vdev, 64, virtio_gpu_handle_ctrl_cb);
- g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
+ g->use_virgl_renderer = false;
+#if !defined(CONFIG_VIRGL) || defined(HOST_WORDS_BIGENDIAN)
+ have_virgl = false;
+#else
+ have_virgl = display_opengl;
+#endif
+ if (!have_virgl) {
+ g->conf.flags &= ~(1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED);
+ }
+
+ if (virtio_gpu_virgl_enabled(g->conf)) {
+ /* use larger control queue in 3d mode */
+ g->ctrl_vq = virtio_add_queue(vdev, 256, virtio_gpu_handle_ctrl_cb);
+ g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
+ g->virtio_config.num_capsets = 1;
+ } else {
+ g->ctrl_vq = virtio_add_queue(vdev, 64, virtio_gpu_handle_ctrl_cb);
+ g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
+ }
g->ctrl_bh = qemu_bh_new(virtio_gpu_ctrl_bh, g);
g->cursor_bh = qemu_bh_new(virtio_gpu_cursor_bh, g);
QTAILQ_INIT(&g->reslist);
+ QTAILQ_INIT(&g->cmdq);
QTAILQ_INIT(&g->fenceq);
g->enabled_output_bitmask = 1;
@@ -832,6 +973,8 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
dpy_gfx_replace_surface(g->scanout[i].con, NULL);
}
}
+
+ vmstate_register(qdev, -1, &vmstate_virtio_gpu_unmigratable, g);
}
static void virtio_gpu_instance_init(Object *obj)
@@ -869,10 +1012,23 @@ static void virtio_gpu_reset(VirtIODevice *vdev)
g->scanout[i].ds = NULL;
}
g->enabled_output_bitmask = 1;
+
+#ifdef CONFIG_VIRGL
+ if (g->use_virgl_renderer) {
+ virtio_gpu_virgl_reset(g);
+ g->use_virgl_renderer = 0;
+ }
+#endif
}
static Property virtio_gpu_properties[] = {
DEFINE_PROP_UINT32("max_outputs", VirtIOGPU, conf.max_outputs, 1),
+#ifdef CONFIG_VIRGL
+ DEFINE_PROP_BIT("virgl", VirtIOGPU, conf.flags,
+ VIRTIO_GPU_FLAG_VIRGL_ENABLED, true),
+ DEFINE_PROP_BIT("stats", VirtIOGPU, conf.flags,
+ VIRTIO_GPU_FLAG_STATS_ENABLED, false),
+#endif
DEFINE_PROP_END_OF_LIST(),
};
@@ -885,6 +1041,7 @@ static void virtio_gpu_class_init(ObjectClass *klass, void *data)
vdc->get_config = virtio_gpu_get_config;
vdc->set_config = virtio_gpu_set_config;
vdc->get_features = virtio_gpu_get_features;
+ vdc->set_features = virtio_gpu_set_features;
vdc->reset = virtio_gpu_reset;
@@ -917,3 +1074,14 @@ QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_mem_entry) != 16);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_attach_backing) != 32);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_detach_backing) != 32);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_display_info) != 408);
+
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_host_3d) != 72);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_3d) != 72);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_create) != 96);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_destroy) != 24);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_resource) != 32);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_cmd_submit) != 32);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset_info) != 32);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset_info) != 40);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset) != 32);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset) != 24);
diff --git a/qemu/hw/display/virtio-vga.c b/qemu/hw/display/virtio-vga.c
index f7e539fe9..e58b165ae 100644
--- a/qemu/hw/display/virtio-vga.c
+++ b/qemu/hw/display/virtio-vga.c
@@ -1,3 +1,4 @@
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/pci/pci.h"
#include "ui/console.h"
@@ -65,11 +66,21 @@ static int virtio_vga_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
return -1;
}
+static void virtio_vga_gl_block(void *opaque, bool block)
+{
+ VirtIOVGA *vvga = opaque;
+
+ if (virtio_gpu_ops.gl_block) {
+ virtio_gpu_ops.gl_block(&vvga->vdev, block);
+ }
+}
+
static const GraphicHwOps virtio_vga_ops = {
.invalidate = virtio_vga_invalidate_display,
.gfx_update = virtio_vga_update_display,
.text_update = virtio_vga_text_update,
.ui_info = virtio_vga_ui_info,
+ .gl_block = virtio_vga_gl_block,
};
/* VGA device wrapper around PCI device around virtio GPU */
diff --git a/qemu/hw/display/vmware_vga.c b/qemu/hw/display/vmware_vga.c
index 7f397d3c2..0c63fa851 100644
--- a/qemu/hw/display/vmware_vga.c
+++ b/qemu/hw/display/vmware_vga.c
@@ -21,6 +21,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/hw.h"
#include "hw/loader.h"
#include "trace.h"
@@ -488,10 +490,10 @@ static inline int vmsvga_fill_rect(struct vmsvga_state_s *s,
#endif
struct vmsvga_cursor_definition_s {
- int width;
- int height;
+ uint32_t width;
+ uint32_t height;
int id;
- int bpp;
+ uint32_t bpp;
int hot_x;
int hot_y;
uint32_t mask[1024];
@@ -658,7 +660,10 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
cursor.bpp = vmsvga_fifo_read(s);
args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp);
- if (SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask ||
+ if (cursor.width > 256 ||
+ cursor.height > 256 ||
+ cursor.bpp > 32 ||
+ SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask ||
SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) {
goto badcmd;
}
@@ -1244,7 +1249,7 @@ static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s,
s->fifo_size = SVGA_FIFO_SIZE;
memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size,
- &error_abort);
+ &error_fatal);
vmstate_register_ram_global(&s->fifo_ram);
s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
diff --git a/qemu/hw/display/xenfb.c b/qemu/hw/display/xenfb.c
index 5e324ef62..9866dfda5 100644
--- a/qemu/hw/display/xenfb.c
+++ b/qemu/hw/display/xenfb.c
@@ -24,16 +24,8 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdarg.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
+#include "qemu/osdep.h"
#include <sys/mman.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
#include "hw/hw.h"
#include "ui/console.h"
@@ -95,23 +87,24 @@ struct XenFB {
static int common_bind(struct common *c)
{
- uint64_t mfn;
+ uint64_t val;
+ xen_pfn_t mfn;
- if (xenstore_read_fe_uint64(&c->xendev, "page-ref", &mfn) == -1)
+ if (xenstore_read_fe_uint64(&c->xendev, "page-ref", &val) == -1)
return -1;
- assert(mfn == (xen_pfn_t)mfn);
+ mfn = (xen_pfn_t)val;
+ assert(val == mfn);
if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1)
return -1;
- c->page = xc_map_foreign_range(xen_xc, c->xendev.dom,
- XC_PAGE_SIZE,
- PROT_READ | PROT_WRITE, mfn);
+ c->page = xenforeignmemory_map(xen_fmem, c->xendev.dom,
+ PROT_READ | PROT_WRITE, 1, &mfn, NULL);
if (c->page == NULL)
return -1;
xen_be_bind_evtchn(&c->xendev);
- xen_be_printf(&c->xendev, 1, "ring mfn %"PRIx64", remote-port %d, local-port %d\n",
+ xen_be_printf(&c->xendev, 1, "ring mfn %"PRI_xen_pfn", remote-port %d, local-port %d\n",
mfn, c->xendev.remote_port, c->xendev.local_port);
return 0;
@@ -121,7 +114,7 @@ static void common_unbind(struct common *c)
{
xen_be_unbind_evtchn(&c->xendev);
if (c->page) {
- munmap(c->page, XC_PAGE_SIZE);
+ xenforeignmemory_unmap(xen_fmem, c->page, 1);
c->page = NULL;
}
}
@@ -248,9 +241,7 @@ static int xenfb_send_motion(struct XenInput *xenfb,
event.type = XENKBD_TYPE_MOTION;
event.motion.rel_x = rel_x;
event.motion.rel_y = rel_y;
-#if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030207
event.motion.rel_z = rel_z;
-#endif
return xenfb_kbd_event(xenfb, &event);
}
@@ -265,12 +256,7 @@ static int xenfb_send_position(struct XenInput *xenfb,
event.type = XENKBD_TYPE_POS;
event.pos.abs_x = abs_x;
event.pos.abs_y = abs_y;
-#if __XEN_LATEST_INTERFACE_VERSION__ == 0x00030207
- event.pos.abs_z = z;
-#endif
-#if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030208
event.pos.rel_z = z;
-#endif
return xenfb_kbd_event(xenfb, &event);
}
@@ -494,15 +480,15 @@ static int xenfb_map_fb(struct XenFB *xenfb)
fbmfns = g_malloc0(sizeof(xen_pfn_t) * xenfb->fbpages);
xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
- map = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
- PROT_READ, pgmfns, n_fbdirs);
+ map = xenforeignmemory_map(xen_fmem, xenfb->c.xendev.dom,
+ PROT_READ, n_fbdirs, pgmfns, NULL);
if (map == NULL)
goto out;
xenfb_copy_mfns(mode, xenfb->fbpages, fbmfns, map);
- munmap(map, n_fbdirs * XC_PAGE_SIZE);
+ xenforeignmemory_unmap(xen_fmem, map, n_fbdirs);
- xenfb->pixels = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
- PROT_READ, fbmfns, xenfb->fbpages);
+ xenfb->pixels = xenforeignmemory_map(xen_fmem, xenfb->c.xendev.dom,
+ PROT_READ, xenfb->fbpages, fbmfns, NULL);
if (xenfb->pixels == NULL)
goto out;
@@ -784,18 +770,21 @@ static void xenfb_invalidate(void *opaque)
static void xenfb_handle_events(struct XenFB *xenfb)
{
- uint32_t prod, cons;
+ uint32_t prod, cons, out_cons;
struct xenfb_page *page = xenfb->c.page;
prod = page->out_prod;
- if (prod == page->out_cons)
- return;
+ out_cons = page->out_cons;
+ if (prod - out_cons > XENFB_OUT_RING_LEN) {
+ return;
+ }
xen_rmb(); /* ensure we see ring contents up to prod */
- for (cons = page->out_cons; cons != prod; cons++) {
+ for (cons = out_cons; cons != prod; cons++) {
union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
+ uint8_t type = event->type;
int x, y, w, h;
- switch (event->type) {
+ switch (type) {
case XENFB_TYPE_UPDATE:
if (xenfb->up_count == UP_QUEUE)
xenfb->up_fullscreen = 1;
@@ -909,6 +898,7 @@ static void fb_disconnect(struct XenDevice *xendev)
* Replacing the framebuffer with anonymous shared memory
* instead. This releases the guest pages and keeps qemu happy.
*/
+ xenforeignmemory_unmap(xen_fmem, fb->pixels, fb->fbpages);
fb->pixels = mmap(fb->pixels, fb->fbpages * XC_PAGE_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON,
-1, 0);