Blame 0418-qxl-make-qxl_render_update-async.patch

Hans de Goede 56753f
From c26805e29312fee136008a57c70a2f5f140ba706 Mon Sep 17 00:00:00 2001
Hans de Goede 56753f
From: Alon Levy <alevy@redhat.com>
Hans de Goede 56753f
Date: Fri, 24 Feb 2012 23:19:31 +0200
Hans de Goede 56753f
Subject: [PATCH 418/434] qxl: make qxl_render_update async
Hans de Goede 56753f
Hans de Goede 56753f
RHBZ# 747011
Hans de Goede 56753f
Hans de Goede 56753f
Removes the last user of QXL_SYNC when using update drivers that use the
Hans de Goede 56753f
_ASYNC io ports.
Hans de Goede 56753f
Hans de Goede 56753f
The last user is qxl_render_update, it is called both by qxl_hw_update
Hans de Goede 56753f
which is the vga_hw_update_ptr passed to graphic_console_init, and by
Hans de Goede 56753f
qxl_hw_screen_dump.
Hans de Goede 56753f
Hans de Goede 56753f
At the same time the QXLRect area being passed to the red_worker thread
Hans de Goede 56753f
is passed as a copy, as part of the QXLCookie.
Hans de Goede 56753f
Hans de Goede 56753f
The implementation uses interface_update_area_complete with a bh to make
Hans de Goede 56753f
sure dpy_update and qxl_flip are called from the io thread, otherwise
Hans de Goede 56753f
the vga->ds->surface.data can change under our feet.
Hans de Goede 56753f
Hans de Goede 56753f
With this patch sdl+spice works fine. But spice by itself doesn't
Hans de Goede 56753f
produce the expected screendumps unless repeated a few times, due to
Hans de Goede 56753f
ppm_save being called before update_area (rendering done in spice server
Hans de Goede 56753f
thread) having a chance to complete. Fixed by next patch, but see commit
Hans de Goede 56753f
message for problem introduced by it.
Hans de Goede 56753f
Hans de Goede 56753f
Signed-off-by: Alon Levy <alevy@redhat.com>
Hans de Goede 56753f
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Hans de Goede 56753f
---
Hans de Goede 56753f
 hw/qxl-render.c    |   96 +++++++++++++++++++++++++++++++++++++---------------
Hans de Goede 56753f
 hw/qxl.c           |   69 ++++++++++++++++++++++++++++++++++---
Hans de Goede 56753f
 hw/qxl.h           |   10 ++++++
Hans de Goede 56753f
 ui/spice-display.h |    6 ++++
Hans de Goede 56753f
 4 files changed, 150 insertions(+), 31 deletions(-)
Hans de Goede 56753f
Hans de Goede 56753f
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
Hans de Goede 56753f
index 4c22166..4857838 100644
Hans de Goede 56753f
--- a/hw/qxl-render.c
Hans de Goede 56753f
+++ b/hw/qxl-render.c
Hans de Goede 56753f
@@ -82,17 +82,25 @@ void qxl_render_resize(PCIQXLDevice *qxl)
Hans de Goede 56753f
     }
Hans de Goede 56753f
 }
Hans de Goede 56753f
 
Hans de Goede 56753f
-void qxl_render_update(PCIQXLDevice *qxl)
Hans de Goede 56753f
+static void qxl_set_rect_to_surface(PCIQXLDevice *qxl, QXLRect *area)
Hans de Goede 56753f
+{
Hans de Goede 56753f
+    area->left   = 0;
Hans de Goede 56753f
+    area->right  = qxl->guest_primary.surface.width;
Hans de Goede 56753f
+    area->top    = 0;
Hans de Goede 56753f
+    area->bottom = qxl->guest_primary.surface.height;
Hans de Goede 56753f
+}
Hans de Goede 56753f
+
Hans de Goede 56753f
+static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
Hans de Goede 56753f
 {
Hans de Goede 56753f
     VGACommonState *vga = &qxl->vga;
Hans de Goede 56753f
-    QXLRect dirty[32], update;
Hans de Goede 56753f
-    int i, redraw = 0;
Hans de Goede 56753f
+    int i;
Hans de Goede 56753f
     DisplaySurface *surface = vga->ds->surface;
Hans de Goede 56753f
 
Hans de Goede 56753f
     if (qxl->guest_primary.resized) {
Hans de Goede 56753f
         qxl->guest_primary.resized = 0;
Hans de Goede 56753f
-
Hans de Goede 56753f
         qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
Hans de Goede 56753f
+        qxl_set_rect_to_surface(qxl, &qxl->dirty[0]);
Hans de Goede 56753f
+        qxl->num_dirty_rects = 1;
Hans de Goede 56753f
         dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d\n",
Hans de Goede 56753f
                __FUNCTION__,
Hans de Goede 56753f
                qxl->guest_primary.surface.width,
Hans de Goede 56753f
@@ -103,9 +111,9 @@ void qxl_render_update(PCIQXLDevice *qxl)
Hans de Goede 56753f
     }
Hans de Goede 56753f
     if (surface->width != qxl->guest_primary.surface.width ||
Hans de Goede 56753f
         surface->height != qxl->guest_primary.surface.height) {
Hans de Goede 56753f
-        dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
Hans de Goede 56753f
-               __func__);
Hans de Goede 56753f
         if (qxl->guest_primary.qxl_stride > 0) {
Hans de Goede 56753f
+            dprint(qxl, 1, "%s: using guest_primary for displaysurface\n",
Hans de Goede 56753f
+                   __func__);
Hans de Goede 56753f
             qemu_free_displaysurface(vga->ds);
Hans de Goede 56753f
             qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
Hans de Goede 56753f
                                             qxl->guest_primary.surface.height,
Hans de Goede 56753f
@@ -113,36 +121,70 @@ void qxl_render_update(PCIQXLDevice *qxl)
Hans de Goede 56753f
                                             qxl->guest_primary.abs_stride,
Hans de Goede 56753f
                                             qxl->guest_primary.data);
Hans de Goede 56753f
         } else {
Hans de Goede 56753f
+            dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
Hans de Goede 56753f
+                   __func__);
Hans de Goede 56753f
             qemu_resize_displaysurface(vga->ds,
Hans de Goede 56753f
                     qxl->guest_primary.surface.width,
Hans de Goede 56753f
                     qxl->guest_primary.surface.height);
Hans de Goede 56753f
         }
Hans de Goede 56753f
     }
Hans de Goede 56753f
-    update.left   = 0;
Hans de Goede 56753f
-    update.right  = qxl->guest_primary.surface.width;
Hans de Goede 56753f
-    update.top    = 0;
Hans de Goede 56753f
-    update.bottom = qxl->guest_primary.surface.height;
Hans de Goede 56753f
-
Hans de Goede 56753f
-    memset(dirty, 0, sizeof(dirty));
Hans de Goede 56753f
-    if (runstate_is_running() && qxl->guest_primary.commands) {
Hans de Goede 56753f
-        qxl->guest_primary.commands = 0;
Hans de Goede 56753f
-        qxl_spice_update_area(qxl, 0, &update,
Hans de Goede 56753f
-                              dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC, NULL);
Hans de Goede 56753f
-    }
Hans de Goede 56753f
-    if (redraw) {
Hans de Goede 56753f
-        memset(dirty, 0, sizeof(dirty));
Hans de Goede 56753f
-        dirty[0] = update;
Hans de Goede 56753f
-    }
Hans de Goede 56753f
-    for (i = 0; i < ARRAY_SIZE(dirty); i++) {
Hans de Goede 56753f
-        if (qemu_spice_rect_is_empty(dirty+i)) {
Hans de Goede 56753f
+    for (i = 0; i < qxl->num_dirty_rects; i++) {
Hans de Goede 56753f
+        if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
Hans de Goede 56753f
             break;
Hans de Goede 56753f
         }
Hans de Goede 56753f
-        qxl_flip(qxl, dirty+i);
Hans de Goede 56753f
+        qxl_flip(qxl, qxl->dirty+i);
Hans de Goede 56753f
         dpy_update(vga->ds,
Hans de Goede 56753f
-                   dirty[i].left, dirty[i].top,
Hans de Goede 56753f
-                   dirty[i].right - dirty[i].left,
Hans de Goede 56753f
-                   dirty[i].bottom - dirty[i].top);
Hans de Goede 56753f
+                   qxl->dirty[i].left, qxl->dirty[i].top,
Hans de Goede 56753f
+                   qxl->dirty[i].right - qxl->dirty[i].left,
Hans de Goede 56753f
+                   qxl->dirty[i].bottom - qxl->dirty[i].top);
Hans de Goede 56753f
+    }
Hans de Goede 56753f
+    qxl->num_dirty_rects = 0;
Hans de Goede 56753f
+}
Hans de Goede 56753f
+
Hans de Goede 56753f
+/*
Hans de Goede 56753f
+ * use ssd.lock to protect render_update_cookie_num.
Hans de Goede 56753f
+ * qxl_render_update is called by io thread or vcpu thread, and the completion
Hans de Goede 56753f
+ * callbacks are called by spice_server thread, defering to bh called from the
Hans de Goede 56753f
+ * io thread.
Hans de Goede 56753f
+ */
Hans de Goede 56753f
+void qxl_render_update(PCIQXLDevice *qxl)
Hans de Goede 56753f
+{
Hans de Goede 56753f
+    QXLCookie *cookie;
Hans de Goede 56753f
+
Hans de Goede 56753f
+    qemu_mutex_lock(&qxl->ssd.lock);
Hans de Goede 56753f
+
Hans de Goede 56753f
+    if (!runstate_is_running() || !qxl->guest_primary.commands) {
Hans de Goede 56753f
+        qxl_render_update_area_unlocked(qxl);
Hans de Goede 56753f
+        qemu_mutex_unlock(&qxl->ssd.lock);
Hans de Goede 56753f
+        return;
Hans de Goede 56753f
     }
Hans de Goede 56753f
+
Hans de Goede 56753f
+    qxl->guest_primary.commands = 0;
Hans de Goede 56753f
+    qxl->render_update_cookie_num++;
Hans de Goede 56753f
+    qemu_mutex_unlock(&qxl->ssd.lock);
Hans de Goede 56753f
+    cookie = qxl_cookie_new(QXL_COOKIE_TYPE_RENDER_UPDATE_AREA,
Hans de Goede 56753f
+                            0);
Hans de Goede 56753f
+    qxl_set_rect_to_surface(qxl, &cookie->u.render.area);
Hans de Goede 56753f
+    qxl_spice_update_area(qxl, 0, &cookie->u.render.area, NULL,
Hans de Goede 56753f
+                          0, 1 /* clear_dirty_region */, QXL_ASYNC, cookie);
Hans de Goede 56753f
+}
Hans de Goede 56753f
+
Hans de Goede 56753f
+void qxl_render_update_area_bh(void *opaque)
Hans de Goede 56753f
+{
Hans de Goede 56753f
+    PCIQXLDevice *qxl = opaque;
Hans de Goede 56753f
+
Hans de Goede 56753f
+    qemu_mutex_lock(&qxl->ssd.lock);
Hans de Goede 56753f
+    qxl_render_update_area_unlocked(qxl);
Hans de Goede 56753f
+    qemu_mutex_unlock(&qxl->ssd.lock);
Hans de Goede 56753f
+}
Hans de Goede 56753f
+
Hans de Goede 56753f
+void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie)
Hans de Goede 56753f
+{
Hans de Goede 56753f
+    qemu_mutex_lock(&qxl->ssd.lock);
Hans de Goede 56753f
+    qemu_bh_schedule(qxl->update_area_bh);
Hans de Goede 56753f
+    qxl->render_update_cookie_num--;
Hans de Goede 56753f
+    qemu_mutex_unlock(&qxl->ssd.lock);
Hans de Goede 56753f
+    g_free(cookie);
Hans de Goede 56753f
 }
Hans de Goede 56753f
 
Hans de Goede 56753f
 static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor)
Hans de Goede 56753f
diff --git a/hw/qxl.c b/hw/qxl.c
Hans de Goede 56753f
index e6e65d9..73be115 100644
Hans de Goede 56753f
--- a/hw/qxl.c
Hans de Goede 56753f
+++ b/hw/qxl.c
Hans de Goede 56753f
@@ -750,6 +750,11 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
Hans de Goede 56753f
                 __func__, current_async, cookie->io);
Hans de Goede 56753f
     }
Hans de Goede 56753f
     switch (current_async) {
Hans de Goede 56753f
+    case QXL_IO_MEMSLOT_ADD_ASYNC:
Hans de Goede 56753f
+    case QXL_IO_DESTROY_PRIMARY_ASYNC:
Hans de Goede 56753f
+    case QXL_IO_UPDATE_AREA_ASYNC:
Hans de Goede 56753f
+    case QXL_IO_FLUSH_SURFACES_ASYNC:
Hans de Goede 56753f
+        break;
Hans de Goede 56753f
     case QXL_IO_CREATE_PRIMARY_ASYNC:
Hans de Goede 56753f
         qxl_create_guest_primary_complete(qxl);
Hans de Goede 56753f
         break;
Hans de Goede 56753f
@@ -759,11 +764,54 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
Hans de Goede 56753f
     case QXL_IO_DESTROY_SURFACE_ASYNC:
Hans de Goede 56753f
         qxl_spice_destroy_surface_wait_complete(qxl, cookie->u.surface_id);
Hans de Goede 56753f
         break;
Hans de Goede 56753f
+    default:
Hans de Goede 56753f
+        fprintf(stderr, "qxl: %s: unexpected current_async %d\n", __func__,
Hans de Goede 56753f
+                current_async);
Hans de Goede 56753f
     }
Hans de Goede 56753f
     qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
Hans de Goede 56753f
 }
Hans de Goede 56753f
 
Hans de Goede 56753f
 /* called from spice server thread context only */
Hans de Goede 56753f
+static void interface_update_area_complete(QXLInstance *sin,
Hans de Goede 56753f
+        uint32_t surface_id,
Hans de Goede 56753f
+        QXLRect *dirty, uint32_t num_updated_rects)
Hans de Goede 56753f
+{
Hans de Goede 56753f
+    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
Hans de Goede 56753f
+    int i;
Hans de Goede 56753f
+    int qxl_i;
Hans de Goede 56753f
+
Hans de Goede 56753f
+    qemu_mutex_lock(&qxl->ssd.lock);
Hans de Goede 56753f
+    if (surface_id != 0 || !qxl->render_update_cookie_num) {
Hans de Goede 56753f
+        qemu_mutex_unlock(&qxl->ssd.lock);
Hans de Goede 56753f
+        return;
Hans de Goede 56753f
+    }
Hans de Goede 56753f
+    if (qxl->num_dirty_rects + num_updated_rects > QXL_NUM_DIRTY_RECTS) {
Hans de Goede 56753f
+        /*
Hans de Goede 56753f
+         * overflow - treat this as a full update. Not expected to be common.
Hans de Goede 56753f
+         */
Hans de Goede 56753f
+        dprint(qxl, 1, "%s: overflow of dirty rects\n", __func__);
Hans de Goede 56753f
+        qxl->guest_primary.resized = 1;
Hans de Goede 56753f
+    }
Hans de Goede 56753f
+    if (qxl->guest_primary.resized) {
Hans de Goede 56753f
+        /*
Hans de Goede 56753f
+         * Don't bother copying or scheduling the bh since we will flip
Hans de Goede 56753f
+         * the whole area anyway on completion of the update_area async call
Hans de Goede 56753f
+         */
Hans de Goede 56753f
+        qemu_mutex_unlock(&qxl->ssd.lock);
Hans de Goede 56753f
+        return;
Hans de Goede 56753f
+    }
Hans de Goede 56753f
+    qxl_i = qxl->num_dirty_rects;
Hans de Goede 56753f
+    for (i = 0; i < num_updated_rects; i++) {
Hans de Goede 56753f
+        qxl->dirty[qxl_i++] = dirty[i];
Hans de Goede 56753f
+    }
Hans de Goede 56753f
+    qxl->num_dirty_rects += num_updated_rects;
Hans de Goede 56753f
+    dprint(qxl, 1, "%s: scheduling update_area_bh, #dirty %d\n",
Hans de Goede 56753f
+           __func__, qxl->num_dirty_rects);
Hans de Goede 56753f
+    qemu_bh_schedule(qxl->update_area_bh);
Hans de Goede 56753f
+    qemu_mutex_unlock(&qxl->ssd.lock);
Hans de Goede 56753f
+}
Hans de Goede 56753f
+
Hans de Goede 56753f
+/* called from spice server thread context only */
Hans de Goede 56753f
 static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
Hans de Goede 56753f
 {
Hans de Goede 56753f
     PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
Hans de Goede 56753f
@@ -772,12 +820,16 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
Hans de Goede 56753f
     switch (cookie->type) {
Hans de Goede 56753f
     case QXL_COOKIE_TYPE_IO:
Hans de Goede 56753f
         interface_async_complete_io(qxl, cookie);
Hans de Goede 56753f
+        g_free(cookie);
Hans de Goede 56753f
+        break;
Hans de Goede 56753f
+    case QXL_COOKIE_TYPE_RENDER_UPDATE_AREA:
Hans de Goede 56753f
+        qxl_render_update_area_done(qxl, cookie);
Hans de Goede 56753f
         break;
Hans de Goede 56753f
     default:
Hans de Goede 56753f
         fprintf(stderr, "qxl: %s: unexpected cookie type %d\n",
Hans de Goede 56753f
                 __func__, cookie->type);
Hans de Goede 56753f
+        g_free(cookie);
Hans de Goede 56753f
     }
Hans de Goede 56753f
-    g_free(cookie);
Hans de Goede 56753f
 }
Hans de Goede 56753f
 
Hans de Goede 56753f
 static const QXLInterface qxl_interface = {
Hans de Goede 56753f
@@ -800,6 +852,7 @@ static const QXLInterface qxl_interface = {
Hans de Goede 56753f
     .notify_update           = interface_notify_update,
Hans de Goede 56753f
     .flush_resources         = interface_flush_resources,
Hans de Goede 56753f
     .async_complete          = interface_async_complete,
Hans de Goede 56753f
+    .update_area_complete    = interface_update_area_complete,
Hans de Goede 56753f
 };
Hans de Goede 56753f
 
Hans de Goede 56753f
 static void qxl_enter_vga_mode(PCIQXLDevice *d)
Hans de Goede 56753f
@@ -1216,11 +1269,17 @@ async_common:
Hans de Goede 56753f
     switch (io_port) {
Hans de Goede 56753f
     case QXL_IO_UPDATE_AREA:
Hans de Goede 56753f
     {
Hans de Goede 56753f
+        QXLCookie *cookie = NULL;
Hans de Goede 56753f
         QXLRect update = d->ram->update_area;
Hans de Goede 56753f
+
Hans de Goede 56753f
+        if (async == QXL_ASYNC) {
Hans de Goede 56753f
+            cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
Hans de Goede 56753f
+                                    QXL_IO_UPDATE_AREA_ASYNC);
Hans de Goede 56753f
+            cookie->u.area = update;
Hans de Goede 56753f
+        }
Hans de Goede 56753f
         qxl_spice_update_area(d, d->ram->update_surface,
Hans de Goede 56753f
-                              &update, NULL, 0, 0, async,
Hans de Goede 56753f
-                              qxl_cookie_new(QXL_COOKIE_TYPE_IO,
Hans de Goede 56753f
-                                             QXL_IO_UPDATE_AREA_ASYNC));
Hans de Goede 56753f
+                              cookie ? &cookie->u.area : &update,
Hans de Goede 56753f
+                              NULL, 0, 0, async, cookie);
Hans de Goede 56753f
         break;
Hans de Goede 56753f
     }
Hans de Goede 56753f
     case QXL_IO_NOTIFY_CMD:
Hans de Goede 56753f
@@ -1652,6 +1711,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
Hans de Goede 56753f
     init_pipe_signaling(qxl);
Hans de Goede 56753f
     qxl_reset_state(qxl);
Hans de Goede 56753f
 
Hans de Goede 56753f
+    qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl);
Hans de Goede 56753f
+
Hans de Goede 56753f
     return 0;
Hans de Goede 56753f
 }
Hans de Goede 56753f
 
Hans de Goede 56753f
diff --git a/hw/qxl.h b/hw/qxl.h
Hans de Goede 56753f
index 1443925..86e415b 100644
Hans de Goede 56753f
--- a/hw/qxl.h
Hans de Goede 56753f
+++ b/hw/qxl.h
Hans de Goede 56753f
@@ -18,6 +18,8 @@ enum qxl_mode {
Hans de Goede 56753f
 
Hans de Goede 56753f
 #define QXL_UNDEFINED_IO UINT32_MAX
Hans de Goede 56753f
 
Hans de Goede 56753f
+#define QXL_NUM_DIRTY_RECTS 64
Hans de Goede 56753f
+
Hans de Goede 56753f
 typedef struct PCIQXLDevice {
Hans de Goede 56753f
     PCIDevice          pci;
Hans de Goede 56753f
     SimpleSpiceDisplay ssd;
Hans de Goede 56753f
@@ -93,6 +95,12 @@ typedef struct PCIQXLDevice {
Hans de Goede 56753f
     /* user-friendly properties (in megabytes) */
Hans de Goede 56753f
     uint32_t          ram_size_mb;
Hans de Goede 56753f
     uint32_t          vram_size_mb;
Hans de Goede 56753f
+
Hans de Goede 56753f
+    /* qxl_render_update state */
Hans de Goede 56753f
+    int                render_update_cookie_num;
Hans de Goede 56753f
+    int                num_dirty_rects;
Hans de Goede 56753f
+    QXLRect            dirty[QXL_NUM_DIRTY_RECTS];
Hans de Goede 56753f
+    QEMUBH            *update_area_bh;
Hans de Goede 56753f
 } PCIQXLDevice;
Hans de Goede 56753f
 
Hans de Goede 56753f
 #define PANIC_ON(x) if ((x)) {                         \
Hans de Goede 56753f
@@ -134,3 +142,5 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
Hans de Goede 56753f
 void qxl_render_resize(PCIQXLDevice *qxl);
Hans de Goede 56753f
 void qxl_render_update(PCIQXLDevice *qxl);
Hans de Goede 56753f
 void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
Hans de Goede 56753f
+void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie);
Hans de Goede 56753f
+void qxl_render_update_area_bh(void *opaque);
Hans de Goede 56753f
diff --git a/ui/spice-display.h b/ui/spice-display.h
Hans de Goede 56753f
index 8a010cb..12e50b6 100644
Hans de Goede 56753f
--- a/ui/spice-display.h
Hans de Goede 56753f
+++ b/ui/spice-display.h
Hans de Goede 56753f
@@ -50,6 +50,7 @@ typedef enum qxl_async_io {
Hans de Goede 56753f
 
Hans de Goede 56753f
 enum {
Hans de Goede 56753f
     QXL_COOKIE_TYPE_IO,
Hans de Goede 56753f
+    QXL_COOKIE_TYPE_RENDER_UPDATE_AREA,
Hans de Goede 56753f
 };
Hans de Goede 56753f
 
Hans de Goede 56753f
 typedef struct QXLCookie {
Hans de Goede 56753f
@@ -57,6 +58,11 @@ typedef struct QXLCookie {
Hans de Goede 56753f
     uint64_t io;
Hans de Goede 56753f
     union {
Hans de Goede 56753f
         uint32_t surface_id;
Hans de Goede 56753f
+        QXLRect area;
Hans de Goede 56753f
+        struct {
Hans de Goede 56753f
+            QXLRect area;
Hans de Goede 56753f
+            int redraw;
Hans de Goede 56753f
+        } render;
Hans de Goede 56753f
     } u;
Hans de Goede 56753f
 } QXLCookie;
Hans de Goede 56753f
 
Hans de Goede 56753f
-- 
Hans de Goede 56753f
1.7.10
Hans de Goede 56753f