@@ -61,6 +61,12 @@ typedef struct PCIQXLDevice {
enum qxl_mode mode;
int generation;
+ DisplaySurface *surface_native;
+ SpiceRect surface_rect;
+ uint32_t surface_id;
+ int surface_render;
+ int surface_commands;
+
/* thread signaling */
pthread_t main;
int pipe[2];
@@ -325,6 +331,7 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
if (notify) {
qxl_send_events(qxl, QXL_INTERRUPT_DISPLAY);
}
+ qxl->surface_commands++;
return true;
case QXL_MODE_UNDEFINED:
default:
@@ -433,6 +440,7 @@ static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *
if (notify) {
qxl_send_events(qxl, QXL_INTERRUPT_CURSOR);
}
+ qxl->surface_commands++;
return true;
} else {
return false;
@@ -454,6 +462,13 @@ static void interface_get_update_area(QXLInstance *sin, const struct SpiceRect *
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+ if (qxl->surface_render) {
+ qxl->surface_render = 0;
+ *rect = &qxl->surface_rect;
+ *surface_id = &qxl->surface_id;
+ return;
+ }
+
*rect = &qxl->ram->update_area;
*surface_id = &qxl->ram->update_surface;
}
@@ -711,6 +726,7 @@ static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id)
static void qxl_create_guest_primary(PCIQXLDevice *d)
{
QXLDevSurfaceCreate surface;
+ void *ptr;
assert(d->mode != QXL_MODE_NATIVE);
qxl_exit_vga_mode(d);
@@ -732,6 +748,30 @@ static void qxl_create_guest_primary(PCIQXLDevice *d)
d->mode = QXL_MODE_NATIVE;
d->ssd.worker->create_primary_surface(d->ssd.worker, 0, &surface);
+
+ fprintf(stderr, "%s: width %d height %d depth %d stride %d\n", __FUNCTION__,
+ surface.width, surface.height, surface.depth, surface.stride);
+
+ if (surface.stride < 0) {
+ /* FIXME: will display upside down */
+ surface.stride = -surface.stride;
+ }
+
+ if (d->surface_native) {
+ qemu_free(d->surface_native);
+ d->surface_native = NULL;
+ }
+
+ ptr = qemu_get_ram_ptr(d->vga.vram_offset);
+ d->surface_native =
+ qemu_create_displaysurface_from(surface.width, surface.height,
+ surface.depth, surface.stride, ptr);
+
+ d->surface_id = 0;
+ d->surface_rect.top = 0;
+ d->surface_rect.bottom = surface.height;
+ d->surface_rect.left = 0;
+ d->surface_rect.right = surface.width;
}
static void qxl_destroy_primary(PCIQXLDevice *d)
@@ -826,10 +866,16 @@ static uint32_t ioport_read(void *opaque, uint32_t addr)
static void qxl_map(PCIDevice *pci, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
+ static const char *names[] = {
+ [ QXL_IO_RANGE_INDEX ] = "ioports",
+ [ QXL_RAM_RANGE_INDEX ] = "devram",
+ [ QXL_ROM_RANGE_INDEX ] = "rom",
+ [ QXL_VRAM_RANGE_INDEX ] = "vram",
+ };
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, pci);
- dprintf(1, "%s: bar %d addr 0x%lx size 0x%lx\n", __FUNCTION__,
- region_num, addr, size);
+ dprintf(1, "%s: bar %d [%s] addr 0x%lx size 0x%lx\n", __FUNCTION__,
+ region_num, names[region_num], addr, size);
switch (region_num) {
case QXL_IO_RANGE_INDEX:
@@ -901,6 +947,67 @@ static void init_pipe_signaling(PCIQXLDevice *d)
qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
}
+/* graphics console */
+
+static void qxl_hw_update(void *opaque)
+{
+ PCIQXLDevice *qxl = opaque;
+ VGACommonState *vga = &qxl->vga;
+
+ if (qxl->mode == QXL_MODE_VGA) {
+ vga->update(vga);
+ return;
+ }
+
+ if (qxl->surface_native) {
+ qemu_free_displaysurface(vga->ds);
+ vga->ds->surface = qxl->surface_native;
+ qxl->surface_native = NULL;
+ dpy_resize(vga->ds);
+ }
+
+ if (qxl->surface_commands) {
+ qxl->surface_commands = 0;
+ qxl->surface_render = 1;
+ qxl->ssd.worker->update_area(qxl->ssd.worker);
+
+ /* FIXME: want more specific dirty region here */
+ dpy_update(vga->ds, 0, 0, ds_get_width(vga->ds), ds_get_height(vga->ds));
+ }
+}
+
+static void qxl_hw_invalidate(void *opaque)
+{
+ PCIQXLDevice *qxl = opaque;
+ VGACommonState *vga = &qxl->vga;
+
+ vga->invalidate(vga);
+}
+
+static void qxl_hw_screen_dump(void *opaque, const char *filename)
+{
+ PCIQXLDevice *qxl = opaque;
+ VGACommonState *vga = &qxl->vga;
+
+ if (qxl->mode == QXL_MODE_VGA) {
+ vga->screen_dump(vga, filename);
+ return;
+ }
+}
+
+static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
+{
+ PCIQXLDevice *qxl = opaque;
+ VGACommonState *vga = &qxl->vga;
+
+ if (qxl->mode == QXL_MODE_VGA) {
+ vga->text_update(vga, chardata);
+ return;
+ }
+}
+
+/* display change listener */
+
static void display_update(struct DisplayState *ds, int x, int y, int w, int h)
{
if (qxl0->mode == QXL_MODE_VGA) {
@@ -950,13 +1057,19 @@ static int qxl_init(PCIDevice *dev)
register_ioport_write(0x3ba, 1, 1, qxl_vga_ioport_write, vga);
register_ioport_write(0x3da, 1, 1, qxl_vga_ioport_write, vga);
- qxl0 = qxl;
+#if 0
vga->ds = graphic_console_init(vga->update, vga->invalidate,
vga->screen_dump, vga->text_update, vga);
+#else
+ vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
+ qxl_hw_screen_dump, qxl_hw_text_update, qxl);
+#endif
qxl->ssd.ds = vga->ds;
qxl->ssd.bufsize = (16 * 1024 * 1024);
qxl->ssd.buf = qemu_malloc(qxl->ssd.bufsize);
pthread_mutex_init(&qxl->ssd.lock, NULL);
+
+ qxl0 = qxl;
register_displaychangelistener(vga->ds, &display_listener);
if (qxl->pci.romfile == NULL)
@@ -1021,7 +1134,7 @@ static PCIDeviceInfo qxl_info = {
.init = qxl_init,
.config_write = qxl_write_config,
.qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 32 * 1024 * 1024),
+ DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024),
DEFINE_PROP_END_OF_LIST(),
}