diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-06-28 15:23:12 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-07-02 17:25:14 -0400 |
commit | 1f4ac956589055b0be9bd955ff3556e68dbe8573 (patch) | |
tree | 7c4dd735d2aac72f89075a06d49856452737ed2a | |
parent | 77fd531ed5080de0aeeca2149b0f107b797f40b9 (diff) |
wip
-rw-r--r-- | server/red_parse_qxl.c | 65 | ||||
-rw-r--r-- | server/red_parse_qxl.h | 1 | ||||
-rw-r--r-- | server/red_worker.c | 102 |
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; |