I generated a diff without the move, see http://pastebin.com/4G6BtBff > > On Fri, 2015-11-13 at 10:29 -0600, Jonathon Jongsma wrote: > > From: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> > > > > --- > > server/display-channel.c | 526 > > ++++++++++++++++++++++++++++++++++++++++++++ > > server/display-channel.h | 15 +- > > server/red_worker.c | 559 > > ++-------------------------------------------- > > - > > 3 files changed, 552 insertions(+), 548 deletions(-) > > > > diff --git a/server/display-channel.c b/server/display-channel.c > > index 1d5d8d3..4f6cfc4 100644 > > --- a/server/display-channel.c > > +++ b/server/display-channel.c > > @@ -20,6 +20,21 @@ > > > > #include "display-channel.h" > > > > +static stat_time_t display_channel_stat_now(DisplayChannel *display) > > +{ > > +#ifdef RED_WORKER_STAT > > + RedWorker *worker = COMMON_CHANNEL(display)->worker; > > + > > + return stat_now(red_worker_get_clockid(worker)); > > + > > +#else > > + return 0; > > +#endif > > +} > > + > > +#define stat_start(display, var) \ > > + G_GNUC_UNUSED stat_time_t var = display_channel_stat_now((display)); > > + > > void display_channel_compress_stats_reset(DisplayChannel *display) > > { > > spice_return_if_fail(display); > > @@ -406,3 +421,514 @@ bool > > display_channel_surface_has_canvas(DisplayChannel > > *display, > > { > > return display->surfaces[surface_id].context.canvas != NULL; > > } > > + > > +static void streams_update_visible_region(DisplayChannel *display, > > Drawable > > *drawable) > > +{ > > + Ring *ring; > > + RingItem *item; > > + RingItem *dcc_ring_item, *next; > > + DisplayChannelClient *dcc; > > + > > + if (!red_channel_is_connected(RED_CHANNEL(display))) { > > + return; > > + } > > + > > + if (!is_primary_surface(display, drawable->surface_id)) { > > + return; > > + } > > + > > + ring = &display->streams; > > + item = ring_get_head(ring); > > + > > + while (item) { > > + Stream *stream = SPICE_CONTAINEROF(item, Stream, link); > > + StreamAgent *agent; > > + > > + item = ring_next(ring, item); > > + > > + if (stream->current == drawable) { > > + continue; > > + } > > + > > + FOREACH_DCC(display, dcc_ring_item, next, dcc) { > > + agent = &dcc->stream_agents[get_stream_id(display, stream)]; > > + > > + if (region_intersects(&agent->vis_region, &drawable > > ->tree_item.base.rgn)) { > > + region_exclude(&agent->vis_region, &drawable > > ->tree_item.base.rgn); > > + region_exclude(&agent->clip, > > &drawable->tree_item.base.rgn); > > + dcc_add_stream_agent_clip(dcc, agent); > > + } > > + } > > + } > > +} > > + > > + > > +static void current_add_drawable(DisplayChannel *display, > > + Drawable *drawable, RingItem *pos) > > +{ > > + RedSurface *surface; > > + uint32_t surface_id = drawable->surface_id; > > + > > + surface = &display->surfaces[surface_id]; > > + ring_add_after(&drawable->tree_item.base.siblings_link, pos); > > + ring_add(&display->current_list, &drawable->list_link); > > + ring_add(&surface->current_list, &drawable->surface_list_link); > > + display->current_size++; > > + drawable->refs++; > > +} > > + > > +static int current_add_equal(DisplayChannel *display, DrawItem *item, > > TreeItem *other) > > +{ > > + DrawItem *other_draw_item; > > + Drawable *drawable; > > + Drawable *other_drawable; > > + > > + if (other->type != TREE_ITEM_TYPE_DRAWABLE) { > > + return FALSE; > > + } > > + other_draw_item = (DrawItem *)other; > > + > > + if (item->shadow || other_draw_item->shadow || item->effect != > > other_draw_item->effect) { > > + return FALSE; > > + } > > + > > + drawable = SPICE_CONTAINEROF(item, Drawable, tree_item); > > + other_drawable = SPICE_CONTAINEROF(other_draw_item, Drawable, > > tree_item); > > + > > + if (item->effect == QXL_EFFECT_OPAQUE) { > > + int add_after = !!other_drawable->stream && > > + is_drawable_independent_from_surfaces(drawable); > > + stream_maintenance(display, drawable, other_drawable); > > + current_add_drawable(display, drawable, &other->siblings_link); > > + other_drawable->refs++; > > + current_remove_drawable(display, other_drawable); > > + if (add_after) { > > + red_pipes_add_drawable_after(display, drawable, > > other_drawable); > > + } else { > > + red_pipes_add_drawable(display, drawable); > > + } > > + red_pipes_remove_drawable(other_drawable); > > + display_channel_drawable_unref(display, other_drawable); > > + return TRUE; > > + } > > + > > + switch (item->effect) { > > + case QXL_EFFECT_REVERT_ON_DUP: > > + if (is_same_drawable(drawable, other_drawable)) { > > + > > + DisplayChannelClient *dcc; > > + DrawablePipeItem *dpi; > > + RingItem *worker_ring_item, *dpi_ring_item; > > + > > + other_drawable->refs++; > > + current_remove_drawable(display, other_drawable); > > + > > + /* sending the drawable to clients that already received > > + * (or will receive) other_drawable */ > > + worker_ring_item = > > ring_get_head(&RED_CHANNEL(display)->clients); > > + dpi_ring_item = ring_get_head(&other_drawable->pipes); > > + /* dpi contains a sublist of dcc's, ordered the same */ > > + while (worker_ring_item) { > > + dcc = SPICE_CONTAINEROF(worker_ring_item, > > DisplayChannelClient, > > + common.base.channel_link); > > + dpi = SPICE_CONTAINEROF(dpi_ring_item, DrawablePipeItem, > > base); > > + while (worker_ring_item && (!dpi || dcc != dpi->dcc)) { > > + dcc_add_drawable(dcc, drawable); > > + worker_ring_item = ring_next(&RED_CHANNEL(display) > > ->clients, > > + worker_ring_item); > > + dcc = SPICE_CONTAINEROF(worker_ring_item, > > DisplayChannelClient, > > + common.base.channel_link); > > + } > > + > > + if (dpi_ring_item) { > > + dpi_ring_item = ring_next(&other_drawable->pipes, > > dpi_ring_item); > > + } > > + if (worker_ring_item) { > > + worker_ring_item = ring_next(&RED_CHANNEL(display) > > ->clients, > > + worker_ring_item); > > + } > > + } > > + /* not sending other_drawable where possible */ > > + red_pipes_remove_drawable(other_drawable); > > + > > + display_channel_drawable_unref(display, other_drawable); > > + return TRUE; > > + } > > + break; > > + case QXL_EFFECT_OPAQUE_BRUSH: > > + if (is_same_geometry(drawable, other_drawable)) { > > + current_add_drawable(display, drawable, > > &other->siblings_link); > > + red_pipes_remove_drawable(other_drawable); > > + current_remove_drawable(display, other_drawable); > > + red_pipes_add_drawable(display, drawable); > > + return TRUE; > > + } > > + break; > > + case QXL_EFFECT_NOP_ON_DUP: > > + if (is_same_drawable(drawable, other_drawable)) { > > + return TRUE; > > + } > > + break; > > + } > > + return FALSE; > > +} > > + > > +static void __exclude_region(DisplayChannel *display, Ring *ring, TreeItem > > *item, QRegion *rgn, > > + Ring **top_ring, Drawable *frame_candidate) > > +{ > > + QRegion and_rgn; > > + stat_start(display, start_time); > > + > > + region_clone(&and_rgn, rgn); > > + region_and(&and_rgn, &item->rgn); > > + if (!region_is_empty(&and_rgn)) { > > + if (IS_DRAW_ITEM(item)) { > > + DrawItem *draw = (DrawItem *)item; > > + > > + if (draw->effect == QXL_EFFECT_OPAQUE) { > > + region_exclude(rgn, &and_rgn); > > + } > > + > > + if (draw->shadow) { > > + Shadow *shadow; > > + int32_t x = item->rgn.extents.x1; > > + int32_t y = item->rgn.extents.y1; > > + > > + region_exclude(&draw->base.rgn, &and_rgn); > > + shadow = draw->shadow; > > + region_offset(&and_rgn, shadow->base.rgn.extents.x1 - x, > > + shadow->base.rgn.extents.y1 - y); > > + region_exclude(&shadow->base.rgn, &and_rgn); > > + region_and(&and_rgn, &shadow->on_hold); > > + if (!region_is_empty(&and_rgn)) { > > + region_exclude(&shadow->on_hold, &and_rgn); > > + region_or(rgn, &and_rgn); > > + // in flat representation of current, shadow is always > > his owner next > > + if (!tree_item_contained_by((TreeItem*)shadow, > > *top_ring)) { > > + *top_ring = > > tree_item_container_items((TreeItem*)shadow, ring); > > + } > > + } > > + } else { > > + if (frame_candidate) { > > + Drawable *drawable = SPICE_CONTAINEROF(draw, Drawable, > > tree_item); > > + stream_maintenance(display, frame_candidate, > > drawable); > > + } > > + region_exclude(&draw->base.rgn, &and_rgn); > > + } > > + } else if (item->type == TREE_ITEM_TYPE_CONTAINER) { > > + region_exclude(&item->rgn, &and_rgn); > > + > > + if (region_is_empty(&item->rgn)) { //assume container removal > > will follow > > + Shadow *shadow; > > + > > + region_exclude(rgn, &and_rgn); > > + if ((shadow = tree_item_find_shadow(item))) { > > + region_or(rgn, &shadow->on_hold); > > + if (!tree_item_contained_by((TreeItem*)shadow, > > *top_ring)) { > > + *top_ring = > > tree_item_container_items((TreeItem*)shadow, ring); > > + } > > + } > > + } > > + } else { > > + Shadow *shadow; > > + > > + spice_assert(item->type == TREE_ITEM_TYPE_SHADOW); > > + shadow = (Shadow *)item; > > + region_exclude(rgn, &and_rgn); > > + region_or(&shadow->on_hold, &and_rgn); > > + } > > + } > > + region_destroy(&and_rgn); > > + stat_add(&display->__exclude_stat, start_time); > > +} > > + > > +static void exclude_region(DisplayChannel *display, Ring *ring, RingItem > > *ring_item, > > + QRegion *rgn, TreeItem **last, Drawable > > *frame_candidate) > > +{ > > + Ring *top_ring; > > + stat_start(display, start_time); > > + > > + if (!ring_item) { > > + return; > > + } > > + > > + top_ring = ring; > > + > > + for (;;) { > > + TreeItem *now = SPICE_CONTAINEROF(ring_item, TreeItem, > > siblings_link); > > + Container *container = now->container; > > + > > + spice_assert(!region_is_empty(&now->rgn)); > > + > > + if (region_intersects(rgn, &now->rgn)) { > > + __exclude_region(display, ring, now, rgn, &top_ring, > > frame_candidate); > > + > > + if (region_is_empty(&now->rgn)) { > > + spice_assert(now->type != TREE_ITEM_TYPE_SHADOW); > > + ring_item = now->siblings_link.prev; > > + current_remove(display, now); > > + if (last && *last == now) { > > + *last = (TreeItem *)ring_next(ring, ring_item); > > + } > > + } else if (now->type == TREE_ITEM_TYPE_CONTAINER) { > > + Container *container = (Container *)now; > > + if ((ring_item = ring_get_head(&container->items))) { > > + ring = &container->items; > > + spice_assert(((TreeItem *)ring_item)->container); > > + continue; > > + } > > + ring_item = &now->siblings_link; > > + } > > + > > + if (region_is_empty(rgn)) { > > + stat_add(&display->exclude_stat, start_time); > > + return; > > + } > > + } > > + > > + while ((last && *last == (TreeItem *)ring_item) || > > + !(ring_item = ring_next(ring, ring_item))) { > > + if (ring == top_ring) { > > + stat_add(&display->exclude_stat, start_time); > > + return; > > + } > > + ring_item = &container->base.siblings_link; > > + container = container->base.container; > > + ring = (container) ? &container->items : top_ring; > > + } > > + } > > +} > > + > > +static int current_add_with_shadow(DisplayChannel *display, Ring *ring, > > Drawable *item) > > +{ > > + stat_start(display, start_time); > > + ++display->add_with_shadow_count; > > + > > + RedDrawable *red_drawable = item->red_drawable; > > + SpicePoint delta = { > > + .x = red_drawable->u.copy_bits.src_pos.x - > > red_drawable->bbox.left, > > + .y = red_drawable->u.copy_bits.src_pos.y - red_drawable->bbox.top > > + }; > > + > > + Shadow *shadow = shadow_new(&item->tree_item, &delta); > > + if (!shadow) { > > + stat_add(&display->add_stat, start_time); > > + return FALSE; > > + } > > + // item and his shadow must initially be placed in the same container. > > + // for now putting them on root. > > + > > + // only primary surface streams are supported > > + if (is_primary_surface(display, item->surface_id)) { > > + detach_streams_behind(display, &shadow->base.rgn, NULL); > > + } > > + > > + ring_add(ring, &shadow->base.siblings_link); > > + current_add_drawable(display, item, ring); > > + if (item->tree_item.effect == QXL_EFFECT_OPAQUE) { > > + QRegion exclude_rgn; > > + region_clone(&exclude_rgn, &item->tree_item.base.rgn); > > + exclude_region(display, ring, &shadow->base.siblings_link, > > &exclude_rgn, NULL, NULL); > > + region_destroy(&exclude_rgn); > > + streams_update_visible_region(display, item); > > + } else { > > + if (is_primary_surface(display, item->surface_id)) { > > + detach_streams_behind(display, &item->tree_item.base.rgn, > > item); > > + } > > + } > > + stat_add(&display->add_stat, start_time); > > + return TRUE; > > +} > > + > > +static int current_add(DisplayChannel *display, Ring *ring, Drawable > > *drawable) > > +{ > > + DrawItem *item = &drawable->tree_item; > > + RingItem *now; > > + QRegion exclude_rgn; > > + RingItem *exclude_base = NULL; > > + stat_start(display, start_time); > > + > > + spice_return_val_if_fail(!region_is_empty(&item->base.rgn), FALSE); > > + region_init(&exclude_rgn); > > + now = ring_next(ring, ring); > > + > > + while (now) { > > + TreeItem *sibling = SPICE_CONTAINEROF(now, TreeItem, > > siblings_link); > > + int test_res; > > + > > + if (!region_bounds_intersects(&item->base.rgn, &sibling->rgn)) { > > + now = ring_next(ring, now); > > + continue; > > + } > > + test_res = region_test(&item->base.rgn, &sibling->rgn, > > REGION_TEST_ALL); > > + if (!(test_res & REGION_TEST_SHARED)) { > > + now = ring_next(ring, now); > > + continue; > > + } else if (sibling->type != TREE_ITEM_TYPE_SHADOW) { > > + if (!(test_res & REGION_TEST_RIGHT_EXCLUSIVE) && > > + !(test_res & > > REGION_TEST_LEFT_EXCLUSIVE) && > > + > > current_add_equal(display, > > item, sibling)) { > > + stat_add(&display->add_stat, start_time); > > + return FALSE; > > + } > > + > > + if (!(test_res & REGION_TEST_RIGHT_EXCLUSIVE) && item->effect > > == > > QXL_EFFECT_OPAQUE) { > > + Shadow *shadow; > > + int skip = now == exclude_base; > > + > > + if ((shadow = tree_item_find_shadow(sibling))) { > > + if (exclude_base) { > > + TreeItem *next = sibling; > > + exclude_region(display, ring, exclude_base, > > &exclude_rgn, &next, NULL); > > + if (next != sibling) { > > + now = next ? &next->siblings_link : NULL; > > + exclude_base = NULL; > > + continue; > > + } > > + } > > + region_or(&exclude_rgn, &shadow->on_hold); > > + } > > + now = now->prev; > > + current_remove(display, sibling); > > + now = ring_next(ring, now); > > + if (shadow || skip) { > > + exclude_base = now; > > + } > > + continue; > > + } > > + > > + if (!(test_res & REGION_TEST_LEFT_EXCLUSIVE) && > > is_opaque_item(sibling)) { > > + Container *container; > > + > > + if (exclude_base) { > > + exclude_region(display, ring, exclude_base, > > &exclude_rgn, > > NULL, NULL); > > + region_clear(&exclude_rgn); > > + exclude_base = NULL; > > + } > > + if (sibling->type == TREE_ITEM_TYPE_CONTAINER) { > > + container = (Container *)sibling; > > + ring = &container->items; > > + item->base.container = container; > > + now = ring_next(ring, ring); > > + continue; > > + } > > + spice_assert(IS_DRAW_ITEM(sibling)); > > + if (!DRAW_ITEM(sibling)->container_root) { > > + container = container_new(DRAW_ITEM(sibling)); > > + if (!container) { > > + spice_warning("create new container failed"); > > + region_destroy(&exclude_rgn); > > + return FALSE; > > + } > > + item->base.container = container; > > + ring = &container->items; > > + } > > + } > > + } > > + if (!exclude_base) { > > + exclude_base = now; > > + } > > + break; > > + } > > + if (item->effect == QXL_EFFECT_OPAQUE) { > > + region_or(&exclude_rgn, &item->base.rgn); > > + exclude_region(display, ring, exclude_base, &exclude_rgn, NULL, > > drawable); > > + stream_trace_update(display, drawable); > > + streams_update_visible_region(display, drawable); > > + /* > > + * Performing the insertion after exclude_region for > > + * safety (todo: Not sure if exclude_region can affect the > > drawable > > + * if it is added to the tree before calling exclude_region). > > + */ > > + current_add_drawable(display, drawable, ring); > > + } else { > > + /* > > + * red_detach_streams_behind can affect the current tree since it > > may > > + * trigger calls to update_area. Thus, the drawable should be > > added > > to the tree > > + * before calling red_detach_streams_behind > > + */ > > + current_add_drawable(display, drawable, ring); > > + if (is_primary_surface(display, drawable->surface_id)) { > > + detach_streams_behind(display, &drawable->tree_item.base.rgn, > > drawable); > > + } > > + } > > + region_destroy(&exclude_rgn); > > + stat_add(&display->add_stat, start_time); > > + return TRUE; > > +} > > + > > +static bool drawable_can_stream(DisplayChannel *display, Drawable > > *drawable) > > +{ > > + RedDrawable *red_drawable = drawable->red_drawable; > > + SpiceImage *image; > > + > > + if (display->stream_video == SPICE_STREAM_VIDEO_OFF) > > + return FALSE; > > on this test and the following ones, the braces were removed compared to the > previous version. Not a big deal, but in general our coding style is to > always > use braces. > I'll add again braces. > > > + > > + if (!is_primary_surface(display, drawable->surface_id)) > > + return FALSE; > > + > > + if (drawable->tree_item.effect != QXL_EFFECT_OPAQUE || > > + red_drawable->type != QXL_DRAW_COPY || > > + red_drawable->u.copy.rop_descriptor != SPICE_ROPD_OP_PUT) > > + return FALSE; > > + > > + image = red_drawable->u.copy.src_bitmap; > > + if (image == NULL || > > + image->descriptor.type != SPICE_IMAGE_TYPE_BITMAP) > > + return FALSE; > > + > > + if (display->stream_video == SPICE_STREAM_VIDEO_FILTER) { > > + SpiceRect* rect; > > + int size; > > + > > + rect = &drawable->red_drawable->u.copy.src_area; > > + size = (rect->right - rect->left) * (rect->bottom - rect->top); > > + if (size < RED_STREAM_MIN_SIZE) > > + return FALSE; > > + } > > + > > + return TRUE; > > +} > > + > > +void display_channel_print_stats(DisplayChannel *display) > > +{ > > +#ifdef RED_WORKER_STAT > > + stat_time_t total = display->add_stat.total; > > + spice_info("add with shadow count %u", > > + display->add_with_shadow_count); > > + display->add_with_shadow_count = 0; > > + spice_info("add[%u] %f exclude[%u] %f __exclude[%u] %f", > > + display->add_stat.count, > > + stat_cpu_time_to_sec(total), > > + display->exclude_stat.count, > > + stat_cpu_time_to_sec(display->exclude_stat.total), > > + display->__exclude_stat.count, > > + stat_cpu_time_to_sec(display->__exclude_stat.total)); > > + spice_info("add %f%% exclude %f%% exclude2 %f%% __exclude %f%%", > > + (double)(total - display->exclude_stat.total) / total * > > 100, > > + (double)(display->exclude_stat.total) / total * 100, > > + (double)(display->exclude_stat.total - > > + display->__exclude_stat.total) / display > > ->exclude_stat.total * 100, > > + (double)(display->__exclude_stat.total) / display > > ->exclude_stat.total * 100); > > + stat_reset(&display->add_stat); > > + stat_reset(&display->exclude_stat); > > + stat_reset(&display->__exclude_stat); > > +#endif > > +} > > As far as I can tell, this function is no longer used. See below. > I think for the moment I'll add again the code that calls this functions. > > > + > > +int display_channel_add_drawable(DisplayChannel *display, Drawable > > *drawable) > > +{ > > + int ret = FALSE, surface_id = drawable->surface_id; > > + RedDrawable *red_drawable = drawable->red_drawable; > > + Ring *ring = &display->surfaces[surface_id].current; > > + > > + if (has_shadow(red_drawable)) { > > + ret = current_add_with_shadow(display, ring, drawable); > > + } else { > > + drawable->streamable = drawable_can_stream(display, drawable); > > + ret = current_add(display, ring, drawable); > > + } > > + > > + return ret; > > +} > > compared with the previous version (red_add_drawable()), this function > removes > the call to print_stats() (which was renamed to > display_channel_print_stats()). > I think this was the only location where this function was called. I don't > know > whether this debug information was useful or not, since I've never used it. > But > if we're not going to ever print out the stats, we should probably just get > rid > of the funciton. > If we decide to remove this feature we should have a better change than this > > > diff --git a/server/display-channel.h b/server/display-channel.h > > index ce9ce50..432cc61 100644 > > --- a/server/display-channel.h > > +++ b/server/display-channel.h > > @@ -356,12 +356,12 @@ struct DisplayChannel { > > RedCompressBuf *free_compress_bufs; > > > > /* TODO: some day unify this, make it more runtime.. */ > > + uint32_t add_count; > > As far as I can tell, this is no longer used anywhere due to the removal of > the > print_stats() functionality from add_drawable() above > > > > + uint32_t add_with_shadow_count; > > ...and this one is incremented in current_add_with_shadow(), but it is only > read > in display_channel_print_stats() (which is no longer called from anywhere). > So it seems these two values could perhaps be removed. So I don't understand > why > they were moved out from inside the #ifdef... > I moved them back adding a #ifdef where needed for the shadow. > > > #ifdef RED_WORKER_STAT > > stat_info_t add_stat; > > stat_info_t exclude_stat; > > stat_info_t __exclude_stat; > > - uint32_t add_count; > > - uint32_t add_with_shadow_count; > > #endif > > #ifdef RED_STATISTICS > > uint64_t *cache_hits_counter; > > @@ -415,6 +415,8 @@ void > > display_channel_surface_unref > > (DisplayCha > > bool display_channel_surface_has_canvas > > (DisplayChannel *display, > > > > uint32_t surface_id); > > void display_channel_show_tree > > (DisplayChannel *display); > > +int display_channel_add_drawable > > (DisplayChannel *display, > > + > > Drawable *drawable); > > > > static inline int is_equal_path(SpicePath *path1, SpicePath *path2) > > { > > @@ -531,4 +533,13 @@ static inline void region_add_clip_rects(QRegion *rgn, > > SpiceClipRects *data) > > } > > } > > > > +void red_pipes_add_drawable(DisplayChannel *display, Drawable *drawable); > > +void current_remove_drawable(DisplayChannel *display, Drawable *item); > > +void red_pipes_add_drawable_after(DisplayChannel *display, > > + Drawable *drawable, Drawable > > *pos_after); > > +void red_pipes_remove_drawable(Drawable *drawable); > > +void dcc_add_drawable(DisplayChannelClient *dcc, Drawable *drawable); > > +void current_remove(DisplayChannel *display, TreeItem *item); > > +void detach_streams_behind(DisplayChannel *display, QRegion *region, > > Drawable > > *drawable); > > + > > #endif /* DISPLAY_CHANNEL_H_ */ > > diff --git a/server/red_worker.c b/server/red_worker.c > > index fcb5128..8aa7e70 100644 > > --- a/server/red_worker.c > > +++ b/server/red_worker.c > > @@ -492,7 +492,7 @@ static int cursor_is_connected(RedWorker *worker) > > red_channel_is_connected(RED_CHANNEL(worker->cursor_channel)); > > } > > > > -static void dcc_add_drawable(DisplayChannelClient *dcc, Drawable > > *drawable) > > +void dcc_add_drawable(DisplayChannelClient *dcc, Drawable *drawable) > > { > > DrawablePipeItem *dpi; > > > > @@ -501,7 +501,7 @@ static void dcc_add_drawable(DisplayChannelClient *dcc, > > Drawable *drawable) > > red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &dpi > > ->dpi_pipe_item); > > } > > > > -static void red_pipes_add_drawable(DisplayChannel *display, Drawable > > *drawable) > > +void red_pipes_add_drawable(DisplayChannel *display, Drawable *drawable) > > { > > DisplayChannelClient *dcc; > > RingItem *dcc_ring_item, *next; > > @@ -524,8 +524,8 @@ static void > > dcc_add_drawable_to_tail(DisplayChannelClient > > *dcc, Drawable *drawab > > red_channel_client_pipe_add_tail(RED_CHANNEL_CLIENT(dcc), &dpi > > ->dpi_pipe_item); > > } > > > > -static inline void red_pipes_add_drawable_after(DisplayChannel *display, > > - Drawable *drawable, > > Drawable > > *pos_after) > > +void red_pipes_add_drawable_after(DisplayChannel *display, > > + Drawable *drawable, Drawable *pos_after) > > { > > DrawablePipeItem *dpi, *dpi_pos_after; > > RingItem *dpi_link, *dpi_next; > > @@ -571,7 +571,7 @@ static inline PipeItem > > *red_pipe_get_tail(DisplayChannelClient *dcc) > > return (PipeItem*)ring_get_tail(&RED_CHANNEL_CLIENT(dcc)->pipe); > > } > > > > -static inline void red_pipes_remove_drawable(Drawable *drawable) > > +void red_pipes_remove_drawable(Drawable *drawable) > > { > > DrawablePipeItem *dpi; > > RingItem *item, *next; > > @@ -816,8 +816,9 @@ static void red_flush_source_surfaces(DisplayChannel > > *display, Drawable *drawabl > > } > > } > > > > -static inline void current_remove_drawable(DisplayChannel *display, > > Drawable > > *item) > > +void current_remove_drawable(DisplayChannel *display, Drawable *item) > > { > > + /* todo: move all to unref? */ > > display_stream_trace_add_drawable(display, item); > > draw_item_remove_shadow(&item->tree_item); > > ring_remove(&item->tree_item.base.siblings_link); > > @@ -827,13 +828,7 @@ static inline void > > current_remove_drawable(DisplayChannel > > *display, Drawable *it > > display->current_size--; > > } > > > > -static void remove_drawable(DisplayChannel *display, Drawable *drawable) > > -{ > > - red_pipes_remove_drawable(drawable); > > - current_remove_drawable(display, drawable); > > -} > > - > > -static inline void current_remove(DisplayChannel *display, TreeItem *item) > > +void current_remove(DisplayChannel *display, TreeItem *item) > > { > > TreeItem *now = item; > > > > @@ -843,8 +838,10 @@ static inline void current_remove(DisplayChannel > > *display, TreeItem *item) > > RingItem *ring_item; > > > > if (now->type == TREE_ITEM_TYPE_DRAWABLE) { > > + Drawable *drawable = SPICE_CONTAINEROF(now, Drawable, > > tree_item); > > ring_item = now->siblings_link.prev; > > - remove_drawable(display, SPICE_CONTAINEROF(now, Drawable, > > tree_item)); > > + red_pipes_remove_drawable(drawable); > > + current_remove_drawable(display, drawable); > > } else { > > Container *container = (Container *)now; > > > > @@ -975,152 +972,6 @@ static void > > red_clear_surface_drawables_from_pipes(DisplayChannel *display, > > } > > } > > > > -static void __exclude_region(DisplayChannel *display, Ring *ring, TreeItem > > *item, QRegion *rgn, > > - Ring **top_ring, Drawable *frame_candidate) > > -{ > > - QRegion and_rgn; > > -#ifdef RED_WORKER_STAT > > - RedWorker *worker = COMMON_CHANNEL(display)->worker; > > - stat_time_t start_time = stat_now(worker->clockid); > > -#endif > > - > > - region_clone(&and_rgn, rgn); > > - region_and(&and_rgn, &item->rgn); > > - if (!region_is_empty(&and_rgn)) { > > - if (IS_DRAW_ITEM(item)) { > > - DrawItem *draw = (DrawItem *)item; > > - > > - if (draw->effect == QXL_EFFECT_OPAQUE) { > > - region_exclude(rgn, &and_rgn); > > - } > > - > > - if (draw->shadow) { > > - Shadow *shadow; > > - int32_t x = item->rgn.extents.x1; > > - int32_t y = item->rgn.extents.y1; > > - > > - region_exclude(&draw->base.rgn, &and_rgn); > > - shadow = draw->shadow; > > - region_offset(&and_rgn, shadow->base.rgn.extents.x1 - x, > > - shadow->base.rgn.extents.y1 - y); > > - region_exclude(&shadow->base.rgn, &and_rgn); > > - region_and(&and_rgn, &shadow->on_hold); > > - if (!region_is_empty(&and_rgn)) { > > - region_exclude(&shadow->on_hold, &and_rgn); > > - region_or(rgn, &and_rgn); > > - // in flat representation of current, shadow is always > > his owner next > > - if (!tree_item_contained_by((TreeItem*)shadow, > > *top_ring)) { > > - *top_ring = > > tree_item_container_items((TreeItem*)shadow, ring); > > - } > > - } > > - } else { > > - if (frame_candidate) { > > - Drawable *drawable = SPICE_CONTAINEROF(draw, Drawable, > > tree_item); > > - stream_maintenance(display, frame_candidate, > > drawable); > > - } > > - region_exclude(&draw->base.rgn, &and_rgn); > > - } > > - } else if (item->type == TREE_ITEM_TYPE_CONTAINER) { > > - region_exclude(&item->rgn, &and_rgn); > > - > > - if (region_is_empty(&item->rgn)) { //assume container removal > > will follow > > - Shadow *shadow; > > - > > - region_exclude(rgn, &and_rgn); > > - if ((shadow = tree_item_find_shadow(item))) { > > - region_or(rgn, &shadow->on_hold); > > - if (!tree_item_contained_by((TreeItem*)shadow, > > *top_ring)) { > > - *top_ring = > > tree_item_container_items((TreeItem*)shadow, ring); > > - } > > - } > > - } > > - } else { > > - Shadow *shadow; > > - > > - spice_assert(item->type == TREE_ITEM_TYPE_SHADOW); > > - shadow = (Shadow *)item; > > - region_exclude(rgn, &and_rgn); > > - region_or(&shadow->on_hold, &and_rgn); > > - } > > - } > > - region_destroy(&and_rgn); > > - stat_add(&display->__exclude_stat, start_time); > > -} > > - > > -static void exclude_region(DisplayChannel *display, Ring *ring, RingItem > > *ring_item, > > - QRegion *rgn, TreeItem **last, Drawable > > *frame_candidate) > > -{ > > -#ifdef RED_WORKER_STAT > > - RedWorker *worker = COMMON_CHANNEL(display)->worker; > > - stat_time_t start_time = stat_now(worker->clockid); > > -#endif > > - Ring *top_ring; > > - > > - if (!ring_item) { > > - return; > > - } > > - > > - top_ring = ring; > > - > > - for (;;) { > > - TreeItem *now = SPICE_CONTAINEROF(ring_item, TreeItem, > > siblings_link); > > - Container *container = now->container; > > - > > - spice_assert(!region_is_empty(&now->rgn)); > > - > > - if (region_intersects(rgn, &now->rgn)) { > > - __exclude_region(display, ring, now, rgn, &top_ring, > > frame_candidate); > > - > > - if (region_is_empty(&now->rgn)) { > > - spice_assert(now->type != TREE_ITEM_TYPE_SHADOW); > > - ring_item = now->siblings_link.prev; > > - current_remove(display, now); > > - if (last && *last == now) { > > - *last = (TreeItem *)ring_next(ring, ring_item); > > - } > > - } else if (now->type == TREE_ITEM_TYPE_CONTAINER) { > > - Container *container = (Container *)now; > > - if ((ring_item = ring_get_head(&container->items))) { > > - ring = &container->items; > > - spice_assert(((TreeItem *)ring_item)->container); > > - continue; > > - } > > - ring_item = &now->siblings_link; > > - } > > - > > - if (region_is_empty(rgn)) { > > - stat_add(&display->exclude_stat, start_time); > > - return; > > - } > > - } > > - > > - while ((last && *last == (TreeItem *)ring_item) || > > - !(ring_item = ring_next(ring, ring_item))) { > > - if (ring == top_ring) { > > - stat_add(&display->exclude_stat, start_time); > > - return; > > - } > > - ring_item = &container->base.siblings_link; > > - container = container->base.container; > > - ring = (container) ? &container->items : top_ring; > > - } > > - } > > -} > > - > > -static void current_add_drawable(DisplayChannel *display, > > - Drawable *drawable, RingItem *pos) > > -{ > > - RedSurface *surface; > > - uint32_t surface_id = drawable->surface_id; > > - > > - surface = &display->surfaces[surface_id]; > > - ring_add_after(&drawable->tree_item.base.siblings_link, pos); > > - ring_add(&display->current_list, &drawable->list_link); > > - ring_add(&surface->current_list, &drawable->surface_list_link); > > - display->current_size++; > > - drawable->refs++; > > -} > > - > > void detach_stream(DisplayChannel *display, Stream *stream, > > int detach_sized) > > { > > @@ -1243,7 +1094,7 @@ static void detach_stream_gracefully(DisplayChannel > > *display, Stream *stream, > > * involves sending an upgrade image to the client, this > > drawable > > won't be rendered > > * (see dcc_detach_stream_gracefully). > > */ > > -static void detach_streams_behind(DisplayChannel *display, QRegion > > *region, > > Drawable *drawable) > > +void detach_streams_behind(DisplayChannel *display, QRegion *region, > > Drawable > > *drawable) > > { > > Ring *ring = &display->streams; > > RingItem *item = ring_get_head(ring); > > @@ -1276,46 +1127,6 @@ static void detach_streams_behind(DisplayChannel > > *display, QRegion *region, Draw > > } > > } > > > > -static void streams_update_visible_region(DisplayChannel *display, > > Drawable > > *drawable) > > -{ > > - Ring *ring; > > - RingItem *item; > > - RingItem *dcc_ring_item, *next; > > - DisplayChannelClient *dcc; > > - > > - if (!red_channel_is_connected(RED_CHANNEL(display))) { > > - return; > > - } > > - > > - if (!is_primary_surface(display, drawable->surface_id)) { > > - return; > > - } > > - > > - ring = &display->streams; > > - item = ring_get_head(ring); > > - > > - while (item) { > > - Stream *stream = SPICE_CONTAINEROF(item, Stream, link); > > - StreamAgent *agent; > > - > > - item = ring_next(ring, item); > > - > > - if (stream->current == drawable) { > > - continue; > > - } > > - > > - FOREACH_DCC(display, dcc_ring_item, next, dcc) { > > - agent = &dcc->stream_agents[get_stream_id(display, stream)]; > > - > > - if (region_intersects(&agent->vis_region, &drawable > > ->tree_item.base.rgn)) { > > - region_exclude(&agent->vis_region, &drawable > > ->tree_item.base.rgn); > > - region_exclude(&agent->clip, > > &drawable->tree_item.base.rgn); > > - dcc_add_stream_agent_clip(dcc, agent); > > - } > > - } > > - } > > -} > > - > > static void display_channel_streams_timeout(DisplayChannel *display) > > { > > Ring *ring = &display->streams; > > @@ -1552,350 +1363,6 @@ static void > > dcc_destroy_stream_agents(DisplayChannelClient *dcc) > > } > > } > > > > -static inline int red_current_add_equal(DisplayChannel *display, DrawItem > > *item, TreeItem *other) > > -{ > > - DrawItem *other_draw_item; > > - Drawable *drawable; > > - Drawable *other_drawable; > > - > > - if (other->type != TREE_ITEM_TYPE_DRAWABLE) { > > - return FALSE; > > - } > > - other_draw_item = (DrawItem *)other; > > - > > - if (item->shadow || other_draw_item->shadow || item->effect != > > other_draw_item->effect) { > > - return FALSE; > > - } > > - > > - drawable = SPICE_CONTAINEROF(item, Drawable, tree_item); > > - other_drawable = SPICE_CONTAINEROF(other_draw_item, Drawable, > > tree_item); > > - > > - if (item->effect == QXL_EFFECT_OPAQUE) { > > - int add_after = !!other_drawable->stream && > > - is_drawable_independent_from_surfaces(drawable); > > - stream_maintenance(display, drawable, other_drawable); > > - current_add_drawable(display, drawable, &other->siblings_link); > > - other_drawable->refs++; > > - current_remove_drawable(display, other_drawable); > > - if (add_after) { > > - red_pipes_add_drawable_after(display, drawable, > > other_drawable); > > - } else { > > - red_pipes_add_drawable(display, drawable); > > - } > > - red_pipes_remove_drawable(other_drawable); > > - display_channel_drawable_unref(display, other_drawable); > > - return TRUE; > > - } > > - > > - switch (item->effect) { > > - case QXL_EFFECT_REVERT_ON_DUP: > > - if (is_same_drawable(drawable, other_drawable)) { > > - > > - DisplayChannelClient *dcc; > > - DrawablePipeItem *dpi; > > - RingItem *worker_ring_item, *dpi_ring_item; > > - > > - other_drawable->refs++; > > - current_remove_drawable(display, other_drawable); > > - > > - /* sending the drawable to clients that already received > > - * (or will receive) other_drawable */ > > - worker_ring_item = > > ring_get_head(&RED_CHANNEL(display)->clients); > > - dpi_ring_item = ring_get_head(&other_drawable->pipes); > > - /* dpi contains a sublist of dcc's, ordered the same */ > > - while (worker_ring_item) { > > - dcc = SPICE_CONTAINEROF(worker_ring_item, > > DisplayChannelClient, > > - common.base.channel_link); > > - dpi = SPICE_CONTAINEROF(dpi_ring_item, DrawablePipeItem, > > base); > > - while (worker_ring_item && (!dpi || dcc != dpi->dcc)) { > > - dcc_add_drawable(dcc, drawable); > > - worker_ring_item = ring_next(&RED_CHANNEL(display) > > ->clients, > > - worker_ring_item); > > - dcc = SPICE_CONTAINEROF(worker_ring_item, > > DisplayChannelClient, > > - common.base.channel_link); > > - } > > - > > - if (dpi_ring_item) { > > - dpi_ring_item = ring_next(&other_drawable->pipes, > > dpi_ring_item); > > - } > > - if (worker_ring_item) { > > - worker_ring_item = ring_next(&RED_CHANNEL(display) > > ->clients, > > - worker_ring_item); > > - } > > - } > > - /* not sending other_drawable where possible */ > > - red_pipes_remove_drawable(other_drawable); > > - > > - display_channel_drawable_unref(display, other_drawable); > > - return TRUE; > > - } > > - break; > > - case QXL_EFFECT_OPAQUE_BRUSH: > > - if (is_same_geometry(drawable, other_drawable)) { > > - current_add_drawable(display, drawable, > > &other->siblings_link); > > - remove_drawable(display, other_drawable); > > - red_pipes_add_drawable(display, drawable); > > - return TRUE; > > - } > > - break; > > - case QXL_EFFECT_NOP_ON_DUP: > > - if (is_same_drawable(drawable, other_drawable)) { > > - return TRUE; > > - } > > - break; > > - } > > - return FALSE; > > -} > > - > > -static int current_add(DisplayChannel *display, Ring *ring, Drawable > > *drawable) > > -{ > > - DrawItem *item = &drawable->tree_item; > > -#ifdef RED_WORKER_STAT > > - RedWorker *worker = COMMON_CHANNEL(display)->worker; > > - stat_time_t start_time = stat_now(worker->clockid); > > -#endif > > - RingItem *now; > > - QRegion exclude_rgn; > > - RingItem *exclude_base = NULL; > > - > > - spice_return_val_if_fail(!region_is_empty(&item->base.rgn), FALSE); > > - region_init(&exclude_rgn); > > - now = ring_next(ring, ring); > > - > > - while (now) { > > - TreeItem *sibling = SPICE_CONTAINEROF(now, TreeItem, > > siblings_link); > > - int test_res; > > - > > - if (!region_bounds_intersects(&item->base.rgn, &sibling->rgn)) { > > - now = ring_next(ring, now); > > - continue; > > - } > > - test_res = region_test(&item->base.rgn, &sibling->rgn, > > REGION_TEST_ALL); > > - if (!(test_res & REGION_TEST_SHARED)) { > > - now = ring_next(ring, now); > > - continue; > > - } else if (sibling->type != TREE_ITEM_TYPE_SHADOW) { > > - if (!(test_res & REGION_TEST_RIGHT_EXCLUSIVE) && > > - !(test_res & > > REGION_TEST_LEFT_EXCLUSIVE) && > > - > > red_current_add_equal(display, item, sibling)) { > > - stat_add(&display->add_stat, start_time); > > - return FALSE; > > - } > > - > > - if (!(test_res & REGION_TEST_RIGHT_EXCLUSIVE) && item->effect > > == > > QXL_EFFECT_OPAQUE) { > > - Shadow *shadow; > > - int skip = now == exclude_base; > > - > > - if ((shadow = tree_item_find_shadow(sibling))) { > > - if (exclude_base) { > > - TreeItem *next = sibling; > > - exclude_region(display, ring, exclude_base, > > &exclude_rgn, &next, NULL); > > - if (next != sibling) { > > - now = next ? &next->siblings_link : NULL; > > - exclude_base = NULL; > > - continue; > > - } > > - } > > - region_or(&exclude_rgn, &shadow->on_hold); > > - } > > - now = now->prev; > > - current_remove(display, sibling); > > - now = ring_next(ring, now); > > - if (shadow || skip) { > > - exclude_base = now; > > - } > > - continue; > > - } > > - > > - if (!(test_res & REGION_TEST_LEFT_EXCLUSIVE) && > > is_opaque_item(sibling)) { > > - Container *container; > > - > > - if (exclude_base) { > > - exclude_region(display, ring, exclude_base, > > &exclude_rgn, > > NULL, NULL); > > - region_clear(&exclude_rgn); > > - exclude_base = NULL; > > - } > > - if (sibling->type == TREE_ITEM_TYPE_CONTAINER) { > > - container = (Container *)sibling; > > - ring = &container->items; > > - item->base.container = container; > > - now = ring_next(ring, ring); > > - continue; > > - } > > - spice_assert(IS_DRAW_ITEM(sibling)); > > - if (!DRAW_ITEM(sibling)->container_root) { > > - container = container_new(DRAW_ITEM(sibling)); > > - if (!container) { > > - spice_warning("create new container failed"); > > - region_destroy(&exclude_rgn); > > - return FALSE; > > - } > > - item->base.container = container; > > - ring = &container->items; > > - } > > - } > > - } > > - if (!exclude_base) { > > - exclude_base = now; > > - } > > - break; > > - } > > - if (item->effect == QXL_EFFECT_OPAQUE) { > > - region_or(&exclude_rgn, &item->base.rgn); > > - exclude_region(display, ring, exclude_base, &exclude_rgn, NULL, > > drawable); > > - stream_trace_update(display, drawable); > > - streams_update_visible_region(display, drawable); > > - /* > > - * Performing the insertion after exclude_region for > > - * safety (todo: Not sure if exclude_region can affect the > > drawable > > - * if it is added to the tree before calling exclude_region). > > - */ > > - current_add_drawable(display, drawable, ring); > > - } else { > > - /* > > - * red_detach_streams_behind can affect the current tree since it > > may > > - * trigger calls to update_area. Thus, the drawable should be > > added > > to the tree > > - * before calling red_detach_streams_behind > > - */ > > - current_add_drawable(display, drawable, ring); > > - if (is_primary_surface(display, drawable->surface_id)) { > > - detach_streams_behind(display, &drawable->tree_item.base.rgn, > > drawable); > > - } > > - } > > - region_destroy(&exclude_rgn); > > - stat_add(&display->add_stat, start_time); > > - return TRUE; > > -} > > - > > -static int current_add_with_shadow(DisplayChannel *display, Ring *ring, > > Drawable *item) > > -{ > > -#ifdef RED_WORKER_STAT > > - RedWorker *worker = COMMON_CHANNEL(display)->worker; > > - stat_time_t start_time = stat_now(worker->clockid); > > - ++display->add_with_shadow_count; > > -#endif > > - > > - RedDrawable *red_drawable = item->red_drawable; > > - SpicePoint delta = { > > - .x = red_drawable->u.copy_bits.src_pos.x - > > red_drawable->bbox.left, > > - .y = red_drawable->u.copy_bits.src_pos.y - red_drawable->bbox.top > > - }; > > - > > - Shadow *shadow = shadow_new(&item->tree_item, &delta); > > - if (!shadow) { > > - stat_add(&display->add_stat, start_time); > > - return FALSE; > > - } > > - // item and his shadow must initially be placed in the same container. > > - // for now putting them on root. > > - > > - // only primary surface streams are supported > > - if (is_primary_surface(display, item->surface_id)) { > > - detach_streams_behind(display, &shadow->base.rgn, NULL); > > - } > > - > > - ring_add(ring, &shadow->base.siblings_link); > > - current_add_drawable(display, item, ring); > > - if (item->tree_item.effect == QXL_EFFECT_OPAQUE) { > > - QRegion exclude_rgn; > > - region_clone(&exclude_rgn, &item->tree_item.base.rgn); > > - exclude_region(display, ring, &shadow->base.siblings_link, > > &exclude_rgn, NULL, NULL); > > - region_destroy(&exclude_rgn); > > - streams_update_visible_region(display, item); > > - } else { > > - if (is_primary_surface(display, item->surface_id)) { > > - detach_streams_behind(display, &item->tree_item.base.rgn, > > item); > > - } > > - } > > - stat_add(&display->add_stat, start_time); > > - return TRUE; > > -} > > - > > -static void drawable_update_streamable(DisplayChannel *display, Drawable > > *drawable) > > -{ > > - RedDrawable *red_drawable = drawable->red_drawable; > > - SpiceImage *image; > > - > > - if (display->stream_video == SPICE_STREAM_VIDEO_OFF) { > > - return; > > - } > > - > > - if (!is_primary_surface(display, drawable->surface_id)) { > > - return; > > - } > > - > > - if (drawable->tree_item.effect != QXL_EFFECT_OPAQUE || > > - red_drawable->type != QXL_DRAW_COPY || > > - red_drawable->u.copy.rop_descriptor != SPICE_ROPD_OP_PUT) { > > - return; > > - } > > - > > - image = red_drawable->u.copy.src_bitmap; > > - if (image == NULL || > > - image->descriptor.type != SPICE_IMAGE_TYPE_BITMAP) { > > - return; > > - } > > - > > - if (display->stream_video == SPICE_STREAM_VIDEO_FILTER) { > > - SpiceRect* rect; > > - int size; > > - > > - rect = &drawable->red_drawable->u.copy.src_area; > > - size = (rect->right - rect->left) * (rect->bottom - rect->top); > > - if (size < RED_STREAM_MIN_SIZE) { > > - return; > > - } > > - } > > - > > - drawable->streamable = TRUE; > > -} > > - > > -void print_stats(DisplayChannel *display) > > -{ > > -#ifdef RED_WORKER_STAT > > - stat_time_t total = display->add_stat.total; > > - spice_info("add with shadow count %u", > > - display->add_with_shadow_count); > > - display->add_with_shadow_count = 0; > > - spice_info("add[%u] %f exclude[%u] %f __exclude[%u] %f", > > - display->add_stat.count, > > - stat_cpu_time_to_sec(total), > > - display->exclude_stat.count, > > - stat_cpu_time_to_sec(display->exclude_stat.total), > > - display->__exclude_stat.count, > > - stat_cpu_time_to_sec(display->__exclude_stat.total)); > > - spice_info("add %f%% exclude %f%% exclude2 %f%% __exclude %f%%", > > - (double)(total - display->exclude_stat.total) / total * > > 100, > > - (double)(display->exclude_stat.total) / total * 100, > > - (double)(display->exclude_stat.total - > > - display->__exclude_stat.total) / display > > ->exclude_stat.total * 100, > > - (double)(display->__exclude_stat.total) / display > > ->exclude_stat.total * 100); > > - stat_reset(&display->add_stat); > > - stat_reset(&display->exclude_stat); > > - stat_reset(&display->__exclude_stat); > > -#endif > > -} > > - > > - static int red_add_drawable(DisplayChannel *display, Drawable *drawable) > > -{ > > - int ret = FALSE, surface_id = drawable->surface_id; > > - RedDrawable *red_drawable = drawable->red_drawable; > > - Ring *ring = &display->surfaces[surface_id].current; > > - > > - if (has_shadow(red_drawable)) { > > - ret = current_add_with_shadow(display, ring, drawable); > > - } else { > > - drawable_update_streamable(display, drawable); > > - ret = current_add(display, ring, drawable); > > - } > > - > > -#ifdef RED_WORKER_STAT > > - if ((++display->add_count % 100) == 0) > > - print_stats(display); > > -#endif > > - return ret; > > -} > > - > > static void red_get_area(DisplayChannel *display, int surface_id, const > > SpiceRect *area, > > uint8_t *dest, int dest_stride, int update) > > { > > @@ -2193,7 +1660,7 @@ static inline void red_process_draw(RedWorker > > *worker, > > RedDrawable *red_drawable > > goto cleanup; > > } > > > > - if (red_add_drawable(worker->display_channel, drawable)) { > > + if (display_channel_add_drawable(worker->display_channel, drawable)) { > > red_pipes_add_drawable(worker->display_channel, drawable); > > } > > cleanup: Frediano _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel