summaryrefslogtreecommitdiff
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-07-02 17:25:14 -0400
commit1f4ac956589055b0be9bd955ff3556e68dbe8573 (patch)
tree7c4dd735d2aac72f89075a06d49856452737ed2a
parent77fd531ed5080de0aeeca2149b0f107b797f40b9 (diff)
wip
-rw-r--r--server/red_parse_qxl.c65
-rw-r--r--server/red_parse_qxl.h1
-rw-r--r--server/red_worker.c102
3 files changed, 168 insertions, 0 deletions
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index e6c2705..530a07c 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -606,6 +606,65 @@ static void red_put_alpha_blend(SpiceAlphaBlend *red)
red_put_image(red->src_bitmap);
}
+static void get_transform(RedMemSlotInfo *slots,
+ int group_id,
+ QXLPHYSICAL qxl_transform,
+ SpiceTransform *dst_transform)
+
+{
+ const uint32_t *t = NULL;
+ int error;
+
+ static const SpiceTransform id = {
+ 1 << 16, 0, 0,
+ 0, 1 << 16, 0
+ };
+
+ if (qxl_transform)
+ t = (uint32_t *)get_virt(slots, qxl_transform, sizeof(dst_transform), group_id, &error);
+
+ if (!t || error)
+ *dst_transform = id;
+ else
+ memcpy(dst_transform, t, sizeof(dst_transform));
+}
+
+#define MASK(lo, hi) \
+ (((1U << (hi)) - 1) - (((1U << (lo))) - 1))
+
+#define EXTRACT(v, lo, hi) \
+ ((v & MASK(lo, hi)) >> lo)
+
+static void red_get_composite_ptr(RedMemSlotInfo *slots, int group_id,
+ SpiceComposite *red, QXLComposite *qxl, uint32_t flags)
+{
+ uint32_t info = qxl->info;
+
+ red->src_bitmap = red_get_image(slots, group_id, qxl->src, flags);
+ get_transform(slots, group_id, qxl->src_transform, &red->src_transform);
+
+ red->op = EXTRACT (info, 0, 8);
+ red->src_filter = EXTRACT(info, 8, 11);
+ red->mask_filter = EXTRACT(info, 11, 14);
+ red->src_repeat = EXTRACT(info, 14, 16);
+ red->mask_repeat = EXTRACT(info, 16, 18);
+ red->component_alpha = EXTRACT(info, 18, 19);
+
+ if (qxl->mask) {
+ red->mask_bitmap = red_get_image(slots, group_id, qxl->mask, flags);
+ get_transform(slots, group_id, qxl->mask_transform, &red->mask_transform);
+ } else {
+ red->mask_bitmap = NULL;
+ }
+}
+
+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)
{
@@ -880,6 +939,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;
@@ -1032,6 +1094,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 154cacc..344d4c8 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -1246,6 +1246,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:
@@ -1281,6 +1283,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;
@@ -4309,6 +4312,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;
@@ -7638,6 +7651,60 @@ static void red_lossy_marshall_qxl_draw_rop3(RedWorker *worker,
}
}
+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 brush_is_lossy;
+ BitmapData brush_bitmap_data;
+ int dest_is_lossy;
+ SpiceRect dest_lossy_area;
+
+ src_is_lossy = is_bitmap_lossy(rcc, drawable->u.composite.src_bitmap,
+ &drawable->u.composite.src_area, item, &src_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)) &&
+ (!brush_is_lossy || (brush_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)) &&
+ !dest_is_lossy) {
+ int has_mask = !!drawable->u.rop3.mask.bitmap;
+ red_marshall_qxl_draw_rop3(worker, rcc, base_marshaller, dpi);
+ surface_lossy_region_update(worker, dcc, item, has_mask, 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 (brush_is_lossy && (brush_bitmap_data.type == BITMAP_DATA_TYPE_SURFACE)) {
+ resend_surface_ids[num_resend] = brush_bitmap_data.id;
+ resend_areas[num_resend] = &brush_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,
@@ -7664,6 +7731,35 @@ static void red_marshall_qxl_draw_stroke(RedWorker *worker,
}
}
+static void red_marshall_qxl_draw_composite(RedWorker *worker,
+ RedChannelClient *rcc,
+ SpiceMarshaller *base_marshaller,
+ DrawablePipeItem *dpi)
+{
+ Drawable *item = dpi->drawable;
+#if 0
+ DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
+#endif
+ RedDrawable *drawable = item->red_drawable;
+ SpiceMarshaller *src_bitmap_out;
+ SpiceMarshaller *mask_bitmap_out;
+ SpiceMarshaller *src_transform_out;
+ SpiceMarshaller *mask_transform_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,
+ &src_transform_out,
+ &mask_transform_out);
+
+ /* FIXME */
+}
+
static void red_lossy_marshall_qxl_draw_stroke(RedWorker *worker,
RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
@@ -7854,6 +7950,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;
@@ -7908,6 +8007,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;