Patchwork [RfC,09/11] qxl: local rendering for sdl/vnc

login
register
mail settings
Submitter Gerd Hoffmann
Date April 14, 2010, 9:55 a.m.
Message ID <1271238922-10008-10-git-send-email-kraxel@redhat.com>
Download mbox | patch
Permalink /patch/50142/
State New
Headers show

Comments

Gerd Hoffmann - April 14, 2010, 9:55 a.m.
Not fully functional yet.  Known issues:

 - if the guest creates a "top down" primary surface (windows does)
   the vns/sdl display will be upside down.
 - mouse pointer isn't rendered.
---
 hw/qxl.c |  121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 117 insertions(+), 4 deletions(-)

Patch

diff --git a/hw/qxl.c b/hw/qxl.c
index ed7e975..d69ad17 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -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(),
     }