From a91daa2feb50a3d39150993a9d1b397b3c85ad03 Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Thu, 28 Jun 2012 15:23:12 -0400 Subject: 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. --- server/red_memslots.c | 2 +- server/red_parse_qxl.c | 59 +++++++++++++++++++++++++++- server/red_parse_qxl.h | 1 + server/red_worker.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++ 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; -- cgit