[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