[Spice-commits] 3 commits - client/canvas.cpp client/canvas.h client/display_channel.cpp client/display_channel.h server/red_common.h server/red_memslots.c server/red_parse_qxl.c server/red_parse_qxl.h server/red_worker.c spice-common

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Fri Aug 24 10:49:14 PDT 2012


 client/canvas.cpp          |    7 ++
 client/canvas.h            |    1 
 client/display_channel.cpp |   13 ++++
 client/display_channel.h   |    1 
 server/red_common.h        |    2 
 server/red_memslots.c      |    2 
 server/red_parse_qxl.c     |   61 ++++++++++++++++++++-
 server/red_parse_qxl.h     |    1 
 server/red_worker.c        |  127 ++++++++++++++++++++++++++++++++++++++++++---
 spice-common               |    2 
 10 files changed, 204 insertions(+), 13 deletions(-)

New commits:
commit 37be9e0c2efd21e088e8106b4356de7fcbe5a95b
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Aug 10 18:44:57 2012 -0400

    Add support for Composite command to the client
    
    All the real work is being done in spice-common, so this patch is just
    hooking up the virtual calls and adding the SPICE_DISPLAY_CAP_COMPOSITE
    capability.

diff --git a/client/canvas.cpp b/client/canvas.cpp
index 7d1561a..f132186 100644
--- a/client/canvas.cpp
+++ b/client/canvas.cpp
@@ -114,6 +114,13 @@ void Canvas::draw_alpha_blend(SpiceMsgDisplayDrawAlphaBlend& alpha_blend, int si
     touched_bbox(&alpha_blend.base.box);
 }
 
+void Canvas::draw_composite(SpiceMsgDisplayDrawComposite& composite, int size)
+{
+    begin_draw(composite.base, size, sizeof(SpiceMsgDisplayDrawComposite));
+    _canvas->ops->draw_composite(_canvas, &composite.base.box, &composite.base.clip, &composite.data);
+    touched_bbox(&composite.base.box);
+}
+
 void Canvas::copy_bits(SpiceMsgDisplayCopyBits& copy, int size)
 {
     begin_draw(copy.base, size, sizeof(SpiceMsgDisplayCopyBits));
diff --git a/client/canvas.h b/client/canvas.h
index 7702568..213a753 100644
--- a/client/canvas.h
+++ b/client/canvas.h
@@ -304,6 +304,7 @@ public:
     void draw_invers(SpiceMsgDisplayDrawInvers& invers, int size);
     void draw_rop3(SpiceMsgDisplayDrawRop3& rop3, int size);
     void draw_stroke(SpiceMsgDisplayDrawStroke& stroke, int size);
+    void draw_composite(SpiceMsgDisplayDrawComposite& composite, int size);
 
     void put_image(
 #ifdef WIN32
diff --git a/client/display_channel.cpp b/client/display_channel.cpp
index 17bdf6a..d08072d 100644
--- a/client/display_channel.cpp
+++ b/client/display_channel.cpp
@@ -650,6 +650,8 @@ DisplayChannel::DisplayChannel(RedClient& client, uint32_t id,
     get_process_loop().add_trigger(_interrupt_update);
 
     set_draw_handlers();
+
+    set_capability(SPICE_DISPLAY_CAP_COMPOSITE);
 }
 
 DisplayChannel::~DisplayChannel()
@@ -692,6 +694,8 @@ void DisplayChannel::set_draw_handlers()
                          &DisplayChannel::handle_draw_transparent);
     handler->set_handler(SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND,
                          &DisplayChannel::handle_draw_alpha_blend);
+    handler->set_handler(SPICE_MSG_DISPLAY_DRAW_COMPOSITE,
+                         &DisplayChannel::handle_draw_composite);
     handler->set_handler(SPICE_MSG_DISPLAY_STREAM_DATA, &DisplayChannel::handle_stream_data);
 }
 
@@ -712,6 +716,7 @@ void DisplayChannel::clear_draw_handlers()
     handler->set_handler(SPICE_MSG_DISPLAY_DRAW_TEXT, NULL);
     handler->set_handler(SPICE_MSG_DISPLAY_DRAW_TRANSPARENT, NULL);
     handler->set_handler(SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND, NULL);
+    handler->set_handler(SPICE_MSG_DISPLAY_DRAW_COMPOSITE, NULL);
     handler->set_handler(SPICE_MSG_DISPLAY_STREAM_DATA, NULL);
 }
 
@@ -1735,6 +1740,14 @@ void DisplayChannel::handle_draw_alpha_blend(RedPeer::InMessage* message)
     DRAW(alpha_blend);
 }
 
+void DisplayChannel::handle_draw_composite(RedPeer::InMessage* message)
+{
+    Canvas *canvas;
+    SpiceMsgDisplayDrawComposite* composite = (SpiceMsgDisplayDrawComposite*)message->data();
+    canvas = _surfaces_cache[composite->base.surface_id];
+    DRAW(composite);
+}
+
 void DisplayChannel::streams_time()
 {
     _next_timer_time = 0;
diff --git a/client/display_channel.h b/client/display_channel.h
index 72856f5..197ae73 100644
--- a/client/display_channel.h
+++ b/client/display_channel.h
@@ -173,6 +173,7 @@ private:
     void handle_draw_text(RedPeer::InMessage* message);
     void handle_draw_transparent(RedPeer::InMessage* message);
     void handle_draw_alpha_blend(RedPeer::InMessage* message);
+    void handle_draw_composite(RedPeer::InMessage* message);
 
     void on_streams_trigger();
     virtual void on_update_completion(uint64_t mark);
commit a91daa2feb50a3d39150993a9d1b397b3c85ad03
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Jun 28 15:23:12 2012 -0400

    Add support for QXLComposite to spice server
    
    In red-parse-qxl.c add support for parsing QXLComposite into
    SpiceComposite. In red-worker.c add support for marshalling
    SpiceComposite onto the wire.

diff --git a/server/red_memslots.c b/server/red_memslots.c
index 523890d..d9153d3 100644
--- a/server/red_memslots.c
+++ b/server/red_memslots.c
@@ -120,7 +120,7 @@ unsigned long get_virt(RedMemSlotInfo *info, QXLPHYSICAL addr, uint32_t add_size
     slot_id = get_memslot_id(info, addr);
     if (slot_id > info->num_memslots) {
         print_memslots(info);
-        spice_critical("slot_id too big, addr=%" PRIx64, addr);
+        spice_critical("slot_id %d too big, addr=%" PRIx64, slot_id, addr);
         *error = 1;
         return 0;
     }
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 2953e80..bf57709 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -626,10 +626,61 @@ static void red_put_alpha_blend(SpiceAlphaBlend *red)
     red_put_image(red->src_bitmap);
 }
 
+static bool get_transform(RedMemSlotInfo *slots,
+                          int group_id,
+                          QXLPHYSICAL qxl_transform,
+                          SpiceTransform *dst_transform)
+                                                    
+{
+    const uint32_t *t = NULL;
+    int error;
+
+    if (qxl_transform == 0)
+        return FALSE;
+    
+    t = (uint32_t *)get_virt(slots, qxl_transform, sizeof(*dst_transform), group_id, &error);
+
+    if (!t || error)
+        return FALSE;
+
+    memcpy(dst_transform, t, sizeof(*dst_transform));
+    return TRUE;
+}
+
+static void red_get_composite_ptr(RedMemSlotInfo *slots, int group_id,
+                                  SpiceComposite *red, QXLComposite *qxl, uint32_t flags)
+{
+    red->flags = qxl->flags;
+
+    red->src_bitmap = red_get_image(slots, group_id, qxl->src, flags);
+    if (get_transform(slots, group_id, qxl->src_transform, &red->src_transform))
+        red->flags |= SPICE_COMPOSITE_HAS_SRC_TRANSFORM;
+    
+    if (qxl->mask) {
+        red->mask_bitmap = red_get_image(slots, group_id, qxl->mask, flags);
+        red->flags |= SPICE_COMPOSITE_HAS_MASK;
+        if (get_transform(slots, group_id, qxl->mask_transform, &red->mask_transform))
+            red->flags |= SPICE_COMPOSITE_HAS_MASK_TRANSFORM;
+    } else {
+        red->mask_bitmap = NULL;
+    }
+    red->src_origin.x = qxl->src_origin.x;
+    red->src_origin.y = qxl->src_origin.y;
+    red->mask_origin.x = qxl->mask_origin.x;
+    red->mask_origin.y = qxl->mask_origin.y;
+}
+
+static void red_put_composite(SpiceComposite *red)
+{
+    red_put_image(red->src_bitmap);
+    if (red->mask_bitmap)
+        red_put_image(red->mask_bitmap);
+}
+
 static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id,
                              SpiceRop3 *red, QXLRop3 *qxl, uint32_t flags)
 {
-    red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap, flags);
+   red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap, flags);
    red_get_rect_ptr(&red->src_area, &qxl->src_area);
    red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush, flags);
    red->rop3       = qxl->rop3;
@@ -900,6 +951,9 @@ static int red_get_native_drawable(RedMemSlotInfo *slots, int group_id,
     case QXL_DRAW_ROP3:
         red_get_rop3_ptr(slots, group_id, &red->u.rop3, &qxl->u.rop3, flags);
         break;
+    case QXL_DRAW_COMPOSITE:
+        red_get_composite_ptr(slots, group_id, &red->u.composite, &qxl->u.composite, flags);
+        break;
     case QXL_DRAW_STROKE:
         error = red_get_stroke_ptr(slots, group_id, &red->u.stroke, &qxl->u.stroke, flags);
         break;
@@ -1052,6 +1106,9 @@ void red_put_drawable(RedDrawable *red)
     case QXL_DRAW_ROP3:
         red_put_rop3(&red->u.rop3);
         break;
+    case QXL_DRAW_COMPOSITE:
+        red_put_composite(&red->u.composite);
+        break;
     case QXL_DRAW_STROKE:
         red_put_stroke(&red->u.stroke);
         break;
diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h
index 70f8509..3adc9fa 100644
--- a/server/red_parse_qxl.h
+++ b/server/red_parse_qxl.h
@@ -53,6 +53,7 @@ typedef struct RedDrawable {
         SpiceBlackness blackness;
         SpiceInvers invers;
         SpiceWhiteness whiteness;
+        SpiceComposite composite;
     } u;
 } RedDrawable;
 
diff --git a/server/red_worker.c b/server/red_worker.c
index 59749f9..bd6de1c 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -1254,6 +1254,8 @@ static inline void validate_surface(RedWorker *worker, uint32_t surface_id)
 {
     spice_warn_if(surface_id >= worker->n_surfaces);
     if (!worker->surfaces[surface_id].context.canvas) {
+        spice_warning("canvas address is %p for %d (and is NULL)\n",
+                   &(worker->surfaces[surface_id].context.canvas), surface_id);
         spice_warning("failed on %d", surface_id);
         spice_warn_if(!worker->surfaces[surface_id].context.canvas);
     }
@@ -1284,6 +1286,8 @@ static const char *draw_type_to_str(uint8_t type)
         return "QXL_DRAW_INVERS";
     case QXL_DRAW_ROP3:
         return "QXL_DRAW_ROP3";
+    case QXL_DRAW_COMPOSITE:
+        return "QXL_DRAW_COMPOSITE";
     case QXL_DRAW_STROKE:
         return "QXL_DRAW_STROKE";
     case QXL_DRAW_TEXT:
@@ -1319,6 +1323,7 @@ static void show_red_drawable(RedWorker *worker, RedDrawable *drawable, const ch
     case QXL_DRAW_WHITENESS:
     case QXL_DRAW_INVERS:
     case QXL_DRAW_ROP3:
+    case QXL_DRAW_COMPOSITE:
     case QXL_DRAW_STROKE:
     case QXL_DRAW_TEXT:
         break;
@@ -4347,6 +4352,16 @@ static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable)
                                &clip, &rop3);
         break;
     }
+    case QXL_DRAW_COMPOSITE: {
+        SpiceComposite composite = drawable->red_drawable->u.composite;
+        SpiceImage src, mask;
+        localize_bitmap(worker, &composite.src_bitmap, &src, drawable);
+        if (composite.mask_bitmap)
+            localize_bitmap(worker, &composite.mask_bitmap, &mask, drawable);
+        canvas->ops->draw_composite(canvas, &drawable->red_drawable->bbox,
+                                    &clip, &composite);
+        break;
+    }
     case QXL_DRAW_STROKE: {
         SpiceStroke stroke = drawable->red_drawable->u.stroke;
         SpiceImage img1;
@@ -7679,6 +7694,89 @@ static void red_lossy_marshall_qxl_draw_rop3(RedWorker *worker,
     }
 }
 
+static void red_marshall_qxl_draw_composite(RedWorker *worker,
+                                     RedChannelClient *rcc,
+                                     SpiceMarshaller *base_marshaller,
+                                     DrawablePipeItem *dpi)
+{
+    Drawable *item = dpi->drawable;
+    DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
+    RedDrawable *drawable = item->red_drawable;
+    SpiceMarshaller *src_bitmap_out;
+    SpiceMarshaller *mask_bitmap_out;
+    SpiceComposite composite;
+
+    red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_COMPOSITE, &dpi->dpi_pipe_item);
+    fill_base(base_marshaller, item);
+    composite = drawable->u.composite;
+    spice_marshall_Composite(base_marshaller,
+                             &composite,
+                             &src_bitmap_out,
+                             &mask_bitmap_out);
+
+    fill_bits(dcc, src_bitmap_out, composite.src_bitmap, item, FALSE);
+    if (mask_bitmap_out) {
+        fill_bits(dcc, mask_bitmap_out, composite.mask_bitmap, item, FALSE);
+    }
+}
+
+static void red_lossy_marshall_qxl_draw_composite(RedWorker *worker,
+                                                  RedChannelClient *rcc,
+                                                  SpiceMarshaller *base_marshaller,
+                                                  DrawablePipeItem *dpi)
+{
+    Drawable *item = dpi->drawable;
+    DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
+    RedDrawable *drawable = item->red_drawable;
+    int src_is_lossy;
+    BitmapData src_bitmap_data;
+    int mask_is_lossy;
+    BitmapData mask_bitmap_data;
+    int dest_is_lossy;
+    SpiceRect dest_lossy_area;
+
+    src_is_lossy = is_bitmap_lossy(rcc, drawable->u.composite.src_bitmap,
+                                   NULL, item, &src_bitmap_data);
+    mask_is_lossy = drawable->u.composite.mask_bitmap &&
+        is_bitmap_lossy(rcc, drawable->u.composite.mask_bitmap, NULL, item, &mask_bitmap_data);
+
+    dest_is_lossy = is_surface_area_lossy(dcc, drawable->surface_id,
+                                          &drawable->bbox, &dest_lossy_area);
+
+    if ((!src_is_lossy || (src_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE))   &&
+        (!mask_is_lossy || (mask_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)) &&
+        !dest_is_lossy) {
+        red_marshall_qxl_draw_composite(worker, rcc, base_marshaller, dpi);
+        surface_lossy_region_update(worker, dcc, item, FALSE, FALSE);
+    }
+    else {
+        int resend_surface_ids[3];
+        SpiceRect *resend_areas[3];
+        int num_resend = 0;
+
+        if (src_is_lossy && (src_bitmap_data.type == BITMAP_DATA_TYPE_SURFACE)) {
+            resend_surface_ids[num_resend] = src_bitmap_data.id;
+            resend_areas[num_resend] = &src_bitmap_data.lossy_rect;
+            num_resend++;
+        }
+
+        if (mask_is_lossy && (mask_bitmap_data.type == BITMAP_DATA_TYPE_SURFACE)) {
+            resend_surface_ids[num_resend] = mask_bitmap_data.id;
+            resend_areas[num_resend] = &mask_bitmap_data.lossy_rect;
+            num_resend++;
+        }
+
+        if (dest_is_lossy) {
+            resend_surface_ids[num_resend] = item->surface_id;
+            resend_areas[num_resend] = &dest_lossy_area;
+            num_resend++;
+        }
+
+        red_add_lossless_drawable_dependencies(worker, rcc, item,
+                                               resend_surface_ids, resend_areas, num_resend);
+    }
+}
+
 static void red_marshall_qxl_draw_stroke(RedWorker *worker,
                                      RedChannelClient *rcc,
                                      SpiceMarshaller *base_marshaller,
@@ -7895,6 +7993,9 @@ static void red_lossy_marshall_qxl_drawable(RedWorker *worker, RedChannelClient
     case QXL_DRAW_ROP3:
         red_lossy_marshall_qxl_draw_rop3(worker, rcc, base_marshaller, dpi);
         break;
+    case QXL_DRAW_COMPOSITE:
+        red_lossy_marshall_qxl_draw_composite(worker, rcc, base_marshaller, dpi);
+        break;
     case QXL_DRAW_STROKE:
         red_lossy_marshall_qxl_draw_stroke(worker, rcc, base_marshaller, dpi);
         break;
@@ -7949,6 +8050,9 @@ static inline void red_marshall_qxl_drawable(RedWorker *worker, RedChannelClient
     case QXL_DRAW_STROKE:
         red_marshall_qxl_draw_stroke(worker, rcc, m, dpi);
         break;
+    case QXL_DRAW_COMPOSITE:
+        red_marshall_qxl_draw_composite(worker, rcc, m, dpi);
+        break;
     case QXL_DRAW_TEXT:
         red_marshall_qxl_draw_text(worker, rcc, m, dpi);
         break;
commit 22b64d2ae25dba938da65983cbf3d63e6336907f
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri May 18 17:01:49 2012 -0400

    Add support for LZ compression of A8 images
    
    Graduality is irrelevant for A8 images, so instead of using RGB-ness
    as a short-cut, add a new macro BITMAP_FMT_HAS_GRADUALITY() that
    returns true for the existing RGB images, but false for A8.

diff --git a/server/red_common.h b/server/red_common.h
index b52a7d1..478b56a 100644
--- a/server/red_common.h
+++ b/server/red_common.h
@@ -38,7 +38,7 @@ enum {
 static inline int bitmap_fmt_is_rgb(uint8_t fmt)
 {
     static const int BITMAP_FMT_IS_RGB[SPICE_BITMAP_FMT_ENUM_END] =
-                                        {0, 0, 0, 0, 0, 0, 1, 1, 1, 1};
+	                                {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
 
     if (fmt >= SPICE_BITMAP_FMT_ENUM_END) {
         spice_warning("fmt >= SPICE_BITMAP_FMT_ENUM_END");
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 3bf49a0..2953e80 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -329,7 +329,7 @@ static SpiceChunks *red_get_image_data_chunked(RedMemSlotInfo *slots, int group_
 
 // This is based on SPICE_BITMAP_FMT_*, copied from server/red_worker.c
 // to avoid a possible unoptimization from making it non static.
-static const int BITMAP_FMT_IS_RGB[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1};
+static const int BITMAP_FMT_IS_RGB[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
 
 static SpiceImage *red_get_image(RedMemSlotInfo *slots, int group_id,
                                  QXLPHYSICAL addr, uint32_t flags)
diff --git a/server/red_worker.c b/server/red_worker.c
index 9330fff..59749f9 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -445,8 +445,12 @@ struct RedCompressBuf {
     RedCompressBuf *send_next;
 };
 
-static const int BITMAP_FMT_IS_PLT[] = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0};
-static const int BITMAP_FMP_BYTES_PER_PIXEL[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 4};
+static const int BITMAP_FMT_IS_PLT[] = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
+static const int BITMAP_FMP_BYTES_PER_PIXEL[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 1};
+
+#define BITMAP_FMT_HAS_GRADUALITY(f)                                    \
+    (bitmap_fmt_is_rgb(f)        &&                                     \
+     ((f) != SPICE_BITMAP_FMT_8BIT_A))
 
 pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
 Ring pixmap_cache_list = {&pixmap_cache_list, &pixmap_cache_list};
@@ -3111,7 +3115,7 @@ static inline void red_update_copy_graduality(RedWorker* worker, Drawable *drawa
 
     bitmap = &drawable->red_drawable->u.copy.src_bitmap->u.bitmap;
 
-    if (!bitmap_fmt_is_rgb(bitmap->format) || _stride_is_extra(bitmap) ||
+    if (!BITMAP_FMT_HAS_GRADUALITY(bitmap->format) || _stride_is_extra(bitmap) ||
         (bitmap->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE)) {
         drawable->copy_bitmap_graduality = BITMAP_GRADUAL_NOT_AVAIL;
     } else  {
@@ -3671,6 +3675,8 @@ static int surface_format_to_image_type(uint32_t surface_format)
         return SPICE_BITMAP_FMT_32BIT;
     case SPICE_SURFACE_FMT_32_ARGB:
         return SPICE_BITMAP_FMT_RGBA;
+    case SPICE_SURFACE_FMT_8_A:
+        return SPICE_BITMAP_FMT_8BIT_A;
     default:
         spice_critical("Unsupported surface format");
     }
@@ -5882,7 +5888,8 @@ static const LzImageType MAP_BITMAP_FMT_TO_LZ_IMAGE_TYPE[] = {
     LZ_IMAGE_TYPE_RGB16,
     LZ_IMAGE_TYPE_RGB24,
     LZ_IMAGE_TYPE_RGB32,
-    LZ_IMAGE_TYPE_RGBA
+    LZ_IMAGE_TYPE_RGBA,
+    LZ_IMAGE_TYPE_A8
 };
 
 typedef struct compress_send_data_t {
@@ -6344,8 +6351,8 @@ static inline int red_compress_image(DisplayChannelClient *dcc,
                     quic_compress = FALSE;
                 } else {
                     if (drawable->copy_bitmap_graduality == BITMAP_GRADUAL_INVALID) {
-                        quic_compress = bitmap_fmt_is_rgb(src->format) &&
-                            (_get_bitmap_graduality_level(display_channel->common.worker, src,
+                        quic_compress = BITMAP_FMT_HAS_GRADUALITY(src->format) &&
+			    (_get_bitmap_graduality_level(display_channel->common.worker, src,
                                                           drawable->group_id) ==
                              BITMAP_GRADUAL_HIGH);
                     } else {
@@ -6379,7 +6386,7 @@ static inline int red_compress_image(DisplayChannelClient *dcc,
         int ret;
         if ((image_compression == SPICE_IMAGE_COMPRESS_AUTO_GLZ) ||
             (image_compression == SPICE_IMAGE_COMPRESS_GLZ)) {
-            glz = bitmap_fmt_is_rgb(src->format) && (
+            glz = BITMAP_FMT_HAS_GRADUALITY(src->format) && (
                     (src->x * src->y) < glz_enc_dictionary_get_size(
                         dcc->glz_dict->dict));
         } else if ((image_compression == SPICE_IMAGE_COMPRESS_AUTO_LZ) ||
@@ -8452,7 +8459,7 @@ static void red_marshall_image(RedChannelClient *rcc, SpiceMarshaller *m, ImageI
 
     if ((comp_mode == SPICE_IMAGE_COMPRESS_AUTO_LZ) ||
         (comp_mode == SPICE_IMAGE_COMPRESS_AUTO_GLZ)) {
-        if (bitmap_fmt_is_rgb(item->image_format)) {
+        if (BITMAP_FMT_HAS_GRADUALITY(item->image_format)) {
             if (!_stride_is_extra(&bitmap)) {
                 BitmapGradualType grad_level;
                 grad_level = _get_bitmap_graduality_level(display_channel->common.worker,
diff --git a/spice-common b/spice-common
index c2adbb0..c0b048e 160000
--- a/spice-common
+++ b/spice-common
@@ -1 +1 @@
-Subproject commit c2adbb00dc0b29de0fe297f241fb0efeb4a81510
+Subproject commit c0b048ebef41b3a79d42e96c0ecaef65e1bb7599


More information about the Spice-commits mailing list