summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2012-06-28 15:23:12 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2012-08-24 13:44:42 -0400
commita91daa2feb50a3d39150993a9d1b397b3c85ad03 (patch)
treede890ed96413ca8dc7ec5ab40256ddedffaf46fd
parent22b64d2ae25dba938da65983cbf3d63e6336907f (diff)
downloadspice-a91daa2feb50a3d39150993a9d1b397b3c85ad03.tar.gz
spice-a91daa2feb50a3d39150993a9d1b397b3c85ad03.tar.xz
spice-a91daa2feb50a3d39150993a9d1b397b3c85ad03.zip
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.
-rw-r--r--server/red_memslots.c2
-rw-r--r--server/red_parse_qxl.c59
-rw-r--r--server/red_parse_qxl.h1
-rw-r--r--server/red_worker.c104
4 files changed, 164 insertions, 2 deletions
diff --git a/server/red_memslots.c b/server/red_memslots.c
index 523890d6..d9153d3f 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 2953e800..bf577092 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 70f85093..3adc9fa7 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 59749f99..bd6de1c8 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;