summaryrefslogtreecommitdiffstats
path: root/server/dcc.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/dcc.c')
-rw-r--r--server/dcc.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/server/dcc.c b/server/dcc.c
index 8cc2c0a3..6115569d 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -68,6 +68,68 @@ void dcc_create_surface(DisplayChannelClient *dcc, int surface_id)
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &create->pipe_item);
}
+// adding the pipe item after pos. If pos == NULL, adding to head.
+ImageItem *dcc_add_surface_area_image(DisplayChannelClient *dcc, int surface_id,
+ SpiceRect *area, PipeItem *pos, int can_lossy)
+{
+ DisplayChannel *display = DCC_TO_DC(dcc);
+ RedChannel *channel = RED_CHANNEL(display);
+ RedSurface *surface = &display->surfaces[surface_id];
+ SpiceCanvas *canvas = surface->context.canvas;
+ ImageItem *item;
+ int stride;
+ int width;
+ int height;
+ int bpp;
+ int all_set;
+
+ spice_assert(area);
+
+ width = area->right - area->left;
+ height = area->bottom - area->top;
+ bpp = SPICE_SURFACE_FMT_DEPTH(surface->context.format) / 8;
+ stride = width * bpp;
+
+ item = (ImageItem *)spice_malloc_n_m(height, stride, sizeof(ImageItem));
+
+ red_channel_pipe_item_init(channel, &item->link, PIPE_ITEM_TYPE_IMAGE);
+
+ item->refs = 1;
+ item->surface_id = surface_id;
+ item->image_format =
+ spice_bitmap_from_surface_type(surface->context.format);
+ item->image_flags = 0;
+ item->pos.x = area->left;
+ item->pos.y = area->top;
+ item->width = width;
+ item->height = height;
+ item->stride = stride;
+ item->top_down = surface->context.top_down;
+ item->can_lossy = can_lossy;
+
+ canvas->ops->read_bits(canvas, item->data, stride, area);
+
+ /* For 32bit non-primary surfaces we need to keep any non-zero
+ high bytes as the surface may be used as source to an alpha_blend */
+ if (!is_primary_surface(display, surface_id) &&
+ item->image_format == SPICE_BITMAP_FMT_32BIT &&
+ rgb32_data_has_alpha(item->width, item->height, item->stride, item->data, &all_set)) {
+ if (all_set) {
+ item->image_flags |= SPICE_IMAGE_FLAGS_HIGH_BITS_SET;
+ } else {
+ item->image_format = SPICE_BITMAP_FMT_RGBA;
+ }
+ }
+
+ if (pos) {
+ red_channel_client_pipe_add_after(RED_CHANNEL_CLIENT(dcc), &item->link, pos);
+ } else {
+ red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &item->link);
+ }
+
+ return item;
+}
+
void dcc_push_surface_image(DisplayChannelClient *dcc, int surface_id)
{
DisplayChannel *display;