[Spice-commits] 24 commits - common/canvas_base.c common/gl_canvas.c server/Makefile.am server/red_dispatcher.c server/red_memslots.c server/red_parse_qxl.c server/red_parse_qxl.h server/red_worker.c server/spice.h spice.proto spice1.proto

Gerd Hoffmann kraxel at kemper.freedesktop.org
Tue Jun 29 03:49:46 PDT 2010


 common/canvas_base.c    |    8 
 common/gl_canvas.c      |   10 -
 server/Makefile.am      |    2 
 server/red_dispatcher.c |   18 +
 server/red_memslots.c   |   11 -
 server/red_parse_qxl.c  |  432 +++++++++++++++++++++++++++++++++++++++++++++++
 server/red_parse_qxl.h  |  130 ++++++++++++++
 server/red_worker.c     |  438 +++++++++++++++++++++++++-----------------------
 server/spice.h          |    6 
 spice.proto             |    8 
 spice1.proto            |    8 
 11 files changed, 836 insertions(+), 235 deletions(-)

New commits:
commit 58c23b66860def72f6b5186d77b5e047964e40cb
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 24 16:12:17 2010 +0200

    qxl abi: parse QXLRect.

diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 4368cf6..dbc82d4 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -32,6 +32,7 @@
 #include "gl_canvas.h"
 #include "reds.h"
 #include "red_dispatcher.h"
+#include "red_parse_qxl.h"
 
 static int num_active_workers = 0;
 
@@ -200,11 +201,16 @@ static void update_client_mouse_allowed()
 }
 
 static void qxl_worker_update_area(QXLWorker *qxl_worker, uint32_t surface_id,
-                                   SpiceRect *area, SpiceRect *dirty_rects,
+                                   QXLRect *qxl_area, QXLRect *qxl_dirty_rects,
                                    uint32_t num_dirty_rects, uint32_t clear_dirty_region)
 {
     RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
     RedWorkerMessage message = RED_WORKER_MESSAGE_UPDATE;
+    SpiceRect *dirty_rects = spice_new0(SpiceRect, num_dirty_rects);
+    SpiceRect *area = spice_new0(SpiceRect, 1);
+    int i;
+
+    red_get_rect_ptr(area, qxl_area);
 
     write_message(dispatcher->channel, &message);
     send_data(dispatcher->channel, &surface_id, sizeof(uint32_t));
@@ -214,6 +220,16 @@ static void qxl_worker_update_area(QXLWorker *qxl_worker, uint32_t surface_id,
     send_data(dispatcher->channel, &clear_dirty_region, sizeof(uint32_t));
     read_message(dispatcher->channel, &message);
     ASSERT(message == RED_WORKER_MESSAGE_READY);
+
+    for (i = 0; i < num_dirty_rects; i++) {
+        qxl_dirty_rects[i].top    = dirty_rects[i].top;
+        qxl_dirty_rects[i].left   = dirty_rects[i].left;
+        qxl_dirty_rects[i].bottom = dirty_rects[i].bottom;
+        qxl_dirty_rects[i].right  = dirty_rects[i].right;
+    }
+
+    free(dirty_rects);
+    free(area);
 }
 
 static void qxl_worker_add_memslot(QXLWorker *qxl_worker, QXLDevMemSlot *mem_slot)
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index b5362f4..c5a8f56 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -32,6 +32,14 @@ static void red_get_point16_ptr(SpicePoint16 *red, QXLPoint16 *qxl)
     red->y = qxl->y;
 }
 
+void red_get_rect_ptr(SpiceRect *red, QXLRect *qxl)
+{
+    red->top    = qxl->top;
+    red->left   = qxl->left;
+    red->bottom = qxl->bottom;
+    red->right  = qxl->right;
+}
+
 static void red_get_brush_ptr(RedMemSlotInfo *slots, int group_id,
                               SpiceBrush *red, QXLBrush *qxl)
 {
@@ -67,7 +75,7 @@ static void red_get_opaque_ptr(RedMemSlotInfo *slots, int group_id,
                                SpiceOpaque *red, QXLOpaque *qxl)
 {
    red->src_bitmap     = qxl->src_bitmap;
-   red->src_area       = qxl->src_area;
+   red_get_rect_ptr(&red->src_area, &qxl->src_area);
    red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush);
    red->rop_descriptor = qxl->rop_descriptor;
    red->scale_mode     = qxl->scale_mode;
@@ -78,7 +86,7 @@ static void red_get_copy_ptr(RedMemSlotInfo *slots, int group_id,
                              SpiceCopy *red, QXLCopy *qxl)
 {
    red->src_bitmap      = qxl->src_bitmap;
-   red->src_area        = qxl->src_area;
+   red_get_rect_ptr(&red->src_area, &qxl->src_area);
    red->rop_descriptor  = qxl->rop_descriptor;
    red->scale_mode      = qxl->scale_mode;
    red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
@@ -88,7 +96,7 @@ static void red_get_blend_ptr(RedMemSlotInfo *slots, int group_id,
                              SpiceBlend *red, QXLBlend *qxl)
 {
    red->src_bitmap      = qxl->src_bitmap;
-   red->src_area        = qxl->src_area;
+   red_get_rect_ptr(&red->src_area, &qxl->src_area);
    red->rop_descriptor  = qxl->rop_descriptor;
    red->scale_mode      = qxl->scale_mode;
    red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
@@ -98,7 +106,7 @@ static void red_get_transparent_ptr(RedMemSlotInfo *slots, int group_id,
                                     SpiceTransparent *red, QXLTransparent *qxl)
 {
    red->src_bitmap      = qxl->src_bitmap;
-   red->src_area        = qxl->src_area;
+   red_get_rect_ptr(&red->src_area, &qxl->src_area);
    red->src_color       = qxl->src_color;
    red->true_color      = qxl->true_color;
 }
@@ -109,7 +117,7 @@ static void red_get_alpha_blend_ptr(RedMemSlotInfo *slots, int group_id,
     red->alpha_flags = qxl->alpha_flags;
     red->alpha       = qxl->alpha;
     red->src_bitmap  = qxl->src_bitmap;
-    red->src_area    = qxl->src_area;
+    red_get_rect_ptr(&red->src_area, &qxl->src_area);
 }
 
 static void red_get_alpha_blend_ptr_compat(RedMemSlotInfo *slots, int group_id,
@@ -117,14 +125,14 @@ static void red_get_alpha_blend_ptr_compat(RedMemSlotInfo *slots, int group_id,
 {
     red->alpha       = qxl->alpha;
     red->src_bitmap  = qxl->src_bitmap;
-    red->src_area    = qxl->src_area;
+    red_get_rect_ptr(&red->src_area, &qxl->src_area);
 }
 
 static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id,
                              SpiceRop3 *red, QXLRop3 *qxl)
 {
    red->src_bitmap = qxl->src_bitmap;
-   red->src_area   = qxl->src_area;
+   red_get_rect_ptr(&red->src_area, &qxl->src_area);
    red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush);
    red->rop3       = qxl->rop3;
    red->scale_mode = qxl->scale_mode;
@@ -151,7 +159,7 @@ static void red_get_text_ptr(RedMemSlotInfo *slots, int group_id,
                                SpiceText *red, QXLText *qxl)
 {
    red->str        = qxl->str;
-   red->back_area  = qxl->back_area;
+   red_get_rect_ptr(&red->back_area, &qxl->back_area);
    red_get_brush_ptr(slots, group_id, &red->fore_brush, &qxl->fore_brush);
    red_get_brush_ptr(slots, group_id, &red->back_brush, &qxl->back_brush);
    red->fore_mode  = qxl->fore_mode;
@@ -192,17 +200,17 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
     qxl = (QXLDrawable *)get_virt(slots, addr, sizeof(*qxl), group_id);
     red->release_info     = &qxl->release_info;
 
-    red->bbox             = qxl->bbox;
+    red_get_rect_ptr(&red->bbox, &qxl->bbox);
     red_get_clip_ptr(slots, group_id, &red->clip, &qxl->clip);
     red->effect           = qxl->effect;
     red->mm_time          = qxl->mm_time;
     red->self_bitmap      = qxl->self_bitmap;
-    red->self_bitmap_area = qxl->self_bitmap_area;
+    red_get_rect_ptr(&red->self_bitmap_area, &qxl->self_bitmap_area);
     red->surface_id       = qxl->surface_id;
 
     for (i = 0; i < 3; i++) {
         red->surfaces_dest[i] = qxl->surfaces_dest[i];
-        red->surfaces_rects[i] = qxl->surfaces_rects[i];
+        red_get_rect_ptr(&red->surfaces_rects[i], &qxl->surfaces_rects[i]);
     }
 
     red->type = qxl->type;
@@ -264,7 +272,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
     qxl = (QXLCompatDrawable *)get_virt(slots, addr, sizeof(*qxl), group_id);
     red->release_info     = &qxl->release_info;
 
-    red->bbox             = qxl->bbox;
+    red_get_rect_ptr(&red->bbox, &qxl->bbox);
     red_get_clip_ptr(slots, group_id, &red->clip, &qxl->clip);
     red->effect           = qxl->effect;
     red->mm_time          = qxl->mm_time;
@@ -333,7 +341,7 @@ void red_get_update_cmd(RedMemSlotInfo *slots, int group_id,
     qxl = (QXLUpdateCmd *)get_virt(slots, addr, sizeof(*qxl), group_id);
     red->release_info     = &qxl->release_info;
 
-    red->area       = qxl->area;
+    red_get_rect_ptr(&red->area, &qxl->area);
     red->update_id  = qxl->update_id;
     red->surface_id = qxl->surface_id;
 }
diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h
index b96a393..aece6a9 100644
--- a/server/red_parse_qxl.h
+++ b/server/red_parse_qxl.h
@@ -103,6 +103,8 @@ typedef struct SPICE_ATTR_PACKED RedCursorCmd {
     uint8_t *device_data;
 } RedCursorCmd;
 
+void red_get_rect_ptr(SpiceRect *red, QXLRect *qxl);
+
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr);
 void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
diff --git a/server/spice.h b/server/spice.h
index 6c5853d..07bbeef 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -81,7 +81,7 @@ union QXLReleaseInfo;
 struct QXLReleaseInfoExt;
 struct QXLCommand;
 struct QXLCommandExt;
-struct SpiceRect;
+struct QXLRect;
 struct QXLWorker {
     uint32_t minor_version;
     uint32_t major_version;
@@ -90,7 +90,7 @@ struct QXLWorker {
     void (*start)(QXLWorker *worker);
     void (*stop)(QXLWorker *worker);
     void (*update_area)(QXLWorker *qxl_worker, uint32_t surface_id,
-                       struct SpiceRect *area, struct SpiceRect *dirty_rects,
+                       struct QXLRect *area, struct QXLRect *dirty_rects,
                        uint32_t num_dirty_rects, uint32_t clear_dirty_region);
     void (*add_memslot)(QXLWorker *worker, QXLDevMemSlot *slot);
     void (*del_memslot)(QXLWorker *worker, uint32_t slot_group_id, uint32_t slot_id);
@@ -158,8 +158,6 @@ struct QXLDevSurfaceCreate {
     uint32_t group_id;
 };
 
-struct SpiceRect;
-
 struct QXLInterface {
     SpiceBaseInterface base;
 
commit 4fb61b9aa5c092db1f8fcbd51f7967ccfda364ac
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 24 14:37:08 2010 +0200

    qxl abi: parse QXLPoint & friends.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 91d4aa0..b5362f4 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -20,6 +20,18 @@
 #include "red_memslots.h"
 #include "red_parse_qxl.h"
 
+static void red_get_point_ptr(SpicePoint *red, QXLPoint *qxl)
+{
+    red->x = qxl->x;
+    red->y = qxl->y;
+}
+
+static void red_get_point16_ptr(SpicePoint16 *red, QXLPoint16 *qxl)
+{
+    red->x = qxl->x;
+    red->y = qxl->y;
+}
+
 static void red_get_brush_ptr(RedMemSlotInfo *slots, int group_id,
                               SpiceBrush *red, QXLBrush *qxl)
 {
@@ -30,7 +42,7 @@ static void red_get_brush_ptr(RedMemSlotInfo *slots, int group_id,
         break;
     case SPICE_BRUSH_TYPE_PATTERN:
         red->u.pattern.pat = qxl->u.pattern.pat;
-        red->u.pattern.pos = qxl->u.pattern.pos;
+        red_get_point_ptr(&red->u.pattern.pos, &qxl->u.pattern.pos);
         break;
     }
 }
@@ -39,7 +51,7 @@ static void red_get_qmask_ptr(RedMemSlotInfo *slots, int group_id,
                               SpiceQMask *red, QXLQMask *qxl)
 {
     red->flags  = qxl->flags;
-    red->pos    = qxl->pos;
+    red_get_point_ptr(&red->pos, &qxl->pos);
     red->bitmap = qxl->bitmap;
 }
 
@@ -209,7 +221,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
         red_get_copy_ptr(slots, group_id, &red->u.copy, &qxl->u.copy);
         break;
     case QXL_COPY_BITS:
-        red->u.copy_bits = qxl->u.copy_bits;
+        red_get_point_ptr(&red->u.copy_bits.src_pos, &qxl->u.copy_bits.src_pos);
         break;
     case QXL_DRAW_FILL:
         red_get_fill_ptr(slots, group_id, &red->u.fill, &qxl->u.fill);
@@ -273,7 +285,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
         red_get_copy_ptr(slots, group_id, &red->u.copy, &qxl->u.copy);
         break;
     case QXL_COPY_BITS:
-        red->u.copy_bits = qxl->u.copy_bits;
+        red_get_point_ptr(&red->u.copy_bits.src_pos, &qxl->u.copy_bits.src_pos);
         break;
     case QXL_DRAW_FILL:
         red_get_fill_ptr(slots, group_id, &red->u.fill, &qxl->u.fill);
@@ -391,12 +403,12 @@ void red_get_cursor_cmd(RedMemSlotInfo *slots, int group_id,
     red->type = qxl->type;
     switch (red->type) {
     case QXL_CURSOR_SET:
-        red->u.set.position = qxl->u.set.position;
+        red_get_point16_ptr(&red->u.set.position, &qxl->u.set.position);
         red->u.set.visible  = qxl->u.set.visible;
         red->u.set.shape    = qxl->u.set.shape;
         break;
     case QXL_CURSOR_MOVE:
-        red->u.position = qxl->u.position;
+        red_get_point16_ptr(&red->u.position, &qxl->u.position);
         break;
     case QXL_CURSOR_TRAIL:
         red->u.trail.length    = qxl->u.trail.length;
diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h
index 94a880e..b96a393 100644
--- a/server/red_parse_qxl.h
+++ b/server/red_parse_qxl.h
@@ -42,7 +42,9 @@ typedef struct SPICE_ATTR_PACKED RedDrawable {
         SpiceCopy copy;
         SpiceTransparent transparent;
         SpiceAlphaBlnd alpha_blend;
-        QXLCopyBits copy_bits;
+        struct {
+            SpicePoint src_pos;
+        } copy_bits;
         SpiceBlend blend;
         SpiceRop3 rop3;
         SpiceStroke stroke;
commit e7ec85a08fab5be2488ae12fa5a99f96daaeb897
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 24 12:57:56 2010 +0200

    qxl abi: parse QXLCursorCmd.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index f45ab0b..91d4aa0 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -380,3 +380,33 @@ void red_put_surface_cmd(RedSurfaceCmd *red)
     /* nothing yet */
 }
 
+void red_get_cursor_cmd(RedMemSlotInfo *slots, int group_id,
+                        RedCursorCmd *red, SPICE_ADDRESS addr)
+{
+    QXLCursorCmd *qxl;
+
+    qxl = (QXLCursorCmd *)get_virt(slots, addr, sizeof(*qxl), group_id);
+    red->release_info     = &qxl->release_info;
+
+    red->type = qxl->type;
+    switch (red->type) {
+    case QXL_CURSOR_SET:
+        red->u.set.position = qxl->u.set.position;
+        red->u.set.visible  = qxl->u.set.visible;
+        red->u.set.shape    = qxl->u.set.shape;
+        break;
+    case QXL_CURSOR_MOVE:
+        red->u.position = qxl->u.position;
+        break;
+    case QXL_CURSOR_TRAIL:
+        red->u.trail.length    = qxl->u.trail.length;
+        red->u.trail.frequency = qxl->u.trail.frequency;
+        break;
+    }
+}
+
+void red_put_cursor_cmd(RedCursorCmd *red)
+{
+    /* nothing yet */
+}
+
diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h
index 53381d6..94a880e 100644
--- a/server/red_parse_qxl.h
+++ b/server/red_parse_qxl.h
@@ -83,6 +83,24 @@ typedef struct SPICE_ATTR_PACKED RedSurfaceCmd {
     } u;
 } RedSurfaceCmd;
 
+typedef struct SPICE_ATTR_PACKED RedCursorCmd {
+    QXLReleaseInfo *release_info;
+    uint8_t type;
+    union {
+        struct SPICE_ATTR_PACKED {
+            SpicePoint16 position;
+            uint8_t visible;
+            SPICE_ADDRESS shape;
+        } set;
+        struct SPICE_ATTR_PACKED {
+            uint16_t length;
+            uint16_t frequency;
+        } trail;
+        SpicePoint16 position;
+    } u;
+    uint8_t *device_data;
+} RedCursorCmd;
+
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr);
 void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
@@ -101,4 +119,8 @@ void red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
                          RedSurfaceCmd *red, SPICE_ADDRESS addr);
 void red_put_surface_cmd(RedSurfaceCmd *red);
 
+void red_get_cursor_cmd(RedMemSlotInfo *slots, int group_id,
+                        RedCursorCmd *red, SPICE_ADDRESS addr);
+void red_put_cursor_cmd(RedCursorCmd *red);
+
 #endif
diff --git a/server/red_worker.c b/server/red_worker.c
index 7af8eba..e458d4b 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -316,7 +316,7 @@ typedef struct CursorItem {
     uint32_t group_id;
     int refs;
     int type;
-    QXLCursorCmd *qxl_cursor;
+    RedCursorCmd *red_cursor;
 } CursorItem;
 
 typedef struct LocalCursor {
@@ -4862,18 +4862,20 @@ static void red_release_cursor(RedWorker *worker, CursorItem *cursor)
 {
     if (!--cursor->refs) {
         QXLReleaseInfoExt release_info_ext;
-        QXLCursorCmd *cursor_cmd;
+        RedCursorCmd *cursor_cmd;
 
         if (cursor->type == CURSOR_TYPE_LOCAL) {
             free(cursor);
             return;
         }
 
-        cursor_cmd = cursor->qxl_cursor;
+        cursor_cmd = cursor->red_cursor;
         release_info_ext.group_id = cursor->group_id;
-        release_info_ext.info = &cursor_cmd->release_info;
+        release_info_ext.info = cursor_cmd->release_info;
         worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
         free_cursor_item(worker, cursor);
+        red_put_cursor_cmd(cursor_cmd);
+        free(cursor_cmd);
     }
 }
 
@@ -4913,7 +4915,7 @@ static void cursor_items_init(RedWorker *worker)
     }
 }
 
-static CursorItem *get_cursor_item(RedWorker *worker, QXLCursorCmd *cmd, uint32_t group_id)
+static CursorItem *get_cursor_item(RedWorker *worker, RedCursorCmd *cmd, uint32_t group_id)
 {
     CursorItem *cursor_item;
 
@@ -4923,12 +4925,12 @@ static CursorItem *get_cursor_item(RedWorker *worker, QXLCursorCmd *cmd, uint32_
     red_pipe_item_init(&cursor_item->pipe_data, PIPE_ITEM_TYPE_CURSOR);
     cursor_item->type = CURSOR_TYPE_INVALID;
     cursor_item->group_id = group_id;
-    cursor_item->qxl_cursor = cmd;
+    cursor_item->red_cursor = cmd;
 
     return cursor_item;
 }
 
-void qxl_process_cursor(RedWorker *worker, QXLCursorCmd *cursor_cmd, uint32_t group_id)
+void qxl_process_cursor(RedWorker *worker, RedCursorCmd *cursor_cmd, uint32_t group_id)
 {
     CursorItem *item = get_cursor_item(worker, cursor_cmd, group_id);
     int cursor_show = FALSE;
@@ -4994,10 +4996,11 @@ static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size)
         worker->repoll_cursor_ring = 0;
         switch (ext_cmd.cmd.type) {
         case QXL_CMD_CURSOR: {
-            QXLCursorCmd *cursor_cmd = (QXLCursorCmd *)get_virt(&worker->mem_slots, ext_cmd.cmd.data,
-                                                                sizeof(QXLCursorCmd),
-                                                                ext_cmd.group_id);
-            qxl_process_cursor(worker, cursor_cmd, ext_cmd.group_id);
+            RedCursorCmd *cursor = spice_new0(RedCursorCmd, 1);
+
+            red_get_cursor_cmd(&worker->mem_slots, ext_cmd.group_id,
+                               cursor, ext_cmd.cmd.data);
+            qxl_process_cursor(worker, cursor, ext_cmd.group_id);
             break;
         }
         default:
@@ -7183,10 +7186,10 @@ static void fill_cursor(CursorChannel *cursor_channel, SpiceCursor *red_cursor,
     }
 
     if (cursor->type == CURSOR_TYPE_DEV) {
-        QXLCursorCmd *cursor_cmd;
+        RedCursorCmd *cursor_cmd;
         QXLCursor *qxl_cursor;
 
-        cursor_cmd = cursor->qxl_cursor;
+        cursor_cmd = cursor->red_cursor;
         qxl_cursor = (QXLCursor *)get_virt(&channel->worker->mem_slots, cursor_cmd->u.set.shape,
                                            sizeof(QXLCursor), cursor->group_id);
         red_cursor->flags = 0;
@@ -9414,7 +9417,7 @@ static void cursor_channel_send_migrate(CursorChannel *cursor_channel)
 static void red_send_cursor(CursorChannel *cursor_channel, CursorItem *cursor)
 {
     RedChannel *channel;
-    QXLCursorCmd *cmd;
+    RedCursorCmd *cmd;
     SpiceMarshaller *m;
 
     ASSERT(cursor_channel);
@@ -9422,7 +9425,7 @@ static void red_send_cursor(CursorChannel *cursor_channel, CursorItem *cursor)
     channel = &cursor_channel->base;
     m = channel->send_data.marshaller;
 
-    cmd = cursor->qxl_cursor;
+    cmd = cursor->red_cursor;
     switch (cmd->type) {
     case QXL_CURSOR_MOVE:
         {
@@ -10785,7 +10788,7 @@ static LocalCursor *_new_local_cursor(SpiceCursorHeader *header, int data_size,
 
 static void red_cursor_flush(RedWorker *worker)
 {
-    QXLCursorCmd *cursor_cmd;
+    RedCursorCmd *cursor_cmd;
     QXLCursor *qxl_cursor;
     LocalCursor *local;
     uint32_t data_size;
@@ -10798,7 +10801,7 @@ static void red_cursor_flush(RedWorker *worker)
 
     ASSERT(worker->cursor->type == CURSOR_TYPE_DEV);
 
-    cursor_cmd = worker->cursor->qxl_cursor;
+    cursor_cmd = worker->cursor->red_cursor;
     ASSERT(cursor_cmd->type == QXL_CURSOR_SET);
     qxl_cursor = (QXLCursor *)get_virt(&worker->mem_slots, cursor_cmd->u.set.shape, sizeof(QXLCursor),
                                        worker->cursor->group_id);
@@ -11272,7 +11275,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
     case RED_WORKER_MESSAGE_LOADVM_COMMANDS: {
         uint32_t count;
         QXLCommandExt ext;
-        QXLCursorCmd *cursor_cmd;
+        RedCursorCmd *cursor_cmd;
         RedSurfaceCmd *surface_cmd;
 
         red_printf("loadvm_commands");
@@ -11281,10 +11284,9 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
             receive_data(worker->channel, &ext, sizeof(QXLCommandExt));
             switch (ext.cmd.type) {
             case QXL_CMD_CURSOR:
-                cursor_cmd = (QXLCursorCmd *)get_virt(&worker->mem_slots,
-                                                      ext.cmd.data,
-                                                      sizeof(QXLCursorCmd),
-                                                      ext.group_id);
+                cursor_cmd = spice_new0(RedCursorCmd, 1);
+                red_get_cursor_cmd(&worker->mem_slots, ext.group_id,
+                                   cursor_cmd, ext.cmd.data);
                 qxl_process_cursor(worker, cursor_cmd, ext.group_id);
                 break;
             case QXL_CMD_SURFACE:
commit e03e4f0fc9fc41ecfb9ea5bc3183ec9dc20eb426
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 24 12:25:21 2010 +0200

    qxl abi: parse QXLSurfaceCmd.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 6c8eb69..f45ab0b 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -352,3 +352,31 @@ void red_put_message(RedMessage *red)
     /* nothing yet */
 }
 
+void red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
+                         RedSurfaceCmd *red, SPICE_ADDRESS addr)
+{
+    QXLSurfaceCmd *qxl;
+
+    qxl = (QXLSurfaceCmd *)get_virt(slots, addr, sizeof(*qxl), group_id);
+    red->release_info     = &qxl->release_info;
+
+    red->surface_id = qxl->surface_id;
+    red->type       = qxl->type;
+    red->flags      = qxl->flags;
+
+    switch (red->type) {
+    case QXL_SURFACE_CMD_CREATE:
+        red->u.surface_create.format = qxl->u.surface_create.format;
+        red->u.surface_create.width  = qxl->u.surface_create.width;
+        red->u.surface_create.height = qxl->u.surface_create.height;
+        red->u.surface_create.stride = qxl->u.surface_create.stride;
+        red->u.surface_create.data   = qxl->u.surface_create.data;
+        break;
+    }
+}
+
+void red_put_surface_cmd(RedSurfaceCmd *red)
+{
+    /* nothing yet */
+}
+
diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h
index b4baed8..53381d6 100644
--- a/server/red_parse_qxl.h
+++ b/server/red_parse_qxl.h
@@ -65,6 +65,24 @@ typedef struct SPICE_ATTR_PACKED RedMessage {
     uint8_t *data;
 } RedMessage;
 
+typedef struct SPICE_ATTR_PACKED RedSurfaceCreate {
+    uint32_t format;
+    uint32_t width;
+    uint32_t height;
+    int32_t stride;
+    SPICE_ADDRESS data;
+} RedSurfaceCreate;
+
+typedef struct SPICE_ATTR_PACKED RedSurfaceCmd {
+    QXLReleaseInfo *release_info;
+    uint32_t surface_id;
+    uint8_t type;
+    uint32_t flags;
+    union {
+        RedSurfaceCreate surface_create;
+    } u;
+} RedSurfaceCmd;
+
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr);
 void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
@@ -79,4 +97,8 @@ void red_get_message(RedMemSlotInfo *slots, int group_id,
                      RedMessage *red, SPICE_ADDRESS addr);
 void red_put_message(RedMessage *red);
 
+void red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
+                         RedSurfaceCmd *red, SPICE_ADDRESS addr);
+void red_put_surface_cmd(RedSurfaceCmd *red);
+
 #endif
diff --git a/server/red_worker.c b/server/red_worker.c
index 34f723f..7af8eba 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -3940,7 +3940,7 @@ static inline void red_create_surface(RedWorker *worker, uint32_t surface_id,uin
                                       uint32_t height, int32_t stride, uint32_t format,
                                       void *line_0, int data_is_valid);
 
-static inline void red_process_surface(RedWorker *worker, QXLSurfaceCmd *surface, uint32_t group_id, int data_is_valid)
+static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface, uint32_t group_id, int data_is_valid)
 {
     int surface_id;
     RedSurface *red_surface;
@@ -3964,12 +3964,12 @@ static inline void red_process_surface(RedWorker *worker, QXLSurfaceCmd *surface
         red_create_surface(worker, surface_id, surface->u.surface_create.width,
                            height, stride, surface->u.surface_create.format, data,
                            data_is_valid);
-        set_surface_release_info(worker, surface_id, 1, &surface->release_info, group_id);
+        set_surface_release_info(worker, surface_id, 1, surface->release_info, group_id);
         break;
     }
     case QXL_SURFACE_CMD_DESTROY:
         PANIC_ON(!red_surface->context.canvas);
-        set_surface_release_info(worker, surface_id, 0, &surface->release_info, group_id);
+        set_surface_release_info(worker, surface_id, 0, surface->release_info, group_id);
         red_handle_depends_on_target_surface(worker, surface_id);
         red_current_clear(worker, surface_id);
         red_clear_surface_glz_drawables(worker, surface_id);
@@ -3979,6 +3979,8 @@ static inline void red_process_surface(RedWorker *worker, QXLSurfaceCmd *surface
     default:
             red_error("unknown surface command");
     };
+    red_put_surface_cmd(surface);
+    free(surface);
 }
 
 static void localize_path(RedWorker *worker, QXLPHYSICAL *in_path, uint32_t group_id)
@@ -5073,8 +5075,10 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size)
             break;
         }
         case QXL_CMD_SURFACE: {
-            QXLSurfaceCmd *surface = (QXLSurfaceCmd *)get_virt(&worker->mem_slots, ext_cmd.cmd.data,
-                                                               sizeof(QXLSurfaceCmd), ext_cmd.group_id);
+            RedSurfaceCmd *surface = spice_new0(RedSurfaceCmd, 1);
+
+            red_get_surface_cmd(&worker->mem_slots, ext_cmd.group_id,
+                                surface, ext_cmd.cmd.data);
             red_process_surface(worker, surface, ext_cmd.group_id, 0);
             break;
         }
@@ -11269,7 +11273,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
         uint32_t count;
         QXLCommandExt ext;
         QXLCursorCmd *cursor_cmd;
-        QXLSurfaceCmd *surface_cmd;
+        RedSurfaceCmd *surface_cmd;
 
         red_printf("loadvm_commands");
         receive_data(worker->channel, &count, sizeof(uint32_t));
@@ -11284,10 +11288,9 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
                 qxl_process_cursor(worker, cursor_cmd, ext.group_id);
                 break;
             case QXL_CMD_SURFACE:
-                surface_cmd = (QXLSurfaceCmd *)get_virt(&worker->mem_slots,
-                                                        ext.cmd.data,
-                                                        sizeof(QXLSurfaceCmd),
-                                                        ext.group_id);
+                surface_cmd = spice_new0(RedSurfaceCmd, 1);
+                red_get_surface_cmd(&worker->mem_slots, ext.group_id,
+                                    surface_cmd, ext.cmd.data);
                 red_process_surface(worker, surface_cmd, ext.group_id, 1);
                 break;
             default:
commit 5de492e930ebe7597279b7392e14fe1d0653c94c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 24 11:54:36 2010 +0200

    qxl abi: parse QXLMessage.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index f7de6cf..6c8eb69 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -330,3 +330,25 @@ void red_put_update_cmd(RedUpdateCmd *red)
 {
     /* nothing yet */
 }
+
+void red_get_message(RedMemSlotInfo *slots, int group_id,
+                     RedMessage *red, SPICE_ADDRESS addr)
+{
+    QXLMessage *qxl;
+
+    /*
+     * security alert:
+     *   qxl->data[0] size isn't specified anywhere -> can't verify
+     *   luckily this is for debug logging only,
+     *   so we can just ignore it by default.
+     */
+    qxl = (QXLMessage *)get_virt(slots, addr, sizeof(*qxl), group_id);
+    red->release_info  = &qxl->release_info;
+    red->data          = qxl->data;
+}
+
+void red_put_message(RedMessage *red)
+{
+    /* nothing yet */
+}
+
diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h
index bc2dd4e..b4baed8 100644
--- a/server/red_parse_qxl.h
+++ b/server/red_parse_qxl.h
@@ -60,6 +60,11 @@ typedef struct SPICE_ATTR_PACKED RedUpdateCmd {
     uint32_t surface_id;
 } RedUpdateCmd;
 
+typedef struct SPICE_ATTR_PACKED RedMessage {
+    QXLReleaseInfo *release_info;
+    uint8_t *data;
+} RedMessage;
+
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr);
 void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
@@ -70,4 +75,8 @@ void red_get_update_cmd(RedMemSlotInfo *slots, int group_id,
                         RedUpdateCmd *red, SPICE_ADDRESS addr);
 void red_put_update_cmd(RedUpdateCmd *red);
 
+void red_get_message(RedMemSlotInfo *slots, int group_id,
+                     RedMessage *red, SPICE_ADDRESS addr);
+void red_put_message(RedMessage *red);
+
 #endif
diff --git a/server/red_worker.c b/server/red_worker.c
index b90c3f9..34f723f 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -5057,13 +5057,19 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size)
             break;
         }
         case QXL_CMD_MESSAGE: {
+            RedMessage message;
             QXLReleaseInfoExt release_info_ext;
-            QXLMessage *message = (QXLMessage *)get_virt(&worker->mem_slots, ext_cmd.cmd.data,
-                                                         sizeof(QXLMessage), ext_cmd.group_id);
-            red_printf("MESSAGE: %s", message->data);
+
+            red_get_message(&worker->mem_slots, ext_cmd.group_id,
+                            &message, ext_cmd.cmd.data);
+#ifdef DEBUG
+            /* alert: accessing message.data is insecure */
+            red_printf("MESSAGE: %s", message.data);
+#endif
             release_info_ext.group_id = ext_cmd.group_id;
-            release_info_ext.info = &message->release_info;
+            release_info_ext.info = message.release_info;
             worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
+            red_put_message(&message);
             break;
         }
         case QXL_CMD_SURFACE: {
commit fada35a173996ff24aa081112d37cfa7292cabe3
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 24 11:26:11 2010 +0200

    qxl abi: parse QXLUpdateCmd.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 34308c3..f7de6cf 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -312,3 +312,21 @@ void red_put_drawable(RedDrawable *red)
 {
     /* nothing yet */
 }
+
+void red_get_update_cmd(RedMemSlotInfo *slots, int group_id,
+                        RedUpdateCmd *red, SPICE_ADDRESS addr)
+{
+    QXLUpdateCmd *qxl;
+
+    qxl = (QXLUpdateCmd *)get_virt(slots, addr, sizeof(*qxl), group_id);
+    red->release_info     = &qxl->release_info;
+
+    red->area       = qxl->area;
+    red->update_id  = qxl->update_id;
+    red->surface_id = qxl->surface_id;
+}
+
+void red_put_update_cmd(RedUpdateCmd *red)
+{
+    /* nothing yet */
+}
diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h
index 5737b55..bc2dd4e 100644
--- a/server/red_parse_qxl.h
+++ b/server/red_parse_qxl.h
@@ -53,10 +53,21 @@ typedef struct SPICE_ATTR_PACKED RedDrawable {
     } u;
 } RedDrawable;
 
+typedef struct SPICE_ATTR_PACKED RedUpdateCmd {
+    QXLReleaseInfo *release_info;
+    SpiceRect area;
+    uint32_t update_id;
+    uint32_t surface_id;
+} RedUpdateCmd;
+
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr);
 void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
                              RedDrawable *red, SPICE_ADDRESS addr);
 void red_put_drawable(RedDrawable *red);
 
+void red_get_update_cmd(RedMemSlotInfo *slots, int group_id,
+                        RedUpdateCmd *red, SPICE_ADDRESS addr);
+void red_put_update_cmd(RedUpdateCmd *red);
+
 #endif
diff --git a/server/red_worker.c b/server/red_worker.c
index 72eba10..b90c3f9 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -5042,18 +5042,18 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size)
             break;
         }
         case QXL_CMD_UPDATE: {
-            int surface_id;
+            RedUpdateCmd update;
             QXLReleaseInfoExt release_info_ext;
-            QXLUpdateCmd *draw_cmd = (QXLUpdateCmd *)get_virt(&worker->mem_slots, ext_cmd.cmd.data,
-                                                              sizeof(QXLUpdateCmd),
-                                                              ext_cmd.group_id);
-            surface_id = draw_cmd->surface_id;
-            validate_surface(worker, surface_id);
-            red_update_area(worker, &draw_cmd->area, draw_cmd->surface_id);
-            worker->qxl->st->qif->notify_update(worker->qxl, draw_cmd->update_id);
+
+            red_get_update_cmd(&worker->mem_slots, ext_cmd.group_id,
+                               &update, ext_cmd.cmd.data);
+            validate_surface(worker, update.surface_id);
+            red_update_area(worker, &update.area, update.surface_id);
+            worker->qxl->st->qif->notify_update(worker->qxl, update.update_id);
             release_info_ext.group_id = ext_cmd.group_id;
-            release_info_ext.info = &draw_cmd->release_info;
+            release_info_ext.info = update.release_info;
             worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
+            red_put_update_cmd(&update);
             break;
         }
         case QXL_CMD_MESSAGE: {
commit b081ec4b0472b697862f996759e2e406a3af38f9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 24 09:50:01 2010 +0200

    qxl abi: parse QXLClip.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 7bb347f..34308c3 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -164,6 +164,13 @@ static void red_get_invers_ptr(RedMemSlotInfo *slots, int group_id,
     red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
 }
 
+static void red_get_clip_ptr(RedMemSlotInfo *slots, int group_id,
+                             SpiceClip *red, QXLClip *qxl)
+{
+    red->type = qxl->type;
+    red->data = qxl->data;
+}
+
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr)
 {
@@ -174,7 +181,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
     red->release_info     = &qxl->release_info;
 
     red->bbox             = qxl->bbox;
-    red->clip             = qxl->clip;
+    red_get_clip_ptr(slots, group_id, &red->clip, &qxl->clip);
     red->effect           = qxl->effect;
     red->mm_time          = qxl->mm_time;
     red->self_bitmap      = qxl->self_bitmap;
@@ -246,7 +253,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
     red->release_info     = &qxl->release_info;
 
     red->bbox             = qxl->bbox;
-    red->clip             = qxl->clip;
+    red_get_clip_ptr(slots, group_id, &red->clip, &qxl->clip);
     red->effect           = qxl->effect;
     red->mm_time          = qxl->mm_time;
 
commit 948806b5838906e744d9e70ce633479d9a7e9178
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 24 09:19:59 2010 +0200

    qxl abi: parse QXLLineAttr.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 667a57a..7bb347f 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -122,11 +122,17 @@ static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id,
 static void red_get_stroke_ptr(RedMemSlotInfo *slots, int group_id,
                                SpiceStroke *red, QXLStroke *qxl)
 {
-   red->path       = qxl->path;
-   red->attr       = qxl->attr;
+   red->path             = qxl->path;
+   red->attr.flags       = qxl->attr.flags;
+   red->attr.join_style  = qxl->attr.join_style;
+   red->attr.end_style   = qxl->attr.end_style;
+   red->attr.style_nseg  = qxl->attr.style_nseg;
+   red->attr.width       = qxl->attr.width;
+   red->attr.miter_limit = qxl->attr.miter_limit;
+   red->attr.style       = qxl->attr.style;
    red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush);
-   red->fore_mode  = qxl->fore_mode;
-   red->back_mode  = qxl->back_mode;
+   red->fore_mode        = qxl->fore_mode;
+   red->back_mode        = qxl->back_mode;
 }
 
 static void red_get_text_ptr(RedMemSlotInfo *slots, int group_id,
commit 49f77eec2ed63a13da92eaba1325d09e9e247fe8
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 24 09:13:48 2010 +0200

    qxl abi: parse QXLPattern.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 1bd19aa..667a57a 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -29,7 +29,8 @@ static void red_get_brush_ptr(RedMemSlotInfo *slots, int group_id,
         red->u.color = qxl->u.color;
         break;
     case SPICE_BRUSH_TYPE_PATTERN:
-        red->u.pattern = qxl->u.pattern;
+        red->u.pattern.pat = qxl->u.pattern.pat;
+        red->u.pattern.pos = qxl->u.pattern.pos;
         break;
     }
 }
commit 4de61f2dd89a5f5f2372afd2f6e7575d911cf235
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 23 17:50:15 2010 +0200

    qxl abi: parse QXLBrush.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index c6048f0..1bd19aa 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -20,6 +20,20 @@
 #include "red_memslots.h"
 #include "red_parse_qxl.h"
 
+static void red_get_brush_ptr(RedMemSlotInfo *slots, int group_id,
+                              SpiceBrush *red, QXLBrush *qxl)
+{
+    red->type = qxl->type;
+    switch (red->type) {
+    case SPICE_BRUSH_TYPE_SOLID:
+        red->u.color = qxl->u.color;
+        break;
+    case SPICE_BRUSH_TYPE_PATTERN:
+        red->u.pattern = qxl->u.pattern;
+        break;
+    }
+}
+
 static void red_get_qmask_ptr(RedMemSlotInfo *slots, int group_id,
                               SpiceQMask *red, QXLQMask *qxl)
 {
@@ -31,7 +45,7 @@ static void red_get_qmask_ptr(RedMemSlotInfo *slots, int group_id,
 static void red_get_fill_ptr(RedMemSlotInfo *slots, int group_id,
                              SpiceFill *red, QXLFill *qxl)
 {
-    red->brush          = qxl->brush;
+    red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush);
     red->rop_descriptor = qxl->rop_descriptor;
     red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
 }
@@ -41,7 +55,7 @@ static void red_get_opaque_ptr(RedMemSlotInfo *slots, int group_id,
 {
    red->src_bitmap     = qxl->src_bitmap;
    red->src_area       = qxl->src_area;
-   red->brush          = qxl->brush;
+   red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush);
    red->rop_descriptor = qxl->rop_descriptor;
    red->scale_mode     = qxl->scale_mode;
    red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
@@ -98,7 +112,7 @@ static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id,
 {
    red->src_bitmap = qxl->src_bitmap;
    red->src_area   = qxl->src_area;
-   red->brush      = qxl->brush;
+   red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush);
    red->rop3       = qxl->rop3;
    red->scale_mode = qxl->scale_mode;
    red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
@@ -109,7 +123,7 @@ static void red_get_stroke_ptr(RedMemSlotInfo *slots, int group_id,
 {
    red->path       = qxl->path;
    red->attr       = qxl->attr;
-   red->brush      = qxl->brush;
+   red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush);
    red->fore_mode  = qxl->fore_mode;
    red->back_mode  = qxl->back_mode;
 }
@@ -119,8 +133,8 @@ static void red_get_text_ptr(RedMemSlotInfo *slots, int group_id,
 {
    red->str        = qxl->str;
    red->back_area  = qxl->back_area;
-   red->fore_brush = qxl->fore_brush;
-   red->back_brush = qxl->back_brush;
+   red_get_brush_ptr(slots, group_id, &red->fore_brush, &qxl->fore_brush);
+   red_get_brush_ptr(slots, group_id, &red->back_brush, &qxl->back_brush);
    red->fore_mode  = qxl->fore_mode;
    red->back_mode  = qxl->back_mode;
 }
commit 45ba74c79532480c0e1f98a0392c801368728295
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 23 17:40:35 2010 +0200

    qxl abi: parse QXLQMask.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index dfdd41d..c6048f0 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -20,12 +20,20 @@
 #include "red_memslots.h"
 #include "red_parse_qxl.h"
 
+static void red_get_qmask_ptr(RedMemSlotInfo *slots, int group_id,
+                              SpiceQMask *red, QXLQMask *qxl)
+{
+    red->flags  = qxl->flags;
+    red->pos    = qxl->pos;
+    red->bitmap = qxl->bitmap;
+}
+
 static void red_get_fill_ptr(RedMemSlotInfo *slots, int group_id,
                              SpiceFill *red, QXLFill *qxl)
 {
     red->brush          = qxl->brush;
     red->rop_descriptor = qxl->rop_descriptor;
-    red->mask           = qxl->mask;
+    red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
 }
 
 static void red_get_opaque_ptr(RedMemSlotInfo *slots, int group_id,
@@ -36,7 +44,7 @@ static void red_get_opaque_ptr(RedMemSlotInfo *slots, int group_id,
    red->brush          = qxl->brush;
    red->rop_descriptor = qxl->rop_descriptor;
    red->scale_mode     = qxl->scale_mode;
-   red->mask           = qxl->mask;
+   red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
 }
 
 static void red_get_copy_ptr(RedMemSlotInfo *slots, int group_id,
@@ -46,7 +54,7 @@ static void red_get_copy_ptr(RedMemSlotInfo *slots, int group_id,
    red->src_area        = qxl->src_area;
    red->rop_descriptor  = qxl->rop_descriptor;
    red->scale_mode      = qxl->scale_mode;
-   red->mask            = qxl->mask;
+   red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
 }
 
 static void red_get_blend_ptr(RedMemSlotInfo *slots, int group_id,
@@ -56,7 +64,7 @@ static void red_get_blend_ptr(RedMemSlotInfo *slots, int group_id,
    red->src_area        = qxl->src_area;
    red->rop_descriptor  = qxl->rop_descriptor;
    red->scale_mode      = qxl->scale_mode;
-   red->mask            = qxl->mask;
+   red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
 }
 
 static void red_get_transparent_ptr(RedMemSlotInfo *slots, int group_id,
@@ -93,7 +101,7 @@ static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id,
    red->brush      = qxl->brush;
    red->rop3       = qxl->rop3;
    red->scale_mode = qxl->scale_mode;
-   red->mask       = qxl->mask;
+   red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
 }
 
 static void red_get_stroke_ptr(RedMemSlotInfo *slots, int group_id,
@@ -120,19 +128,19 @@ static void red_get_text_ptr(RedMemSlotInfo *slots, int group_id,
 static void red_get_whiteness_ptr(RedMemSlotInfo *slots, int group_id,
                                   SpiceWhiteness *red, QXLWhiteness *qxl)
 {
-    red->mask = qxl->mask;
+    red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
 }
 
 static void red_get_blackness_ptr(RedMemSlotInfo *slots, int group_id,
                                   SpiceBlackness *red, QXLBlackness *qxl)
 {
-    red->mask = qxl->mask;
+    red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
 }
 
 static void red_get_invers_ptr(RedMemSlotInfo *slots, int group_id,
                                SpiceInvers *red, QXLInvers *qxl)
 {
-    red->mask = qxl->mask;
+    red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
 }
 
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
commit 387f80422f3f2ce35fc17a828d06a9bd4ceede8e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 23 16:56:49 2010 +0200

    qxl abi: parse QXLBlackness+QXLInvers+QXLWhiteness.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index c1c6e66..dfdd41d 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -117,6 +117,24 @@ static void red_get_text_ptr(RedMemSlotInfo *slots, int group_id,
    red->back_mode  = qxl->back_mode;
 }
 
+static void red_get_whiteness_ptr(RedMemSlotInfo *slots, int group_id,
+                                  SpiceWhiteness *red, QXLWhiteness *qxl)
+{
+    red->mask = qxl->mask;
+}
+
+static void red_get_blackness_ptr(RedMemSlotInfo *slots, int group_id,
+                                  SpiceBlackness *red, QXLBlackness *qxl)
+{
+    red->mask = qxl->mask;
+}
+
+static void red_get_invers_ptr(RedMemSlotInfo *slots, int group_id,
+                               SpiceInvers *red, QXLInvers *qxl)
+{
+    red->mask = qxl->mask;
+}
+
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr)
 {
@@ -146,7 +164,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                                 &red->u.alpha_blend, &qxl->u.alpha_blend);
         break;
     case QXL_DRAW_BLACKNESS:
-        red->u.blackness = qxl->u.blackness;
+        red_get_blackness_ptr(slots, group_id, &red->u.blackness, &qxl->u.blackness);
         break;
     case QXL_DRAW_BLEND:
         red_get_blend_ptr(slots, group_id, &red->u.blend, &qxl->u.blend);
@@ -164,7 +182,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
         red_get_opaque_ptr(slots, group_id, &red->u.opaque, &qxl->u.opaque);
         break;
     case QXL_DRAW_INVERS:
-        red->u.invers = qxl->u.invers;
+        red_get_invers_ptr(slots, group_id, &red->u.invers, &qxl->u.invers);
         break;
     case QXL_DRAW_NOP:
         break;
@@ -182,7 +200,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                                 &red->u.transparent, &qxl->u.transparent);
         break;
     case QXL_DRAW_WHITENESS:
-        red->u.whiteness = qxl->u.whiteness;
+        red_get_whiteness_ptr(slots, group_id, &red->u.whiteness, &qxl->u.whiteness);
         break;
     default:
         red_error("unknown type");
@@ -210,7 +228,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
                                        &red->u.alpha_blend, &qxl->u.alpha_blend);
         break;
     case QXL_DRAW_BLACKNESS:
-        red->u.blackness = qxl->u.blackness;
+        red_get_blackness_ptr(slots, group_id, &red->u.blackness, &qxl->u.blackness);
         break;
     case QXL_DRAW_BLEND:
         red_get_blend_ptr(slots, group_id, &red->u.blend, &qxl->u.blend);
@@ -228,7 +246,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
         red_get_opaque_ptr(slots, group_id, &red->u.opaque, &qxl->u.opaque);
         break;
     case QXL_DRAW_INVERS:
-        red->u.invers = qxl->u.invers;
+        red_get_invers_ptr(slots, group_id, &red->u.invers, &qxl->u.invers);
         break;
     case QXL_DRAW_NOP:
         break;
@@ -246,7 +264,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
                                 &red->u.transparent, &qxl->u.transparent);
         break;
     case QXL_DRAW_WHITENESS:
-        red->u.whiteness = qxl->u.whiteness;
+        red_get_whiteness_ptr(slots, group_id, &red->u.whiteness, &qxl->u.whiteness);
         break;
     default:
         red_error("unknown type");
commit 21fffa15e1b921a54b5dab908c89ea946b2fbe1c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 23 16:31:23 2010 +0200

    qxl abi: parse QXLText.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index b82a6e8..c1c6e66 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -106,6 +106,17 @@ static void red_get_stroke_ptr(RedMemSlotInfo *slots, int group_id,
    red->back_mode  = qxl->back_mode;
 }
 
+static void red_get_text_ptr(RedMemSlotInfo *slots, int group_id,
+                               SpiceText *red, QXLText *qxl)
+{
+   red->str        = qxl->str;
+   red->back_area  = qxl->back_area;
+   red->fore_brush = qxl->fore_brush;
+   red->back_brush = qxl->back_brush;
+   red->fore_mode  = qxl->fore_mode;
+   red->back_mode  = qxl->back_mode;
+}
+
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr)
 {
@@ -164,7 +175,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
         red_get_stroke_ptr(slots, group_id, &red->u.stroke, &qxl->u.stroke);
         break;
     case QXL_DRAW_TEXT:
-        red->u.text = qxl->u.text;
+        red_get_text_ptr(slots, group_id, &red->u.text, &qxl->u.text);
         break;
     case QXL_DRAW_TRANSPARENT:
         red_get_transparent_ptr(slots, group_id,
@@ -228,7 +239,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
         red_get_stroke_ptr(slots, group_id, &red->u.stroke, &qxl->u.stroke);
         break;
     case QXL_DRAW_TEXT:
-        red->u.text = qxl->u.text;
+        red_get_text_ptr(slots, group_id, &red->u.text, &qxl->u.text);
         break;
     case QXL_DRAW_TRANSPARENT:
         red_get_transparent_ptr(slots, group_id,
commit b39b130a84601fec0f0c8d771ac636c7a2b8099a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 23 16:24:01 2010 +0200

    qxl abi: parse QXLStroke.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index cfb2026..b82a6e8 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -96,6 +96,16 @@ static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id,
    red->mask       = qxl->mask;
 }
 
+static void red_get_stroke_ptr(RedMemSlotInfo *slots, int group_id,
+                               SpiceStroke *red, QXLStroke *qxl)
+{
+   red->path       = qxl->path;
+   red->attr       = qxl->attr;
+   red->brush      = qxl->brush;
+   red->fore_mode  = qxl->fore_mode;
+   red->back_mode  = qxl->back_mode;
+}
+
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr)
 {
@@ -151,7 +161,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
         red_get_rop3_ptr(slots, group_id, &red->u.rop3, &qxl->u.rop3);
         break;
     case QXL_DRAW_STROKE:
-        red->u.stroke = qxl->u.stroke;
+        red_get_stroke_ptr(slots, group_id, &red->u.stroke, &qxl->u.stroke);
         break;
     case QXL_DRAW_TEXT:
         red->u.text = qxl->u.text;
@@ -215,7 +225,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
         red_get_rop3_ptr(slots, group_id, &red->u.rop3, &qxl->u.rop3);
         break;
     case QXL_DRAW_STROKE:
-        red->u.stroke = qxl->u.stroke;
+        red_get_stroke_ptr(slots, group_id, &red->u.stroke, &qxl->u.stroke);
         break;
     case QXL_DRAW_TEXT:
         red->u.text = qxl->u.text;
commit c26b574b40e01789471c080af7b1c6c1c976dfc6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 23 15:34:28 2010 +0200

    qxl abi: parse QXLRop3.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index f53a9ba..cfb2026 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -85,6 +85,17 @@ static void red_get_alpha_blend_ptr_compat(RedMemSlotInfo *slots, int group_id,
     red->src_area    = qxl->src_area;
 }
 
+static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id,
+                             SpiceRop3 *red, QXLRop3 *qxl)
+{
+   red->src_bitmap = qxl->src_bitmap;
+   red->src_area   = qxl->src_area;
+   red->brush      = qxl->brush;
+   red->rop3       = qxl->rop3;
+   red->scale_mode = qxl->scale_mode;
+   red->mask       = qxl->mask;
+}
+
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr)
 {
@@ -137,7 +148,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
     case QXL_DRAW_NOP:
         break;
     case QXL_DRAW_ROP3:
-        red->u.rop3 = qxl->u.rop3;
+        red_get_rop3_ptr(slots, group_id, &red->u.rop3, &qxl->u.rop3);
         break;
     case QXL_DRAW_STROKE:
         red->u.stroke = qxl->u.stroke;
@@ -201,7 +212,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
     case QXL_DRAW_NOP:
         break;
     case QXL_DRAW_ROP3:
-        red->u.rop3 = qxl->u.rop3;
+        red_get_rop3_ptr(slots, group_id, &red->u.rop3, &qxl->u.rop3);
         break;
     case QXL_DRAW_STROKE:
         red->u.stroke = qxl->u.stroke;
commit dffb0401e79b8e9f85975330abb74134278aff86
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 23 14:55:50 2010 +0200

    qxl abi: parse QXLTransparent.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index efe624e..f53a9ba 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -59,6 +59,15 @@ static void red_get_blend_ptr(RedMemSlotInfo *slots, int group_id,
    red->mask            = qxl->mask;
 }
 
+static void red_get_transparent_ptr(RedMemSlotInfo *slots, int group_id,
+                                    SpiceTransparent *red, QXLTransparent *qxl)
+{
+   red->src_bitmap      = qxl->src_bitmap;
+   red->src_area        = qxl->src_area;
+   red->src_color       = qxl->src_color;
+   red->true_color      = qxl->true_color;
+}
+
 static void red_get_alpha_blend_ptr(RedMemSlotInfo *slots, int group_id,
                                     SpiceAlphaBlnd *red, QXLAlphaBlnd *qxl)
 {
@@ -137,7 +146,8 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
         red->u.text = qxl->u.text;
         break;
     case QXL_DRAW_TRANSPARENT:
-        red->u.transparent = qxl->u.transparent;
+        red_get_transparent_ptr(slots, group_id,
+                                &red->u.transparent, &qxl->u.transparent);
         break;
     case QXL_DRAW_WHITENESS:
         red->u.whiteness = qxl->u.whiteness;
@@ -200,7 +210,8 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
         red->u.text = qxl->u.text;
         break;
     case QXL_DRAW_TRANSPARENT:
-        red->u.transparent = qxl->u.transparent;
+        red_get_transparent_ptr(slots, group_id,
+                                &red->u.transparent, &qxl->u.transparent);
         break;
     case QXL_DRAW_WHITENESS:
         red->u.whiteness = qxl->u.whiteness;
commit e81c6ef7c4be264cf2c7497d2c927a4b7132590e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 23 14:46:23 2010 +0200

    qxl abi: parse QXLCopy + QXLBlend.
    
    Also adapt to tyops fix (s/rop_decriptor/rop_descriptor/).

diff --git a/common/canvas_base.c b/common/canvas_base.c
index debbd46..c5ab88a 100644
--- a/common/canvas_base.c
+++ b/common/canvas_base.c
@@ -2232,7 +2232,7 @@ static void canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceCl
     canvas_mask_pixman(canvas, &dest_region, &copy->mask,
                        bbox->left, bbox->top);
 
-    rop = ropd_descriptor_to_rop(copy->rop_decriptor,
+    rop = ropd_descriptor_to_rop(copy->rop_descriptor,
                                  ROP_INPUT_SRC,
                                  ROP_INPUT_DEST);
 
@@ -2573,7 +2573,7 @@ static void canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceC
     canvas_mask_pixman(canvas, &dest_region, &blend->mask,
                        bbox->left, bbox->top);
 
-    rop = ropd_descriptor_to_rop(blend->rop_decriptor,
+    rop = ropd_descriptor_to_rop(blend->rop_descriptor,
                                  ROP_INPUT_SRC,
                                  ROP_INPUT_DEST);
 
diff --git a/common/gl_canvas.c b/common/gl_canvas.c
index 1fe08ae..059bd04 100644
--- a/common/gl_canvas.c
+++ b/common/gl_canvas.c
@@ -364,7 +364,7 @@ static void gl_canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spic
 
     set_clip(canvas, bbox, clip);
     set_mask(canvas, &copy->mask, bbox->left, bbox->top);
-    set_op(canvas, copy->rop_decriptor);
+    set_op(canvas, copy->rop_descriptor);
 
     //todo: optimize get_image (use ogl conversion + remove unnecessary copy of 32bpp)
     surface = canvas_get_image(&canvas->base, copy->src_bitmap, FALSE);
@@ -438,7 +438,7 @@ static void gl_canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spi
 
     set_clip(canvas, bbox, clip);
     set_mask(canvas, &blend->mask, bbox->left, bbox->top);
-    set_op(canvas, blend->rop_decriptor);
+    set_op(canvas, blend->rop_descriptor);
 
     surface = canvas_get_image(&canvas->base, blend->src_bitmap, FALSE);
     SET_GLC_RECT(&dest, bbox);
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 8590ec7..efe624e 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -39,6 +39,26 @@ static void red_get_opaque_ptr(RedMemSlotInfo *slots, int group_id,
    red->mask           = qxl->mask;
 }
 
+static void red_get_copy_ptr(RedMemSlotInfo *slots, int group_id,
+                             SpiceCopy *red, QXLCopy *qxl)
+{
+   red->src_bitmap      = qxl->src_bitmap;
+   red->src_area        = qxl->src_area;
+   red->rop_descriptor  = qxl->rop_descriptor;
+   red->scale_mode      = qxl->scale_mode;
+   red->mask            = qxl->mask;
+}
+
+static void red_get_blend_ptr(RedMemSlotInfo *slots, int group_id,
+                             SpiceBlend *red, QXLBlend *qxl)
+{
+   red->src_bitmap      = qxl->src_bitmap;
+   red->src_area        = qxl->src_area;
+   red->rop_descriptor  = qxl->rop_descriptor;
+   red->scale_mode      = qxl->scale_mode;
+   red->mask            = qxl->mask;
+}
+
 static void red_get_alpha_blend_ptr(RedMemSlotInfo *slots, int group_id,
                                     SpiceAlphaBlnd *red, QXLAlphaBlnd *qxl)
 {
@@ -88,10 +108,10 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
         red->u.blackness = qxl->u.blackness;
         break;
     case QXL_DRAW_BLEND:
-        red->u.blend = qxl->u.blend;
+        red_get_blend_ptr(slots, group_id, &red->u.blend, &qxl->u.blend);
         break;
     case QXL_DRAW_COPY:
-        red->u.copy = qxl->u.copy;
+        red_get_copy_ptr(slots, group_id, &red->u.copy, &qxl->u.copy);
         break;
     case QXL_COPY_BITS:
         red->u.copy_bits = qxl->u.copy_bits;
@@ -151,10 +171,10 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
         red->u.blackness = qxl->u.blackness;
         break;
     case QXL_DRAW_BLEND:
-        red->u.blend = qxl->u.blend;
+        red_get_blend_ptr(slots, group_id, &red->u.blend, &qxl->u.blend);
         break;
     case QXL_DRAW_COPY:
-        red->u.copy = qxl->u.copy;
+        red_get_copy_ptr(slots, group_id, &red->u.copy, &qxl->u.copy);
         break;
     case QXL_COPY_BITS:
         red->u.copy_bits = qxl->u.copy_bits;
diff --git a/server/red_worker.c b/server/red_worker.c
index e253c50..72eba10 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -3550,7 +3550,7 @@ static inline void red_update_streamable(RedWorker *worker, Drawable *drawable,
 
     if (drawable->tree_item.effect != QXL_EFFECT_OPAQUE ||
                                         red_drawable->type != QXL_DRAW_COPY ||
-                                        red_drawable->u.copy.rop_decriptor != SPICE_ROPD_OP_PUT) {
+                                        red_drawable->u.copy.rop_descriptor != SPICE_ROPD_OP_PUT) {
         return;
     }
 
@@ -9118,7 +9118,7 @@ static void red_send_image(DisplayChannel *display_channel, ImageItem *item)
     copy.base.box.bottom = item->pos.y + bitmap.y;
     copy.base.clip.type = SPICE_CLIP_TYPE_NONE;
     copy.base.clip.data = 0;
-    copy.data.rop_decriptor = SPICE_ROPD_OP_PUT;
+    copy.data.rop_descriptor = SPICE_ROPD_OP_PUT;
     copy.data.src_area.left = 0;
     copy.data.src_area.top = 0;
     copy.data.src_area.right = bitmap.x;
@@ -9222,7 +9222,7 @@ static void red_display_send_upgrade(DisplayChannel *display_channel, UpgradeIte
 
     red_drawable = item->drawable->red_drawable;
     ASSERT(red_drawable->type == QXL_DRAW_COPY);
-    ASSERT(red_drawable->u.copy.rop_decriptor == SPICE_ROPD_OP_PUT);
+    ASSERT(red_drawable->u.copy.rop_descriptor == SPICE_ROPD_OP_PUT);
     ASSERT(red_drawable->u.copy.mask.bitmap == 0);
 
     copy.base.surface_id = 0;
diff --git a/spice.proto b/spice.proto
index 38493a4..e1062eb 100644
--- a/spice.proto
+++ b/spice.proto
@@ -673,7 +673,7 @@ channel DisplayChannel : BaseChannel {
 	struct Copy {
 	    Image *src_bitmap;
 	    Rect src_area;
-	    ropd rop_decriptor;
+	    ropd rop_descriptor;
 	    image_scale_mode scale_mode;
 	    QMask mask @outvar(mask);
 	} data;
@@ -684,7 +684,7 @@ channel DisplayChannel : BaseChannel {
 	struct Blend {
 	    Image *src_bitmap;
 	    Rect src_area;
-	    ropd rop_decriptor;
+	    ropd rop_descriptor;
 	    image_scale_mode scale_mode;
 	    QMask mask @outvar(mask);
 	} @ctype(SpiceCopy) data;
diff --git a/spice1.proto b/spice1.proto
index a233ffc..98ffb49 100644
--- a/spice1.proto
+++ b/spice1.proto
@@ -622,7 +622,7 @@ channel DisplayChannel : BaseChannel {
 	struct Copy {
 	    Image *src_bitmap;
 	    Rect src_area;
-	    ropd rop_decriptor;
+	    ropd rop_descriptor;
 	    image_scale_mode scale_mode;
 	    QMask mask @outvar(mask);
 	} data;
@@ -633,7 +633,7 @@ channel DisplayChannel : BaseChannel {
 	struct Blend {
 	    Image *src_bitmap;
 	    Rect src_area;
-	    ropd rop_decriptor;
+	    ropd rop_descriptor;
 	    image_scale_mode scale_mode;
 	    QMask mask @outvar(mask);
 	} @ctype(SpiceCopy) data;
commit 63e07be145ae32bacef6f4229619a4d82a9b29cb
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 23 09:59:57 2010 +0200

    qxl abi: add missing QXLCopyBits

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 0620fcb..8590ec7 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -93,6 +93,9 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
     case QXL_DRAW_COPY:
         red->u.copy = qxl->u.copy;
         break;
+    case QXL_COPY_BITS:
+        red->u.copy_bits = qxl->u.copy_bits;
+        break;
     case QXL_DRAW_FILL:
         red_get_fill_ptr(slots, group_id, &red->u.fill, &qxl->u.fill);
         break;
@@ -153,6 +156,9 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
     case QXL_DRAW_COPY:
         red->u.copy = qxl->u.copy;
         break;
+    case QXL_COPY_BITS:
+        red->u.copy_bits = qxl->u.copy_bits;
+        break;
     case QXL_DRAW_FILL:
         red_get_fill_ptr(slots, group_id, &red->u.fill, &qxl->u.fill);
         break;
commit 08cfd6beaff1bfd59c5883b4d07a964eb8644595
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 23 09:49:35 2010 +0200

    qxl abi: parse QXLOpaque.
    
    Also adapt to tyops fix (s/rop_decriptor/rop_descriptor/).

diff --git a/common/canvas_base.c b/common/canvas_base.c
index 68ea1a6..debbd46 100644
--- a/common/canvas_base.c
+++ b/common/canvas_base.c
@@ -2518,7 +2518,7 @@ static void canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spice
     canvas_mask_pixman(canvas, &dest_region, &opaque->mask,
                        bbox->left, bbox->top);
 
-    rop = ropd_descriptor_to_rop(opaque->rop_decriptor,
+    rop = ropd_descriptor_to_rop(opaque->rop_descriptor,
                                  ROP_INPUT_BRUSH,
                                  ROP_INPUT_SRC);
 
diff --git a/common/gl_canvas.c b/common/gl_canvas.c
index 2773eda..1fe08ae 100644
--- a/common/gl_canvas.c
+++ b/common/gl_canvas.c
@@ -389,7 +389,7 @@ static void gl_canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, Sp
     set_clip(canvas, bbox, clip);
     set_mask(canvas, &opaque->mask, bbox->left, bbox->top);
 
-    glc_set_op(canvas->glc, (opaque->rop_decriptor & SPICE_ROPD_INVERS_SRC) ? GLC_OP_COPY_INVERTED :
+    glc_set_op(canvas->glc, (opaque->rop_descriptor & SPICE_ROPD_INVERS_SRC) ? GLC_OP_COPY_INVERTED :
                GLC_OP_COPY);
     surface = canvas_get_image(&canvas->base, opaque->src_bitmap, FALSE);
     surface_to_image(canvas, surface, &image, 0);
@@ -399,7 +399,7 @@ static void gl_canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, Sp
     pixman_image_unref(surface);
 
     set_brush(canvas, &opaque->brush);
-    set_op(canvas, opaque->rop_decriptor & ~SPICE_ROPD_INVERS_SRC);
+    set_op(canvas, opaque->rop_descriptor & ~SPICE_ROPD_INVERS_SRC);
     SET_GLC_RECT(&fill_rect, bbox);
     glc_fill_rect(canvas->glc, &fill_rect);
 
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 7dad295..0620fcb 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -28,6 +28,17 @@ static void red_get_fill_ptr(RedMemSlotInfo *slots, int group_id,
     red->mask           = qxl->mask;
 }
 
+static void red_get_opaque_ptr(RedMemSlotInfo *slots, int group_id,
+                               SpiceOpaque *red, QXLOpaque *qxl)
+{
+   red->src_bitmap     = qxl->src_bitmap;
+   red->src_area       = qxl->src_area;
+   red->brush          = qxl->brush;
+   red->rop_descriptor = qxl->rop_descriptor;
+   red->scale_mode     = qxl->scale_mode;
+   red->mask           = qxl->mask;
+}
+
 static void red_get_alpha_blend_ptr(RedMemSlotInfo *slots, int group_id,
                                     SpiceAlphaBlnd *red, QXLAlphaBlnd *qxl)
 {
@@ -85,6 +96,9 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
     case QXL_DRAW_FILL:
         red_get_fill_ptr(slots, group_id, &red->u.fill, &qxl->u.fill);
         break;
+    case QXL_DRAW_OPAQUE:
+        red_get_opaque_ptr(slots, group_id, &red->u.opaque, &qxl->u.opaque);
+        break;
     case QXL_DRAW_INVERS:
         red->u.invers = qxl->u.invers;
         break;
@@ -105,6 +119,9 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
     case QXL_DRAW_WHITENESS:
         red->u.whiteness = qxl->u.whiteness;
         break;
+    default:
+        red_error("unknown type");
+        break;
     };
 }
 
@@ -139,6 +156,9 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
     case QXL_DRAW_FILL:
         red_get_fill_ptr(slots, group_id, &red->u.fill, &qxl->u.fill);
         break;
+    case QXL_DRAW_OPAQUE:
+        red_get_opaque_ptr(slots, group_id, &red->u.opaque, &qxl->u.opaque);
+        break;
     case QXL_DRAW_INVERS:
         red->u.invers = qxl->u.invers;
         break;
@@ -159,6 +179,9 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
     case QXL_DRAW_WHITENESS:
         red->u.whiteness = qxl->u.whiteness;
         break;
+    default:
+        red_error("unknown type");
+        break;
     };
 }
 
diff --git a/server/red_worker.c b/server/red_worker.c
index a375a20..e253c50 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -7734,7 +7734,7 @@ static void red_lossy_send_qxl_draw_opaque(RedWorker *worker,
     BitmapData src_bitmap_data;
     BitmapData brush_bitmap_data;
 
-    rop = drawable->u.opaque.rop_decriptor;
+    rop = drawable->u.opaque.rop_descriptor;
     src_allowed_lossy = !((rop & SPICE_ROPD_OP_OR) ||
                           (rop & SPICE_ROPD_OP_AND) ||
                           (rop & SPICE_ROPD_OP_XOR));
diff --git a/spice.proto b/spice.proto
index f2a1903..38493a4 100644
--- a/spice.proto
+++ b/spice.proto
@@ -662,7 +662,7 @@ channel DisplayChannel : BaseChannel {
 	    Image *src_bitmap;
 	    Rect src_area;
 	    Brush brush;
-	    ropd rop_decriptor;
+	    ropd rop_descriptor;
 	    image_scale_mode scale_mode;
 	    QMask mask @outvar(mask);
 	} data;
diff --git a/spice1.proto b/spice1.proto
index 90a2c30..a233ffc 100644
--- a/spice1.proto
+++ b/spice1.proto
@@ -611,7 +611,7 @@ channel DisplayChannel : BaseChannel {
 	    Image *src_bitmap;
 	    Rect src_area;
 	    Brush brush;
-	    ropd rop_decriptor;
+	    ropd rop_descriptor;
 	    image_scale_mode scale_mode;
 	    QMask mask @outvar(mask);
 	} data;
commit ef3e20e29ff124eeb10729c0d512b1d231276394
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 23 08:53:04 2010 +0200

    qxl abi: parse QXLFill.
    
    Also adapt to tyops fix (s/rop_decriptor/rop_descriptor/).

diff --git a/common/canvas_base.c b/common/canvas_base.c
index 700fcb4..68ea1a6 100644
--- a/common/canvas_base.c
+++ b/common/canvas_base.c
@@ -2200,7 +2200,7 @@ static void canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceCl
     canvas_mask_pixman(canvas, &dest_region, &fill->mask,
                        bbox->left, bbox->top);
 
-    rop = ropd_descriptor_to_rop(fill->rop_decriptor,
+    rop = ropd_descriptor_to_rop(fill->rop_descriptor,
                                  ROP_INPUT_BRUSH,
                                  ROP_INPUT_DEST);
 
diff --git a/common/gl_canvas.c b/common/gl_canvas.c
index b16f25f..2773eda 100644
--- a/common/gl_canvas.c
+++ b/common/gl_canvas.c
@@ -347,7 +347,7 @@ static void gl_canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, Spic
     set_clip(canvas, bbox, clip);
     set_mask(canvas, &fill->mask, bbox->left, bbox->top);
     set_brush(canvas, &fill->brush);
-    set_op(canvas, fill->rop_decriptor);
+    set_op(canvas, fill->rop_descriptor);
     SET_GLC_RECT(&rect, bbox);
 
     glc_fill_rect(canvas->glc, &rect);
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index cbdbf72..7dad295 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -20,6 +20,14 @@
 #include "red_memslots.h"
 #include "red_parse_qxl.h"
 
+static void red_get_fill_ptr(RedMemSlotInfo *slots, int group_id,
+                             SpiceFill *red, QXLFill *qxl)
+{
+    red->brush          = qxl->brush;
+    red->rop_descriptor = qxl->rop_descriptor;
+    red->mask           = qxl->mask;
+}
+
 static void red_get_alpha_blend_ptr(RedMemSlotInfo *slots, int group_id,
                                     SpiceAlphaBlnd *red, QXLAlphaBlnd *qxl)
 {
@@ -75,7 +83,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
         red->u.copy = qxl->u.copy;
         break;
     case QXL_DRAW_FILL:
-        red->u.fill = qxl->u.fill;
+        red_get_fill_ptr(slots, group_id, &red->u.fill, &qxl->u.fill);
         break;
     case QXL_DRAW_INVERS:
         red->u.invers = qxl->u.invers;
@@ -129,7 +137,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
         red->u.copy = qxl->u.copy;
         break;
     case QXL_DRAW_FILL:
-        red->u.fill = qxl->u.fill;
+        red_get_fill_ptr(slots, group_id, &red->u.fill, &qxl->u.fill);
         break;
     case QXL_DRAW_INVERS:
         red->u.invers = qxl->u.invers;
diff --git a/server/red_worker.c b/server/red_worker.c
index d352972..a375a20 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -7645,7 +7645,7 @@ static void red_lossy_send_qxl_draw_fill(RedWorker *worker,
     BitmapData brush_bitmap_data;
     uint16_t rop;
 
-    rop = drawable->u.fill.rop_decriptor;
+    rop = drawable->u.fill.rop_descriptor;
 
     dest_allowed_lossy = !((rop & SPICE_ROPD_OP_OR) ||
                            (rop & SPICE_ROPD_OP_AND) ||
diff --git a/spice.proto b/spice.proto
index 1aa2788..f2a1903 100644
--- a/spice.proto
+++ b/spice.proto
@@ -651,7 +651,7 @@ channel DisplayChannel : BaseChannel {
 	DisplayBase base;
 	struct Fill {
 	    Brush brush @outvar(brush);
-	    uint16 rop_decriptor;
+	    uint16 rop_descriptor;
 	    QMask mask @outvar(mask);
 	} data;
     } draw_fill = 302;
diff --git a/spice1.proto b/spice1.proto
index dbe57b5..90a2c30 100644
--- a/spice1.proto
+++ b/spice1.proto
@@ -600,7 +600,7 @@ channel DisplayChannel : BaseChannel {
 	DisplayBase base;
 	struct Fill {
 	    Brush brush @outvar(brush);
-	    uint16 rop_decriptor;
+	    uint16 rop_descriptor;
 	    QMask mask @outvar(mask);
 	} data;
     } draw_fill = 302;
commit 85155b3f441e178858a592341e32a07b82d17dbe
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Jun 22 17:40:34 2010 +0200

    qxl abi: parse QXLAlphaBlnd (+Compat)

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index aafd75a..cbdbf72 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -20,6 +20,23 @@
 #include "red_memslots.h"
 #include "red_parse_qxl.h"
 
+static void red_get_alpha_blend_ptr(RedMemSlotInfo *slots, int group_id,
+                                    SpiceAlphaBlnd *red, QXLAlphaBlnd *qxl)
+{
+    red->alpha_flags = qxl->alpha_flags;
+    red->alpha       = qxl->alpha;
+    red->src_bitmap  = qxl->src_bitmap;
+    red->src_area    = qxl->src_area;
+}
+
+static void red_get_alpha_blend_ptr_compat(RedMemSlotInfo *slots, int group_id,
+                                           SpiceAlphaBlnd *red, QXLCompatAlphaBlnd *qxl)
+{
+    red->alpha       = qxl->alpha;
+    red->src_bitmap  = qxl->src_bitmap;
+    red->src_area    = qxl->src_area;
+}
+
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr)
 {
@@ -45,7 +62,8 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
     red->type = qxl->type;
     switch (red->type) {
     case QXL_DRAW_ALPHA_BLEND:
-        red->u.alpha_blend = qxl->u.alpha_blend;
+        red_get_alpha_blend_ptr(slots, group_id,
+                                &red->u.alpha_blend, &qxl->u.alpha_blend);
         break;
     case QXL_DRAW_BLACKNESS:
         red->u.blackness = qxl->u.blackness;
@@ -98,7 +116,8 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
     red->type = qxl->type;
     switch (red->type) {
     case QXL_DRAW_ALPHA_BLEND:
-        red->u.alpha_blend = qxl->u.alpha_blend;
+        red_get_alpha_blend_ptr_compat(slots, group_id,
+                                       &red->u.alpha_blend, &qxl->u.alpha_blend);
         break;
     case QXL_DRAW_BLACKNESS:
         red->u.blackness = qxl->u.blackness;
commit 856e2ba355a3c277f4dbbfe417f113cef35d7a87
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Jun 22 11:48:33 2010 +0200

    qxl abi: parse QXLCompatDrawable.

diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index b22cb83..aafd75a 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -82,6 +82,59 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
     };
 }
 
+void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
+                             RedDrawable *red, SPICE_ADDRESS addr)
+{
+    QXLCompatDrawable *qxl;
+
+    qxl = (QXLCompatDrawable *)get_virt(slots, addr, sizeof(*qxl), group_id);
+    red->release_info     = &qxl->release_info;
+
+    red->bbox             = qxl->bbox;
+    red->clip             = qxl->clip;
+    red->effect           = qxl->effect;
+    red->mm_time          = qxl->mm_time;
+
+    red->type = qxl->type;
+    switch (red->type) {
+    case QXL_DRAW_ALPHA_BLEND:
+        red->u.alpha_blend = qxl->u.alpha_blend;
+        break;
+    case QXL_DRAW_BLACKNESS:
+        red->u.blackness = qxl->u.blackness;
+        break;
+    case QXL_DRAW_BLEND:
+        red->u.blend = qxl->u.blend;
+        break;
+    case QXL_DRAW_COPY:
+        red->u.copy = qxl->u.copy;
+        break;
+    case QXL_DRAW_FILL:
+        red->u.fill = qxl->u.fill;
+        break;
+    case QXL_DRAW_INVERS:
+        red->u.invers = qxl->u.invers;
+        break;
+    case QXL_DRAW_NOP:
+        break;
+    case QXL_DRAW_ROP3:
+        red->u.rop3 = qxl->u.rop3;
+        break;
+    case QXL_DRAW_STROKE:
+        red->u.stroke = qxl->u.stroke;
+        break;
+    case QXL_DRAW_TEXT:
+        red->u.text = qxl->u.text;
+        break;
+    case QXL_DRAW_TRANSPARENT:
+        red->u.transparent = qxl->u.transparent;
+        break;
+    case QXL_DRAW_WHITENESS:
+        red->u.whiteness = qxl->u.whiteness;
+        break;
+    };
+}
+
 void red_put_drawable(RedDrawable *red)
 {
     /* nothing yet */
diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h
index d8955d2..5737b55 100644
--- a/server/red_parse_qxl.h
+++ b/server/red_parse_qxl.h
@@ -55,6 +55,8 @@ typedef struct SPICE_ATTR_PACKED RedDrawable {
 
 void red_get_drawable(RedMemSlotInfo *slots, int group_id,
                       RedDrawable *red, SPICE_ADDRESS addr);
+void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
+                             RedDrawable *red, SPICE_ADDRESS addr);
 void red_put_drawable(RedDrawable *red);
 
 #endif
diff --git a/server/red_worker.c b/server/red_worker.c
index 34d89ba..d352972 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -5031,8 +5031,13 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size)
         switch (ext_cmd.cmd.type) {
         case QXL_CMD_DRAW: {
             RedDrawable *drawable = spice_new0(RedDrawable, 1);
-            red_get_drawable(&worker->mem_slots, ext_cmd.group_id,
-                             drawable, ext_cmd.cmd.data);
+            if (ext_cmd.flags & QXL_COMMAND_FLAG_COMPAT) {
+                red_get_compat_drawable(&worker->mem_slots, ext_cmd.group_id,
+                                        drawable, ext_cmd.cmd.data);
+            } else {
+                red_get_drawable(&worker->mem_slots, ext_cmd.group_id,
+                                 drawable, ext_cmd.cmd.data);
+            }
             red_process_drawable(worker, drawable, ext_cmd.group_id);
             break;
         }
commit 11034dda428865e442dd2c981851500ed96b9a0c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Jun 22 10:59:52 2010 +0200

    qxl abi: parse QXLDrawable.

diff --git a/server/Makefile.am b/server/Makefile.am
index 447d145..a2e4967 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -91,6 +91,8 @@ libspice_server_la_SOURCES =			\
 	red_dispatcher.h			\
 	red_memslots.c				\
 	red_memslots.h				\
+	red_parse_qxl.c				\
+	red_parse_qxl.h				\
 	reds.c					\
 	reds.h					\
 	stat.h					\
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
new file mode 100644
index 0000000..b22cb83
--- /dev/null
+++ b/server/red_parse_qxl.c
@@ -0,0 +1,88 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009,2010 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   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 "red_common.h"
+#include "red_memslots.h"
+#include "red_parse_qxl.h"
+
+void red_get_drawable(RedMemSlotInfo *slots, int group_id,
+                      RedDrawable *red, SPICE_ADDRESS addr)
+{
+    QXLDrawable *qxl;
+    int i;
+
+    qxl = (QXLDrawable *)get_virt(slots, addr, sizeof(*qxl), group_id);
+    red->release_info     = &qxl->release_info;
+
+    red->bbox             = qxl->bbox;
+    red->clip             = qxl->clip;
+    red->effect           = qxl->effect;
+    red->mm_time          = qxl->mm_time;
+    red->self_bitmap      = qxl->self_bitmap;
+    red->self_bitmap_area = qxl->self_bitmap_area;
+    red->surface_id       = qxl->surface_id;
+
+    for (i = 0; i < 3; i++) {
+        red->surfaces_dest[i] = qxl->surfaces_dest[i];
+        red->surfaces_rects[i] = qxl->surfaces_rects[i];
+    }
+
+    red->type = qxl->type;
+    switch (red->type) {
+    case QXL_DRAW_ALPHA_BLEND:
+        red->u.alpha_blend = qxl->u.alpha_blend;
+        break;
+    case QXL_DRAW_BLACKNESS:
+        red->u.blackness = qxl->u.blackness;
+        break;
+    case QXL_DRAW_BLEND:
+        red->u.blend = qxl->u.blend;
+        break;
+    case QXL_DRAW_COPY:
+        red->u.copy = qxl->u.copy;
+        break;
+    case QXL_DRAW_FILL:
+        red->u.fill = qxl->u.fill;
+        break;
+    case QXL_DRAW_INVERS:
+        red->u.invers = qxl->u.invers;
+        break;
+    case QXL_DRAW_NOP:
+        break;
+    case QXL_DRAW_ROP3:
+        red->u.rop3 = qxl->u.rop3;
+        break;
+    case QXL_DRAW_STROKE:
+        red->u.stroke = qxl->u.stroke;
+        break;
+    case QXL_DRAW_TEXT:
+        red->u.text = qxl->u.text;
+        break;
+    case QXL_DRAW_TRANSPARENT:
+        red->u.transparent = qxl->u.transparent;
+        break;
+    case QXL_DRAW_WHITENESS:
+        red->u.whiteness = qxl->u.whiteness;
+        break;
+    };
+}
+
+void red_put_drawable(RedDrawable *red)
+{
+    /* nothing yet */
+}
diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h
new file mode 100644
index 0000000..d8955d2
--- /dev/null
+++ b/server/red_parse_qxl.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009,2010 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef RED_ABI_TRANSLATE_H
+#define RED_ABI_TRANSLATE_H
+
+#include <spice/qxl_dev.h>
+#include <spice/start-packed.h>
+#include "red_common.h"
+#include "red_memslots.h"
+
+typedef struct SPICE_ATTR_PACKED RedDrawable {
+    QXLReleaseInfo *release_info;
+    uint32_t surface_id;
+    uint8_t effect;
+    uint8_t type;
+    uint8_t self_bitmap;
+    SpiceRect self_bitmap_area;
+    SpiceRect bbox;
+    SpiceClip clip;
+    uint32_t mm_time;
+    int32_t surfaces_dest[3];
+    SpiceRect surfaces_rects[3];
+    union {
+        SpiceFill fill;
+        SpiceOpaque opaque;
+        SpiceCopy copy;
+        SpiceTransparent transparent;
+        SpiceAlphaBlnd alpha_blend;
+        QXLCopyBits copy_bits;
+        SpiceBlend blend;
+        SpiceRop3 rop3;
+        SpiceStroke stroke;
+        SpiceText text;
+        SpiceBlackness blackness;
+        SpiceInvers invers;
+        SpiceWhiteness whiteness;
+    } u;
+} RedDrawable;
+
+void red_get_drawable(RedMemSlotInfo *slots, int group_id,
+                      RedDrawable *red, SPICE_ADDRESS addr);
+void red_put_drawable(RedDrawable *red);
+
+#endif
diff --git a/server/red_worker.c b/server/red_worker.c
index 97ca75d..34d89ba 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -48,6 +48,7 @@
 #include "ring.h"
 #include "mjpeg_encoder.h"
 #include "red_memslots.h"
+#include "red_parse_qxl.h"
 #include "jpeg_encoder.h"
 #include "rect.h"
 #include "marshaller.h"
@@ -621,7 +622,7 @@ typedef struct GlzDrawableInstanceItem {
 struct RedGlzDrawable {
     RingItem link;    // ordered by the time it was encoded
     RingItem surface_link;
-    QXLDrawable *qxl_drawable;
+    RedDrawable *red_drawable;
     Drawable    *drawable;
     uint32_t     group_id;
     int32_t      surface_id;
@@ -805,7 +806,7 @@ struct Drawable {
 #ifdef UPDATE_AREA_BY_TREE
     RingItem collect_link;
 #endif
-    QXLDrawable *qxl_drawable;
+    RedDrawable *red_drawable;
 
     RedGlzDrawable *red_glz_drawable;
 
@@ -1195,7 +1196,7 @@ char *draw_type_to_str(uint8_t type)
     }
 }
 
-static void show_qxl_drawable(RedWorker *worker, QXLDrawable *drawable, const char *prefix)
+static void show_red_drawable(RedWorker *worker, RedDrawable *drawable, const char *prefix)
 {
     if (prefix) {
         printf("%s: ", prefix);
@@ -1602,7 +1603,7 @@ static inline void set_surface_release_info(RedWorker *worker, uint32_t surface_
     }
 }
 
-static inline void free_qxl_drawable(RedWorker *worker, QXLDrawable *drawable, uint32_t group_id,
+static inline void free_red_drawable(RedWorker *worker, RedDrawable *drawable, uint32_t group_id,
                                      uint8_t *self_bitmap, int surface_id)
 {
     QXLReleaseInfoExt release_info_ext;
@@ -1612,8 +1613,10 @@ static inline void free_qxl_drawable(RedWorker *worker, QXLDrawable *drawable, u
         free(self_bitmap);
     }
     release_info_ext.group_id = group_id;
-    release_info_ext.info = &drawable->release_info;
+    release_info_ext.info = drawable->release_info;
     worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
+    red_put_drawable(drawable);
+    free(drawable);
 }
 
 static void remove_depended_item(DependItem *item)
@@ -1670,7 +1673,7 @@ static inline void release_drawable(RedWorker *worker, Drawable *item)
         if (item->red_glz_drawable) {
             item->red_glz_drawable->drawable = NULL;
         } else { // no reference to the qxl drawable left
-            free_qxl_drawable(worker, item->qxl_drawable, item->group_id, item->self_bitmap,
+            free_red_drawable(worker, item->red_drawable, item->group_id, item->self_bitmap,
                               item->surface_id);
         }
         free_drawable(worker, item);
@@ -1731,10 +1734,10 @@ static inline void red_add_item_trace(RedWorker *worker, Drawable *item)
     trace->frames_count = item->frames_count;
     trace->gradual_frames_count = item->gradual_frames_count;
     trace->last_gradual_frame = item->last_gradual_frame;
-    SpiceRect* src_area = &item->qxl_drawable->u.copy.src_area;
+    SpiceRect* src_area = &item->red_drawable->u.copy.src_area;
     trace->width = src_area->right - src_area->left;
     trace->height = src_area->bottom - src_area->top;
-    trace->dest_area = item->qxl_drawable->bbox;
+    trace->dest_area = item->red_drawable->bbox;
 }
 
 #endif
@@ -1753,7 +1756,7 @@ static void red_flush_source_surfaces(RedWorker *worker, Drawable *drawable)
         surface_id = drawable->surfaces_dest[x];
         if (surface_id != -1 && drawable->depend_items[x].drawable) {
             remove_depended_item(&drawable->depend_items[x]);
-            surface_flush(worker, surface_id, &drawable->qxl_drawable->surfaces_rects[x]);
+            surface_flush(worker, surface_id, &drawable->red_drawable->surfaces_rects[x]);
         }
     }
 }
@@ -2366,19 +2369,19 @@ static int is_equal_line_attr(SpiceLineAttr *a1, SpiceLineAttr *a2)
 // partial imp
 static int is_same_geometry(RedWorker *worker, Drawable *d1, Drawable *d2)
 {
-    if (d1->qxl_drawable->type != d2->qxl_drawable->type) {
+    if (d1->red_drawable->type != d2->red_drawable->type) {
         return FALSE;
     }
 
-    switch (d1->qxl_drawable->type) {
+    switch (d1->red_drawable->type) {
     case QXL_DRAW_STROKE:
-        return is_equal_line_attr(&d1->qxl_drawable->u.stroke.attr,
-                                  &d2->qxl_drawable->u.stroke.attr) &&
-               is_equal_path(worker, d1->qxl_drawable->u.stroke.path,
-                             d2->qxl_drawable->u.stroke.path, d1->group_id,
+        return is_equal_line_attr(&d1->red_drawable->u.stroke.attr,
+                                  &d2->red_drawable->u.stroke.attr) &&
+               is_equal_path(worker, d1->red_drawable->u.stroke.path,
+                             d2->red_drawable->u.stroke.path, d1->group_id,
                              d2->group_id);
     case QXL_DRAW_FILL:
-        return rect_is_equal(&d1->qxl_drawable->bbox, &d2->qxl_drawable->bbox);
+        return rect_is_equal(&d1->red_drawable->bbox, &d2->red_drawable->bbox);
     default:
         return FALSE;
     }
@@ -2390,11 +2393,11 @@ static int is_same_drawable(RedWorker *worker, Drawable *d1, Drawable *d2)
         return FALSE;
     }
 
-    switch (d1->qxl_drawable->type) {
+    switch (d1->red_drawable->type) {
     case QXL_DRAW_STROKE:
-        return is_equal_brush(&d1->qxl_drawable->u.stroke.brush, &d2->qxl_drawable->u.stroke.brush);
+        return is_equal_brush(&d1->red_drawable->u.stroke.brush, &d2->red_drawable->u.stroke.brush);
     case QXL_DRAW_FILL:
-        return is_equal_brush(&d1->qxl_drawable->u.fill.brush, &d2->qxl_drawable->u.fill.brush);
+        return is_equal_brush(&d1->red_drawable->u.fill.brush, &d2->red_drawable->u.fill.brush);
     default:
         return FALSE;
     }
@@ -2449,7 +2452,7 @@ static void push_stream_clip_by_drawable(DisplayChannel* channel, StreamAgent *a
         PANIC("alloc failed");
     }
 
-    if (drawable->qxl_drawable->clip.type == SPICE_CLIP_TYPE_NONE) {
+    if (drawable->red_drawable->clip.type == SPICE_CLIP_TYPE_NONE) {
         item->n_rects = 0;
         item->rects = NULL;
         item->clip_type = SPICE_CLIP_TYPE_NONE;
@@ -2769,8 +2772,8 @@ static void red_create_stream(RedWorker *worker, Drawable *drawable)
         return;
     }
 
-    ASSERT(drawable->qxl_drawable->type == QXL_DRAW_COPY);
-    src_rect = &drawable->qxl_drawable->u.copy.src_area;
+    ASSERT(drawable->red_drawable->type == QXL_DRAW_COPY);
+    src_rect = &drawable->red_drawable->u.copy.src_area;
     stream_width = SPICE_ALIGN(src_rect->right - src_rect->left, 2);
     stream_height = SPICE_ALIGN(src_rect->bottom - src_rect->top, 2);
 
@@ -2782,11 +2785,11 @@ static void red_create_stream(RedWorker *worker, Drawable *drawable)
     stream->last_time = drawable->creation_time;
     stream->width = src_rect->right - src_rect->left;
     stream->height = src_rect->bottom - src_rect->top;
-    stream->dest_area = drawable->qxl_drawable->bbox;
+    stream->dest_area = drawable->red_drawable->bbox;
 #endif
     stream->refs = 1;
     stream->bit_rate = get_bit_rate(stream_width, stream_height);
-    QXLImage *qxl_image = (QXLImage *)get_virt(&worker->mem_slots, drawable->qxl_drawable->u.copy.src_bitmap,
+    QXLImage *qxl_image = (QXLImage *)get_virt(&worker->mem_slots, drawable->red_drawable->u.copy.src_bitmap,
                                                sizeof(QXLImage), drawable->group_id);
     stream->top_down = !!(qxl_image->bitmap.flags & SPICE_BITMAP_FLAGS_TOP_DOWN);
     drawable->stream = stream;
@@ -2853,27 +2856,27 @@ static inline int __red_is_next_stream_frame(RedWorker *worker,
                                              const red_time_t other_time,
                                              const Stream *stream)
 {
-    QXLDrawable *qxl_drawable;
+    RedDrawable *red_drawable;
 
     if (candidate->creation_time - other_time >
             (stream ? RED_STREAM_CONTINUS_MAX_DELTA : RED_STREAM_DETACTION_MAX_DELTA)) {
         return FALSE;
     }
 
-    qxl_drawable = candidate->qxl_drawable;
+    red_drawable = candidate->red_drawable;
 
-    if (!rect_is_equal(&qxl_drawable->bbox, other_dest)) {
+    if (!rect_is_equal(&red_drawable->bbox, other_dest)) {
         return FALSE;
     }
 
-    SpiceRect* candidate_src = &qxl_drawable->u.copy.src_area;
+    SpiceRect* candidate_src = &red_drawable->u.copy.src_area;
     if (candidate_src->right - candidate_src->left != other_src_width ||
         candidate_src->bottom - candidate_src->top != other_src_height) {
         return FALSE;
     }
 
     if (stream) {
-        QXLImage *qxl_image = (QXLImage *)get_virt(&worker->mem_slots, qxl_drawable->u.copy.src_bitmap,
+        QXLImage *qxl_image = (QXLImage *)get_virt(&worker->mem_slots, red_drawable->u.copy.src_bitmap,
                                                    sizeof(QXLImage), candidate->group_id);
         if (stream->top_down != !!(qxl_image->bitmap.flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) {
             return FALSE;
@@ -2889,10 +2892,10 @@ static inline int red_is_next_stream_frame(RedWorker *worker, const Drawable *ca
         return FALSE;
     }
 
-    SpiceRect* prev_src = &prev->qxl_drawable->u.copy.src_area;
+    SpiceRect* prev_src = &prev->red_drawable->u.copy.src_area;
     return __red_is_next_stream_frame(worker, candidate, prev_src->right - prev_src->left,
                                       prev_src->bottom - prev_src->top,
-                                      &prev->qxl_drawable->bbox, prev->creation_time,
+                                      &prev->red_drawable->bbox, prev->creation_time,
                                       prev->stream);
 }
 
@@ -2901,16 +2904,16 @@ static inline int red_is_next_stream_frame(RedWorker *worker, const Drawable *ca
 static inline int red_is_next_stream_frame(RedWorker *worker, Drawable *candidate, Drawable *prev)
 {
     QXLImage *qxl_image;
-    QXLDrawable *qxl_drawable;
-    QXLDrawable *prev_qxl_drawable;
+    RedDrawable *red_drawable;
+    RedDrawable *prev_red_drawable;
 
     if (candidate->creation_time - prev->creation_time >
             ((prev->stream) ? RED_STREAM_CONTINUS_MAX_DELTA : RED_STREAM_DETACTION_MAX_DELTA)) {
         return FALSE;
     }
 
-    qxl_drawable = candidate->qxl_drawable;
-    prev_qxl_drawable = prev->qxl_drawable;
+    qxl_drawable = candidate->red_drawable;
+    prev_qxl_drawable = prev->red_drawable;
     if (qxl_drawable->type != QXL_DRAW_COPY || prev_qxl_drawable->type != QXL_DRAW_COPY) {
         return FALSE;
     }
@@ -2995,7 +2998,7 @@ static inline void pre_stream_item_swap(RedWorker *worker, Stream *stream)
 static inline void red_update_copy_graduality(RedWorker* worker, Drawable *drawable)
 {
     QXLImage *qxl_image;
-    ASSERT(drawable->qxl_drawable->type == QXL_DRAW_COPY);
+    ASSERT(drawable->red_drawable->type == QXL_DRAW_COPY);
 
     if (worker->streaming_video != STREAM_VIDEO_FILTER) {
         drawable->copy_bitmap_graduality = BITMAP_GRADUAL_INVALID;
@@ -3006,7 +3009,7 @@ static inline void red_update_copy_graduality(RedWorker* worker, Drawable *drawa
         return; // already set
     }
 
-    qxl_image = (QXLImage *)get_virt(&worker->mem_slots, drawable->qxl_drawable->u.copy.src_bitmap,
+    qxl_image = (QXLImage *)get_virt(&worker->mem_slots, drawable->red_drawable->u.copy.src_bitmap,
                                      sizeof(QXLImage), drawable->group_id);
 
     if (!BITMAP_FMT_IS_RGB[qxl_image->bitmap.format] || _stride_is_extra(&qxl_image->bitmap) ||
@@ -3530,14 +3533,14 @@ static inline int red_current_add_with_shadow(RedWorker *worker, Ring *ring, Dra
     return TRUE;
 }
 
-static inline int has_shadow(QXLDrawable *drawable)
+static inline int has_shadow(RedDrawable *drawable)
 {
     return drawable->type == QXL_COPY_BITS;
 }
 
 #ifdef STREAM_TRACE
 static inline void red_update_streamable(RedWorker *worker, Drawable *drawable,
-                                         QXLDrawable *qxl_drawable)
+                                         RedDrawable *red_drawable)
 {
     QXLImage *qxl_image;
 
@@ -3546,12 +3549,12 @@ static inline void red_update_streamable(RedWorker *worker, Drawable *drawable,
     }
 
     if (drawable->tree_item.effect != QXL_EFFECT_OPAQUE ||
-                                        qxl_drawable->type != QXL_DRAW_COPY ||
-                                        qxl_drawable->u.copy.rop_decriptor != SPICE_ROPD_OP_PUT) {
+                                        red_drawable->type != QXL_DRAW_COPY ||
+                                        red_drawable->u.copy.rop_decriptor != SPICE_ROPD_OP_PUT) {
         return;
     }
 
-    qxl_image = (QXLImage *)get_virt(&worker->mem_slots, qxl_drawable->u.copy.src_bitmap, sizeof(QXLImage),
+    qxl_image = (QXLImage *)get_virt(&worker->mem_slots, red_drawable->u.copy.src_bitmap, sizeof(QXLImage),
                                      drawable->group_id);
     if (qxl_image->descriptor.type != SPICE_IMAGE_TYPE_BITMAP) {
         return;
@@ -3561,7 +3564,7 @@ static inline void red_update_streamable(RedWorker *worker, Drawable *drawable,
         SpiceRect* rect;
         int size;
 
-        rect = &drawable->qxl_drawable->u.copy.src_area;
+        rect = &drawable->red_drawable->u.copy.src_area;
         size = (rect->right - rect->left) * (rect->bottom - rect->top);
         if (size < RED_STREAM_MIN_SIZE) {
             return;
@@ -3574,22 +3577,22 @@ static inline void red_update_streamable(RedWorker *worker, Drawable *drawable,
 #endif
 
 static inline int red_current_add_qxl(RedWorker *worker, Ring *ring, Drawable *drawable,
-                                      QXLDrawable *qxl_drawable)
+                                      RedDrawable *red_drawable)
 {
     int ret;
 
-    if (has_shadow(qxl_drawable)) {
+    if (has_shadow(red_drawable)) {
         SpicePoint delta;
 
 #ifdef RED_WORKER_STAT
         ++worker->add_with_shadow_count;
 #endif
-        delta.x = qxl_drawable->u.copy_bits.src_pos.x - qxl_drawable->bbox.left;
-        delta.y = qxl_drawable->u.copy_bits.src_pos.y - qxl_drawable->bbox.top;
+        delta.x = red_drawable->u.copy_bits.src_pos.x - red_drawable->bbox.left;
+        delta.y = red_drawable->u.copy_bits.src_pos.y - red_drawable->bbox.top;
         ret = red_current_add_with_shadow(worker, ring, drawable, &delta);
     } else {
 #ifdef STREAM_TRACE
-        red_update_streamable(worker, drawable, qxl_drawable);
+        red_update_streamable(worker, drawable, red_drawable);
 #endif
         ret = red_current_add(worker, ring, drawable);
     }
@@ -3689,7 +3692,7 @@ static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable)
     int bpp;
     int all_set;
 
-    if (!drawable->qxl_drawable->self_bitmap) {
+    if (!drawable->red_drawable->self_bitmap) {
         return TRUE;
     }
 
@@ -3698,8 +3701,8 @@ static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable)
 
     bpp = SPICE_SURFACE_FMT_DEPTH(surface->context.format) / 8;
 
-    width = drawable->qxl_drawable->bbox.right - drawable->qxl_drawable->bbox.left;
-    height = drawable->qxl_drawable->bbox.bottom - drawable->qxl_drawable->bbox.top;
+    width = drawable->red_drawable->bbox.right - drawable->red_drawable->bbox.left;
+    height = drawable->red_drawable->bbox.bottom - drawable->red_drawable->bbox.top;
     dest_stride = SPICE_ALIGN(width * bpp, 4);
 
     image = spice_malloc_n_m(height, dest_stride, sizeof(QXLImage));
@@ -3719,7 +3722,7 @@ static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable)
     image->bitmap.palette = 0;
 
     red_get_area(worker, drawable->surface_id,
-                 &drawable->qxl_drawable->self_bitmap_area, dest, dest_stride, TRUE);
+                 &drawable->red_drawable->self_bitmap_area, dest, dest_stride, TRUE);
 
     /* For 32bit non-primary surfaces we need to keep any non-zero
        high bytes as the surface may be used as source to an alpha_blend */
@@ -3756,7 +3759,7 @@ static void free_one_drawable(RedWorker *worker, int force_glz_free)
     container_cleanup(worker, container);
 }
 
-static Drawable *get_drawable(RedWorker *worker, uint8_t effect, QXLDrawable *qxl_drawable,
+static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *red_drawable,
                               uint32_t group_id) {
     Drawable *drawable;
     struct timespec time;
@@ -3782,13 +3785,13 @@ static Drawable *get_drawable(RedWorker *worker, uint8_t effect, QXLDrawable *qx
     region_init(&drawable->tree_item.base.rgn);
     drawable->tree_item.effect = effect;
     red_pipe_item_init(&drawable->pipe_item, PIPE_ITEM_TYPE_DRAW);
-    drawable->qxl_drawable = qxl_drawable;
+    drawable->red_drawable = red_drawable;
     drawable->group_id = group_id;
 
-    drawable->surface_id = qxl_drawable->surface_id;
+    drawable->surface_id = red_drawable->surface_id;
     validate_surface(worker, drawable->surface_id);
     for (x = 0; x < 3; ++x) {
-        drawable->surfaces_dest[x] = qxl_drawable->surfaces_dest[x];
+        drawable->surfaces_dest[x] = red_drawable->surfaces_dest[x];
         if (drawable->surfaces_dest[x] != -1) {
             validate_surface(worker, drawable->surfaces_dest[x]);
         }
@@ -3808,7 +3811,7 @@ static inline int red_handle_depends_on_target_surface(RedWorker *worker, uint32
         Drawable *drawable;
         DependItem *depended_item = SPICE_CONTAINEROF(ring_item, DependItem, ring_item);
         drawable = depended_item->drawable;
-        surface_flush(worker, drawable->surface_id, &drawable->qxl_drawable->bbox);
+        surface_flush(worker, drawable->surface_id, &drawable->red_drawable->bbox);
     }
 
     return TRUE;
@@ -3862,7 +3865,7 @@ static inline void red_inc_surfaces_drawable_dependencies(RedWorker *worker, Dra
     }
 }
 
-static inline void red_process_drawable(RedWorker *worker, QXLDrawable *drawable, uint32_t group_id)
+static inline void red_process_drawable(RedWorker *worker, RedDrawable *drawable, uint32_t group_id)
 {
     int surface_id;
     Drawable *item = get_drawable(worker, drawable->effect, drawable, group_id);
@@ -4437,7 +4440,7 @@ static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable)
 {
     RedSurface *surface;
     SpiceCanvas *canvas; 
-    SpiceClip clip = drawable->qxl_drawable->clip;
+    SpiceClip clip = drawable->red_drawable->clip;
 
     surface = &worker->surfaces[drawable->surface_id];
     canvas = surface->context.canvas;
@@ -4447,124 +4450,124 @@ static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable)
 
     worker->preload_group_id = drawable->group_id;
 
-    region_add(&surface->draw_dirty_region, &drawable->qxl_drawable->bbox);
+    region_add(&surface->draw_dirty_region, &drawable->red_drawable->bbox);
 
     localize_clip(worker, &clip, drawable->group_id);
-    switch (drawable->qxl_drawable->type) {
+    switch (drawable->red_drawable->type) {
     case QXL_DRAW_FILL: {
-        SpiceFill fill = drawable->qxl_drawable->u.fill;
+        SpiceFill fill = drawable->red_drawable->u.fill;
         localize_brush(worker, &fill.brush, drawable->group_id);
         localize_mask(worker, &fill.mask, drawable->group_id);
-        canvas->ops->draw_fill(canvas, &drawable->qxl_drawable->bbox,
+        canvas->ops->draw_fill(canvas, &drawable->red_drawable->bbox,
                                &clip, &fill); unlocalize_mask(&fill.mask);
         unlocalize_brush(&fill.brush);
         break;
     }
     case QXL_DRAW_OPAQUE: {
-        SpiceOpaque opaque = drawable->qxl_drawable->u.opaque;
+        SpiceOpaque opaque = drawable->red_drawable->u.opaque;
         localize_brush(worker, &opaque.brush, drawable->group_id);
         localize_bitmap(worker, &opaque.src_bitmap, drawable->group_id);
         localize_mask(worker, &opaque.mask, drawable->group_id);
-        canvas->ops->draw_opaque(canvas, &drawable->qxl_drawable->bbox, &clip, &opaque);
+        canvas->ops->draw_opaque(canvas, &drawable->red_drawable->bbox, &clip, &opaque);
         unlocalize_mask(&opaque.mask);
         unlocalize_bitmap(&opaque.src_bitmap);
         unlocalize_brush(&opaque.brush);
         break;
     }
     case QXL_DRAW_COPY: {
-        SpiceCopy copy = drawable->qxl_drawable->u.copy;
+        SpiceCopy copy = drawable->red_drawable->u.copy;
         localize_bitmap(worker, &copy.src_bitmap, drawable->group_id);
         localize_mask(worker, &copy.mask, drawable->group_id);
-        canvas->ops->draw_copy(canvas, &drawable->qxl_drawable->bbox,
+        canvas->ops->draw_copy(canvas, &drawable->red_drawable->bbox,
                                &clip, &copy);
         unlocalize_mask(&copy.mask);
         unlocalize_bitmap(&copy.src_bitmap);
         break;
     }
     case QXL_DRAW_TRANSPARENT: {
-        SpiceTransparent transparent = drawable->qxl_drawable->u.transparent;
+        SpiceTransparent transparent = drawable->red_drawable->u.transparent;
         localize_bitmap(worker, &transparent.src_bitmap, drawable->group_id);
         canvas->ops->draw_transparent(canvas,
-                                      &drawable->qxl_drawable->bbox, &clip, &transparent);
+                                      &drawable->red_drawable->bbox, &clip, &transparent);
         unlocalize_bitmap(&transparent.src_bitmap);
         break;
     }
     case QXL_DRAW_ALPHA_BLEND: {
-        SpiceAlphaBlnd alpha_blend = drawable->qxl_drawable->u.alpha_blend;
+        SpiceAlphaBlnd alpha_blend = drawable->red_drawable->u.alpha_blend;
         localize_bitmap(worker, &alpha_blend.src_bitmap, drawable->group_id);
         canvas->ops->draw_alpha_blend(canvas,
-                                      &drawable->qxl_drawable->bbox, &clip, &alpha_blend);
+                                      &drawable->red_drawable->bbox, &clip, &alpha_blend);
         unlocalize_bitmap(&alpha_blend.src_bitmap);
         break;
     }
     case QXL_COPY_BITS: {
-        canvas->ops->copy_bits(canvas, &drawable->qxl_drawable->bbox,
-                               &clip, &drawable->qxl_drawable->u.copy_bits.src_pos);
+        canvas->ops->copy_bits(canvas, &drawable->red_drawable->bbox,
+                               &clip, &drawable->red_drawable->u.copy_bits.src_pos);
         break;
     }
     case QXL_DRAW_BLEND: {
-        SpiceBlend blend = drawable->qxl_drawable->u.blend;
+        SpiceBlend blend = drawable->red_drawable->u.blend;
         localize_bitmap(worker, &blend.src_bitmap, drawable->group_id);
         localize_mask(worker, &blend.mask, drawable->group_id);
-        canvas->ops->draw_blend(canvas, &drawable->qxl_drawable->bbox,
+        canvas->ops->draw_blend(canvas, &drawable->red_drawable->bbox,
                                 &clip, &blend);
         unlocalize_mask(&blend.mask);
         unlocalize_bitmap(&blend.src_bitmap);
         break;
     }
     case QXL_DRAW_BLACKNESS: {
-        SpiceBlackness blackness = drawable->qxl_drawable->u.blackness;
+        SpiceBlackness blackness = drawable->red_drawable->u.blackness;
         localize_mask(worker, &blackness.mask, drawable->group_id);
         canvas->ops->draw_blackness(canvas,
-                                    &drawable->qxl_drawable->bbox, &clip, &blackness);
+                                    &drawable->red_drawable->bbox, &clip, &blackness);
         unlocalize_mask(&blackness.mask);
         break;
     }
     case QXL_DRAW_WHITENESS: {
-        SpiceWhiteness whiteness = drawable->qxl_drawable->u.whiteness;
+        SpiceWhiteness whiteness = drawable->red_drawable->u.whiteness;
         localize_mask(worker, &whiteness.mask, drawable->group_id);
         canvas->ops->draw_whiteness(canvas,
-                                    &drawable->qxl_drawable->bbox, &clip, &whiteness);
+                                    &drawable->red_drawable->bbox, &clip, &whiteness);
         unlocalize_mask(&whiteness.mask);
         break;
     }
     case QXL_DRAW_INVERS: {
-        SpiceInvers invers = drawable->qxl_drawable->u.invers;
+        SpiceInvers invers = drawable->red_drawable->u.invers;
         localize_mask(worker, &invers.mask, drawable->group_id);
         canvas->ops->draw_invers(canvas,
-                                 &drawable->qxl_drawable->bbox, &clip, &invers);
+                                 &drawable->red_drawable->bbox, &clip, &invers);
         unlocalize_mask(&invers.mask);
         break;
     }
     case QXL_DRAW_ROP3: {
-        SpiceRop3 rop3 = drawable->qxl_drawable->u.rop3;
+        SpiceRop3 rop3 = drawable->red_drawable->u.rop3;
         localize_brush(worker, &rop3.brush, drawable->group_id);
         localize_bitmap(worker, &rop3.src_bitmap, drawable->group_id);
         localize_mask(worker, &rop3.mask, drawable->group_id);
-        canvas->ops->draw_rop3(canvas, &drawable->qxl_drawable->bbox,
+        canvas->ops->draw_rop3(canvas, &drawable->red_drawable->bbox,
                                &clip, &rop3); unlocalize_mask(&rop3.mask);
         unlocalize_bitmap(&rop3.src_bitmap);
         unlocalize_brush(&rop3.brush);
         break;
     }
     case QXL_DRAW_STROKE: {
-        SpiceStroke stroke = drawable->qxl_drawable->u.stroke;
+        SpiceStroke stroke = drawable->red_drawable->u.stroke;
         localize_brush(worker, &stroke.brush, drawable->group_id);
         localize_path(worker, &stroke.path, drawable->group_id);
         localize_attr(worker, &stroke.attr, drawable->group_id);
         canvas->ops->draw_stroke(canvas,
-                                 &drawable->qxl_drawable->bbox, &clip, &stroke);
+                                 &drawable->red_drawable->bbox, &clip, &stroke);
         unlocalize_attr(&stroke.attr);
         unlocalize_path(&stroke.path);
         unlocalize_brush(&stroke.brush);
         break;
     }
     case QXL_DRAW_TEXT: {
-        SpiceText text = drawable->qxl_drawable->u.text;
+        SpiceText text = drawable->red_drawable->u.text;
         localize_brush(worker, &text.fore_brush, drawable->group_id);
         localize_brush(worker, &text.back_brush, drawable->group_id);
         localize_str(worker, &text.str, drawable->group_id);
-        canvas->ops->draw_text(canvas, &drawable->qxl_drawable->bbox,
+        canvas->ops->draw_text(canvas, &drawable->red_drawable->bbox,
                                &clip, &text);
         unlocalize_str(&text.str);
         unlocalize_brush(&text.back_brush);
@@ -5027,8 +5030,9 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size)
         worker->repoll_cmd_ring = 0;
         switch (ext_cmd.cmd.type) {
         case QXL_CMD_DRAW: {
-            QXLDrawable *drawable = (QXLDrawable *)get_virt(&worker->mem_slots, ext_cmd.cmd.data,
-                                                            sizeof(QXLDrawable), ext_cmd.group_id);
+            RedDrawable *drawable = spice_new0(RedDrawable, 1);
+            red_get_drawable(&worker->mem_slots, ext_cmd.group_id,
+                             drawable, ext_cmd.cmd.data);
             red_process_drawable(worker, drawable, ext_cmd.group_id);
             break;
         }
@@ -5385,8 +5389,8 @@ static void fill_base(DisplayChannel *display_channel, Drawable *drawable)
     SpiceMarshaller *cliprects_data_out;
 
     base.surface_id = drawable->surface_id;
-    base.box = drawable->qxl_drawable->bbox;
-    base.clip = drawable->qxl_drawable->clip;
+    base.box = drawable->red_drawable->bbox;
+    base.clip = drawable->red_drawable->clip;
 
     spice_marshall_DisplayBase(channel->send_data.marshaller, &base,
                               &cliprects_data_out);
@@ -5490,7 +5494,7 @@ static RedGlzDrawable *red_display_get_glz_drawable(DisplayChannel *channel, Dra
     ret = spice_new(RedGlzDrawable, 1);
 
     ret->display_channel = channel;
-    ret->qxl_drawable = drawable->qxl_drawable;
+    ret->red_drawable = drawable->red_drawable;
     ret->drawable = drawable;
     ret->group_id = drawable->group_id;
     ret->surface_id = drawable->surface_id;
@@ -5559,7 +5563,7 @@ static void red_display_free_glz_drawable_instance(DisplayChannel *channel,
         if (drawable) {
             drawable->red_glz_drawable = NULL;
         } else { // no reference to the qxl drawable left
-            free_qxl_drawable(channel->base.worker, glz_drawable->qxl_drawable,
+            free_red_drawable(channel->base.worker, glz_drawable->red_drawable,
                               glz_drawable->group_id, glz_drawable->self_bitmap,
                               glz_drawable->surface_id);
         }
@@ -7332,14 +7336,14 @@ static void surface_lossy_region_update(RedWorker *worker, DisplayChannel *displ
                                         Drawable *item, int has_mask, int lossy)
 {
     QRegion *surface_lossy_region;
-    QXLDrawable *drawable;
+    RedDrawable *drawable;
 
     if (has_mask && !lossy) {
         return;
     }
 
     surface_lossy_region = &display_channel->surface_client_lossy_region[item->surface_id];
-    drawable = item->qxl_drawable;
+    drawable = item->red_drawable;
 
     if (drawable->clip.type == SPICE_CLIP_TYPE_RECTS ) {
         QRegion clip_rgn;
@@ -7374,8 +7378,8 @@ static inline int drawable_intersects_with_areas(Drawable *drawable, int surface
 {   
     int i;
     for (i = 0; i < num_surfaces; i++) {
-        if (surface_ids[i] == drawable->qxl_drawable->surface_id) {
-            if (rect_intersects(surface_areas[i], &drawable->qxl_drawable->bbox)) {
+        if (surface_ids[i] == drawable->red_drawable->surface_id) {
+            if (rect_intersects(surface_areas[i], &drawable->red_drawable->bbox)) {
                 return TRUE;
             }
         }
@@ -7389,21 +7393,21 @@ static inline int drawable_depends_on_areas(Drawable *drawable,
                                             int num_surfaces)
 {   
     int i;
-    QXLDrawable *qxl_drawable;
+    RedDrawable *red_drawable;
     int drawable_has_shadow;
     SpiceRect shadow_rect;
 
-    qxl_drawable = drawable->qxl_drawable;
-    drawable_has_shadow = has_shadow(qxl_drawable);
+    red_drawable = drawable->red_drawable;
+    drawable_has_shadow = has_shadow(red_drawable);
 
     if (drawable_has_shadow) {
-       int delta_x = qxl_drawable->u.copy_bits.src_pos.x - qxl_drawable->bbox.left;
-       int delta_y = qxl_drawable->u.copy_bits.src_pos.y - qxl_drawable->bbox.top;
+       int delta_x = red_drawable->u.copy_bits.src_pos.x - red_drawable->bbox.left;
+       int delta_y = red_drawable->u.copy_bits.src_pos.y - red_drawable->bbox.top;
 
-       shadow_rect.left = qxl_drawable->u.copy_bits.src_pos.x;
-       shadow_rect.top = qxl_drawable->u.copy_bits.src_pos.y;
-       shadow_rect.right = qxl_drawable->bbox.right + delta_x;
-       shadow_rect.bottom = qxl_drawable->bbox.bottom + delta_y;
+       shadow_rect.left = red_drawable->u.copy_bits.src_pos.x;
+       shadow_rect.top = red_drawable->u.copy_bits.src_pos.y;
+       shadow_rect.right = red_drawable->bbox.right + delta_x;
+       shadow_rect.bottom = red_drawable->bbox.bottom + delta_y;
     }
 
     for (i = 0; i < num_surfaces; i++) {
@@ -7413,13 +7417,13 @@ static inline int drawable_depends_on_areas(Drawable *drawable,
          for (x = 0; x < 3; ++x) {
             dep_surface_id = drawable->surfaces_dest[x];
             if (dep_surface_id == surface_ids[i]) {
-                if (rect_intersects(&surface_areas[i], &qxl_drawable->surfaces_rects[x])) {
+                if (rect_intersects(&surface_areas[i], &red_drawable->surfaces_rects[x])) {
                     return TRUE;
                 }
             }
         }
 
-        if (surface_ids[i] == qxl_drawable->surface_id) {
+        if (surface_ids[i] == red_drawable->surface_id) {
             if (drawable_has_shadow) {
                 if (rect_intersects(&surface_areas[i], &shadow_rect)) {
                     return TRUE;
@@ -7427,11 +7431,11 @@ static inline int drawable_depends_on_areas(Drawable *drawable,
             }
 
             // not dependent on dest
-            if (qxl_drawable->effect == QXL_EFFECT_OPAQUE) {
+            if (red_drawable->effect == QXL_EFFECT_OPAQUE) {
                 continue;
             }
 
-            if (rect_intersects(&surface_areas[i], &qxl_drawable->bbox)) {
+            if (rect_intersects(&surface_areas[i], &red_drawable->bbox)) {
                 return TRUE;
             }
         }
@@ -7514,10 +7518,10 @@ static void red_pipe_replace_rendered_drawables_with_images(RedWorker *worker,
             continue;
         }
 
-        image = red_add_surface_area_image(worker, drawable->qxl_drawable->surface_id,
-                                           &drawable->qxl_drawable->bbox, pipe_item, TRUE);
-        resent_surface_ids[num_resent] = drawable->qxl_drawable->surface_id;
-        resent_areas[num_resent] = drawable->qxl_drawable->bbox;
+        image = red_add_surface_area_image(worker, drawable->red_drawable->surface_id,
+                                           &drawable->red_drawable->bbox, pipe_item, TRUE);
+        resent_surface_ids[num_resent] = drawable->red_drawable->surface_id;
+        resent_areas[num_resent] = drawable->red_drawable->bbox;
         num_resent++;
 
         ASSERT(image);
@@ -7533,7 +7537,7 @@ static void red_add_lossless_drawable_dependencies(RedWorker *worker,
                                                    SpiceRect *deps_areas[],
                                                    int num_deps)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     int sync_rendered = FALSE;
     int i;
 
@@ -7601,7 +7605,7 @@ static void red_send_qxl_draw_fill(RedWorker *worker,
                                    Drawable *item)
 {
     RedChannel *channel = &display_channel->base;
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     SpiceMarshaller *brush_pat_out;
     SpiceMarshaller *mask_bitmap_out;
     SpiceFill fill;
@@ -7627,7 +7631,7 @@ static void red_lossy_send_qxl_draw_fill(RedWorker *worker,
                                          DisplayChannel *display_channel,
                                          Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
 
     int dest_allowed_lossy = FALSE;
     int dest_is_lossy = FALSE;
@@ -7684,7 +7688,7 @@ static FillBitsType red_send_qxl_draw_opaque(RedWorker *worker,
                                              Drawable *item, int src_allowed_lossy)
 {
     RedChannel *channel = &display_channel->base;
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     SpiceMarshaller *brush_pat_out;
     SpiceMarshaller *src_bitmap_out;
     SpiceMarshaller *mask_bitmap_out;
@@ -7716,7 +7720,7 @@ static void red_lossy_send_qxl_draw_opaque(RedWorker *worker,
                                            DisplayChannel *display_channel,
                                            Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
 
     int src_allowed_lossy;
     int rop;
@@ -7781,7 +7785,7 @@ static FillBitsType red_send_qxl_draw_copy(RedWorker *worker,
                                            Drawable *item, int src_allowed_lossy)
 {
     RedChannel *channel = &display_channel->base;
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     SpiceMarshaller *src_bitmap_out;
     SpiceMarshaller *mask_bitmap_out;
     SpiceCopy copy;
@@ -7807,7 +7811,7 @@ static void red_lossy_send_qxl_draw_copy(RedWorker *worker,
                                          DisplayChannel *display_channel,
                                          Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     int has_mask = !!drawable->u.copy.mask.bitmap;
     int src_is_lossy;
     BitmapData src_bitmap_data;
@@ -7833,7 +7837,7 @@ static void red_send_qxl_draw_transparent(RedWorker *worker,
                                           Drawable *item)
 {
     RedChannel *channel = &display_channel->base;
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     SpiceMarshaller *src_bitmap_out;
     SpiceTransparent transparent;
 
@@ -7850,7 +7854,7 @@ static void red_lossy_send_qxl_draw_transparent(RedWorker *worker,
                                                 DisplayChannel *display_channel,
                                                 Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     int src_is_lossy;
     BitmapData src_bitmap_data;
 
@@ -7879,7 +7883,7 @@ static FillBitsType red_send_qxl_draw_alpha_blend(RedWorker *worker,
                                                   int src_allowed_lossy)
 {
     RedChannel *channel = &display_channel->base;
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     SpiceMarshaller *src_bitmap_out;
     SpiceAlphaBlnd alpha_blend;
     FillBitsType src_send_type;
@@ -7899,7 +7903,7 @@ static void red_lossy_send_qxl_draw_alpha_blend(RedWorker *worker,
                                                 DisplayChannel *display_channel,
                                                 Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     int src_is_lossy;
     BitmapData src_bitmap_data;
     FillBitsType src_send_type;
@@ -7925,7 +7929,7 @@ static void red_send_qxl_copy_bits(RedWorker *worker,
                                    Drawable *item)
 {
     RedChannel *channel = &display_channel->base;
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     SpicePoint copy_bits;
 
     fill_base(display_channel, item);
@@ -7939,7 +7943,7 @@ static void red_lossy_send_qxl_copy_bits(RedWorker *worker,
                                          DisplayChannel *display_channel,
                                          Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     SpiceRect src_rect;
     int horz_offset;
     int vert_offset;
@@ -7968,7 +7972,7 @@ static void red_send_qxl_draw_blend(RedWorker *worker,
                                     Drawable *item)
 {
     RedChannel *channel = &display_channel->base;
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     SpiceMarshaller *src_bitmap_out;
     SpiceMarshaller *mask_bitmap_out;
     SpiceBlend blend;
@@ -7990,7 +7994,7 @@ static void red_lossy_send_qxl_draw_blend(RedWorker *worker,
                                           DisplayChannel *display_channel,
                                           Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     int src_is_lossy;
     BitmapData src_bitmap_data;
     int dest_is_lossy;
@@ -8031,7 +8035,7 @@ static void red_send_qxl_draw_blackness(RedWorker *worker,
                                         Drawable *item)
 {
     RedChannel *channel = &display_channel->base;
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     SpiceMarshaller *mask_bitmap_out;
     SpiceBlackness blackness;
 
@@ -8050,7 +8054,7 @@ static void red_lossy_send_qxl_draw_blackness(RedWorker *worker,
                                               DisplayChannel *display_channel,
                                               Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     int has_mask = !!drawable->u.blackness.mask.bitmap;
 
     red_send_qxl_draw_blackness(worker, display_channel, item);
@@ -8063,7 +8067,7 @@ static void red_send_qxl_draw_whiteness(RedWorker *worker,
                                         Drawable *item)
 {
     RedChannel *channel = &display_channel->base;
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     SpiceMarshaller *mask_bitmap_out;
     SpiceWhiteness whiteness;
 
@@ -8082,7 +8086,7 @@ static void red_lossy_send_qxl_draw_whiteness(RedWorker *worker,
                                               DisplayChannel *display_channel,
                                               Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     int has_mask = !!drawable->u.whiteness.mask.bitmap;
 
     red_send_qxl_draw_whiteness(worker, display_channel, item);
@@ -8094,7 +8098,7 @@ static void red_send_qxl_draw_inverse(RedWorker *worker,
                                         DisplayChannel *display_channel,
                                         Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     SpiceMarshaller *mask_bitmap_out;
     RedChannel *channel = &display_channel->base;
     SpiceInvers inverse;
@@ -8121,7 +8125,7 @@ static void red_send_qxl_draw_rop3(RedWorker *worker,
                                    DisplayChannel *display_channel,
                                    Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     RedChannel *channel = &display_channel->base;
     SpiceRop3 rop3;
     SpiceMarshaller *src_bitmap_out;
@@ -8149,7 +8153,7 @@ static void red_lossy_send_qxl_draw_rop3(RedWorker *worker,
                                          DisplayChannel *display_channel,
                                          Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     int src_is_lossy;
     BitmapData src_bitmap_data;
     int brush_is_lossy;
@@ -8203,7 +8207,7 @@ static void red_send_qxl_draw_stroke(RedWorker *worker,
                                      DisplayChannel *display_channel,
                                      Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     RedChannel *channel = &display_channel->base;
     SpiceStroke stroke;
     SpiceMarshaller *brush_pat_out;
@@ -8231,7 +8235,7 @@ static void red_lossy_send_qxl_draw_stroke(RedWorker *worker,
                                            DisplayChannel *display_channel,
                                            Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     int brush_is_lossy;
     BitmapData brush_bitmap_data;
     int dest_is_lossy = FALSE;
@@ -8285,7 +8289,7 @@ static void red_send_qxl_draw_text(RedWorker *worker,
                                    DisplayChannel *display_channel,
                                    Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     RedChannel *channel = &display_channel->base;
     SpiceText text;
     SpiceMarshaller *brush_pat_out;
@@ -8316,7 +8320,7 @@ static void red_lossy_send_qxl_draw_text(RedWorker *worker,
                                          DisplayChannel *display_channel,
                                          Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
     int fg_is_lossy;
     BitmapData fg_bitmap_data;
     int bg_is_lossy;
@@ -8380,7 +8384,7 @@ static void red_lossy_send_qxl_draw_text(RedWorker *worker,
 static void red_lossy_send_qxl_drawable(RedWorker *worker, DisplayChannel *display_channel,
                                    Drawable *item)
 {
-    switch (item->qxl_drawable->type) {
+    switch (item->red_drawable->type) {
     case QXL_DRAW_FILL:
         red_lossy_send_qxl_draw_fill(worker, display_channel, item);
         break;
@@ -8433,7 +8437,7 @@ static void red_lossy_send_qxl_drawable(RedWorker *worker, DisplayChannel *displ
 static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *display_channel,
                                          Drawable *item)
 {
-    QXLDrawable *drawable = item->qxl_drawable;
+    RedDrawable *drawable = item->red_drawable;
 
     switch (drawable->type) {
     case QXL_DRAW_FILL:
@@ -8830,11 +8834,11 @@ static inline int red_send_stream_data(DisplayChannel *display_channel, Drawable
     int n;
 
     ASSERT(stream);
-    ASSERT(drawable->qxl_drawable->type == QXL_DRAW_COPY);
+    ASSERT(drawable->red_drawable->type == QXL_DRAW_COPY);
 
     channel = &display_channel->base;
     worker = channel->worker;
-    qxl_image = (QXLImage *)get_virt(&worker->mem_slots,  drawable->qxl_drawable->u.copy.src_bitmap,
+    qxl_image = (QXLImage *)get_virt(&worker->mem_slots,  drawable->red_drawable->u.copy.src_bitmap,
                                      sizeof(QXLImage), drawable->group_id);
 
     if (qxl_image->descriptor.type != SPICE_IMAGE_TYPE_BITMAP ||
@@ -8855,7 +8859,7 @@ static inline int red_send_stream_data(DisplayChannel *display_channel, Drawable
 
     switch (qxl_image->bitmap.format) {
     case SPICE_BITMAP_FMT_32BIT:
-        if (!red_rgb32bpp_to_24(worker, &drawable->qxl_drawable->u.copy.src_area,
+        if (!red_rgb32bpp_to_24(worker, &drawable->red_drawable->u.copy.src_area,
                                 &qxl_image->bitmap, frame, frame_stride,
                                 get_virt_delta(&worker->mem_slots, data, drawable->group_id),
                                 get_memslot_id(&worker->mem_slots, data),
@@ -8864,7 +8868,7 @@ static inline int red_send_stream_data(DisplayChannel *display_channel, Drawable
         }
         break;
     case SPICE_BITMAP_FMT_16BIT:
-        if (!red_rgb16bpp_to_24(worker, &drawable->qxl_drawable->u.copy.src_area,
+        if (!red_rgb16bpp_to_24(worker, &drawable->red_drawable->u.copy.src_area,
                                 &qxl_image->bitmap, frame, frame_stride,
                                 get_virt_delta(&worker->mem_slots, data, drawable->group_id),
                                 get_memslot_id(&worker->mem_slots, data),
@@ -8873,7 +8877,7 @@ static inline int red_send_stream_data(DisplayChannel *display_channel, Drawable
         }
         break;
     case SPICE_BITMAP_FMT_24BIT:
-        if (!red_rgb24bpp_to_24(worker, &drawable->qxl_drawable->u.copy.src_area,
+        if (!red_rgb24bpp_to_24(worker, &drawable->red_drawable->u.copy.src_area,
                                 &qxl_image->bitmap, frame, frame_stride,
                                 get_virt_delta(&worker->mem_slots, data, drawable->group_id),
                                 get_memslot_id(&worker->mem_slots, data),
@@ -8907,7 +8911,7 @@ static inline int red_send_stream_data(DisplayChannel *display_channel, Drawable
     SpiceMsgDisplayStreamData stream_data;
 
     stream_data.id = stream - worker->streams_buf;
-    stream_data.multi_media_time = drawable->qxl_drawable->mm_time;
+    stream_data.multi_media_time = drawable->red_drawable->mm_time;
     stream_data.data_size = n;
     stream_data.pad_size = PADDING;
     spice_marshall_msg_display_stream_data(channel->send_data.marshaller, &stream_data);
@@ -9201,7 +9205,7 @@ static void red_send_image(DisplayChannel *display_channel, ImageItem *item)
 static void red_display_send_upgrade(DisplayChannel *display_channel, UpgradeItem *item)
 {
     RedChannel *channel;
-    QXLDrawable *qxl_drawable;
+    RedDrawable *red_drawable;
     SpiceMsgDisplayDrawCopy copy;
     SpiceMarshaller *cliprects_data_out, *src_bitmap_out, *mask_bitmap_out;
     int i;
@@ -9211,16 +9215,16 @@ static void red_display_send_upgrade(DisplayChannel *display_channel, UpgradeIte
 
     channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_COPY;
 
-    qxl_drawable = item->drawable->qxl_drawable;
-    ASSERT(qxl_drawable->type == QXL_DRAW_COPY);
-    ASSERT(qxl_drawable->u.copy.rop_decriptor == SPICE_ROPD_OP_PUT);
-    ASSERT(qxl_drawable->u.copy.mask.bitmap == 0);
+    red_drawable = item->drawable->red_drawable;
+    ASSERT(red_drawable->type == QXL_DRAW_COPY);
+    ASSERT(red_drawable->u.copy.rop_decriptor == SPICE_ROPD_OP_PUT);
+    ASSERT(red_drawable->u.copy.mask.bitmap == 0);
 
     copy.base.surface_id = 0;
-    copy.base.box = qxl_drawable->bbox;
+    copy.base.box = red_drawable->bbox;
     copy.base.clip.type = SPICE_CLIP_TYPE_RECTS;
     copy.base.clip.data = 0;
-    copy.data = qxl_drawable->u.copy;
+    copy.data = red_drawable->u.copy;
 
     SpiceMarshaller *m = channel->send_data.marshaller;
 
@@ -9260,8 +9264,8 @@ static void red_display_send_stream_start(DisplayChannel *display_channel, Strea
     stream_create.dest = stream->dest_area;
 
     if (stream->current) {
-        QXLDrawable *qxl_drawable = stream->current->qxl_drawable;
-        stream_create.clip = qxl_drawable->clip;
+        RedDrawable *red_drawable = stream->current->red_drawable;
+        stream_create.clip = red_drawable->clip;
     } else {
         stream_create.clip.type = SPICE_CLIP_TYPE_RECTS;
         stream_create.clip.data = 0;
@@ -9272,12 +9276,12 @@ static void red_display_send_stream_start(DisplayChannel *display_channel, Strea
 
 
     if (stream->current) {
-        QXLDrawable *qxl_drawable = stream->current->qxl_drawable;
-        if (qxl_drawable->clip.type == SPICE_CLIP_TYPE_RECTS) {
+        RedDrawable *red_drawable = stream->current->red_drawable;
+        if (red_drawable->clip.type == SPICE_CLIP_TYPE_RECTS) {
             fill_rects_clip(channel, cliprects_data_out, stream_create.clip.data,
                             stream->current->group_id);
         } else {
-            ASSERT(qxl_drawable->clip.type == SPICE_CLIP_TYPE_NONE);
+            ASSERT(red_drawable->clip.type == SPICE_CLIP_TYPE_NONE);
         }
         display_begin_send_massage(display_channel, &stream->current->pipe_item);
     } else {
@@ -9680,7 +9684,7 @@ static void __show_tree_call(TreeItem *item, void *data)
             printf("  ");
         }
         printf(item_prefix, 0);
-        show_qxl_drawable(tree_data->worker, drawable->qxl_drawable, NULL);
+        show_red_drawable(tree_data->worker, drawable->red_drawable, NULL);
         for (i = 0; i < tree_data->level; i++) {
             printf("  ");
         }
commit c17fdfd053b9520309a45a79b949a610a74efd3e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Jun 22 16:10:31 2010 +0200

    improve memory slot error logging.

diff --git a/server/red_memslots.c b/server/red_memslots.c
index bc428d5..8c9810d 100644
--- a/server/red_memslots.c
+++ b/server/red_memslots.c
@@ -80,9 +80,11 @@ void validate_virt(RedMemSlotInfo *info, unsigned long virt, int slot_id,
 
     if (virt < slot->virt_start_addr || (virt + add_size) > slot->virt_end_addr) {
         print_memslots(info);
-        PANIC("virtual address out of range 0x%lx 0x%lx %d %d 0x%lx 0x%lx 0x%lx", virt,
-              slot->address_delta, slot_id, group_id, slot->virt_start_addr, slot->virt_end_addr,
-              virt + add_size);
+        PANIC("virtual address out of range\n"
+              "    virt=0x%lx+0x%x slot_id=%d group_id=%d\n"
+              "    slot=0x%lx-0x%lx delta=0x%lx",
+              virt, add_size, slot_id, group_id,
+              slot->virt_start_addr, slot->virt_end_addr, slot->address_delta);
     }
 }
 
@@ -101,7 +103,8 @@ unsigned long get_virt(RedMemSlotInfo *info, unsigned long addr, uint32_t add_si
 
     slot_id = get_memslot_id(info, addr);
     if (slot_id > info->num_memslots) {
-        PANIC("slot_id too big");
+        print_memslots(info);
+        PANIC("slot_id too big, addr=%lx", addr);
     }
 
     slot = &info->mem_slots[group_id][slot_id];


More information about the Spice-commits mailing list