I'd like to split this one. Will send a new patch series. On Tue, 2015-11-10 at 14:16 +0000, Frediano Ziglio wrote: > From: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> > > Ok. this one was painful.Note that in some cases, DCC_TO_DC should be > made safer (there used to be a if !dcc guard in some places, although > that looks wrong anyway)... > --- > server/display-channel.c | 79 +++ > server/display-channel.h | 145 ++++- > server/red_worker.c | 1324 +++++++++++++++++---------------------------- > - > server/red_worker.h | 2 + > server/stream.c | 70 +++ > server/stream.h | 12 +- > server/tree.h | 6 + > 7 files changed, 794 insertions(+), 844 deletions(-) > > diff --git a/server/display-channel.c b/server/display-channel.c > index b5d8830..5f422c9 100644 > --- a/server/display-channel.c > +++ b/server/display-channel.c > @@ -305,3 +305,82 @@ void display_channel_set_stream_video(DisplayChannel > *display, int stream_video) > > display->stream_video = stream_video; > } > + > +static void stop_streams(DisplayChannel *display) > +{ > + Ring *ring = &display->streams; > + RingItem *item = ring_get_head(ring); > + > + while (item) { > + Stream *stream = SPICE_CONTAINEROF(item, Stream, link); > + item = ring_next(ring, item); > + if (!stream->current) { > + stream_stop(display, stream); > + } else { > + spice_info("attached stream"); > + } > + } > + > + display->next_item_trace = 0; > + memset(display->items_trace, 0, sizeof(display->items_trace)); > +} > + > +void display_channel_surface_unref(DisplayChannel *display, uint32_t > surface_id) > +{ > + RedSurface *surface = &display->surfaces[surface_id]; > + RedWorker *worker = COMMON_CHANNEL(display)->worker; > + QXLInstance *qxl = red_worker_get_qxl(worker); > + DisplayChannelClient *dcc; > + RingItem *link, *next; > + > + if (--surface->refs != 0) { > + return; > + } > + > + // only primary surface streams are supported > + if (is_primary_surface(display, surface_id)) { > + stop_streams(display); > + } > + spice_assert(surface->context.canvas); > + > + surface->context.canvas->ops->destroy(surface->context.canvas); > + if (surface->create.info) { > + qxl->st->qif->release_resource(qxl, surface->create); > + } > + if (surface->destroy.info) { > + qxl->st->qif->release_resource(qxl, surface->destroy); > + } > + > + region_destroy(&surface->draw_dirty_region); > + surface->context.canvas = NULL; > + FOREACH_DCC(display, link, next, dcc) { > + dcc_push_destroy_surface(dcc, surface_id); > + } > + > + spice_warn_if(!ring_is_empty(&surface->depend_on_me)); > +} > + > +void display_channel_show_tree(DisplayChannel *display) > +{ > + int x; > + > + for (x = 0; x < NUM_SURFACES; ++x) { > + if (!display->surfaces[x].context.canvas) > + continue; > + > + RingItem *it; > + Ring *ring = &display->surfaces[x].current; > + RING_FOREACH(it, ring) { > + TreeItem *now = SPICE_CONTAINEROF(it, TreeItem, siblings_link); > + tree_item_dump(now); > + } > + > + } > +} > + > +/* TODO: perhaps rename to "ready" or "realized" ? */ > +bool display_channel_surface_has_canvas(DisplayChannel *display, > + uint32_t surface_id) > +{ > + return display->surfaces[surface_id].context.canvas != NULL; > +} > diff --git a/server/display-channel.h b/server/display-channel.h > index 1566c21..c7709ad 100644 > --- a/server/display-channel.h > +++ b/server/display-channel.h > @@ -20,6 +20,7 @@ > > #include <setjmp.h> > > +#include "common/rect.h" > #include "red_worker.h" > #include "reds_stream.h" > #include "cache-item.h" > @@ -56,8 +57,6 @@ > #include "tree.h" > #include "stream.h" > > -typedef struct DisplayChannel DisplayChannel; > - > #define PALETTE_CACHE_HASH_SHIFT 8 > #define PALETTE_CACHE_HASH_SIZE (1 << PALETTE_CACHE_HASH_SHIFT) > #define PALETTE_CACHE_HASH_MASK (PALETTE_CACHE_HASH_SIZE - 1) > @@ -205,8 +204,8 @@ struct DisplayChannelClient { > > #define DCC_TO_WORKER(dcc) \ > (SPICE_CONTAINEROF((dcc)->common.base.channel, CommonChannel, base) > ->worker) > -#define DCC_TO_DC(dcc) SPICE_CONTAINEROF((dcc)->common.base.channel, \ > - DisplayChannel, common.base) > +#define DCC_TO_DC(dcc) \ > + SPICE_CONTAINEROF((dcc)->common.base.channel, DisplayChannel, > common.base) > #define RCC_TO_DCC(rcc) SPICE_CONTAINEROF((rcc), DisplayChannelClient, > common.base) > > > @@ -273,6 +272,30 @@ void monitors_config_unref > (MonitorsCo > #define NUM_TRACE_ITEMS (1 << TRACE_ITEMS_SHIFT) > #define ITEMS_TRACE_MASK (NUM_TRACE_ITEMS - 1) > > +typedef struct DrawContext { > + SpiceCanvas *canvas; > + int canvas_draws_on_surface; > + int top_down; > + uint32_t width; > + uint32_t height; > + int32_t stride; > + uint32_t format; > + void *line_0; > +} DrawContext; > + > +typedef struct RedSurface { > + uint32_t refs; > + Ring current; > + Ring current_list; > + DrawContext context; > + > + Ring depend_on_me; > + QRegion draw_dirty_region; > + > + //fix me - better handling here If this comment is needed, it should use the standard "FIXME" format so we can find it with a grep. > + QXLReleaseInfoExt create, destroy; > +} RedSurface; > + > #define NUM_DRAWABLES 1000 > typedef struct _Drawable _Drawable; > struct _Drawable { > @@ -311,6 +334,10 @@ struct DisplayChannel { > uint32_t next_item_trace; > uint64_t streams_size_total; > > + RedSurface surfaces[NUM_SURFACES]; > + uint32_t n_surfaces; > + SpiceImageSurfaces image_surfaces; > + > ImageCache image_cache; > RedCompressBuf *free_compress_bufs; > > @@ -329,6 +356,21 @@ struct DisplayChannel { > stat_info_t lz4_stat; > #endif > }; > + > +#define LINK_TO_DCC(ptr) SPICE_CONTAINEROF(ptr, DisplayChannelClient, \ > + common.base.channel_link) > +#define DCC_FOREACH_SAFE(link, next, dcc, channel) \ > + SAFE_FOREACH(link, next, channel, &(channel)->clients, dcc, > LINK_TO_DCC(link)) > + > + > +#define FOREACH_DCC(display_channel, link, next, dcc) \ > + DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display_channel)) > + > +static inline int get_stream_id(DisplayChannel *display, Stream *stream) > +{ > + return (int)(stream - display->streams_buf); > +} > + > typedef struct SurfaceDestroyItem { > SpiceMsgSurfaceDestroy surface_destroy; > PipeItem pipe_item; > @@ -356,7 +398,100 @@ int > display_channel_get_streams_timeout (DisplayCha > void display_channel_compress_stats_print (const > DisplayChannel *display); > void display_channel_compress_stats_reset > (DisplayChannel *display); > void display_channel_drawable_unref > (DisplayChannel *display, Drawable *drawable); > - > +void display_channel_surface_unref > (DisplayChannel *display, > + > uint32_t surface_id); > +bool display_channel_surface_has_canvas > (DisplayChannel *display, > + > uint32_t surface_id); > +void display_channel_show_tree > (DisplayChannel *display); > + > +static inline int is_equal_path(SpicePath *path1, SpicePath *path2) > +{ > + SpicePathSeg *seg1, *seg2; > + int i, j; > + > + if (path1->num_segments != path2->num_segments) > + return FALSE; > + > + for (i = 0; i < path1->num_segments; i++) { > + seg1 = path1->segments[i]; > + seg2 = path2->segments[i]; > + > + if (seg1->flags != seg2->flags || > + seg1->count != seg2->count) { > + return FALSE; > + } > + for (j = 0; j < seg1->count; j++) { > + if (seg1->points[j].x != seg2->points[j].x || > + seg1->points[j].y != seg2->points[j].y) { > + return FALSE; > + } > + } > + } > + > + return TRUE; > +} > + > +// partial imp > +static inline int is_equal_brush(SpiceBrush *b1, SpiceBrush *b2) > +{ > + return b1->type == b2->type && > + b1->type == SPICE_BRUSH_TYPE_SOLID && > + b1->u.color == b2->u.color; > +} > + > +// partial imp > +static inline int is_equal_line_attr(SpiceLineAttr *a1, SpiceLineAttr *a2) > +{ > + return a1->flags == a2->flags && > + a1->style_nseg == a2->style_nseg && > + a1->style_nseg == 0; > +} > + > +// partial imp > +static inline int is_same_geometry(Drawable *d1, Drawable *d2) > +{ > + if (d1->red_drawable->type != d2->red_drawable->type) { > + return FALSE; > + } > + > + switch (d1->red_drawable->type) { > + case QXL_DRAW_STROKE: > + return is_equal_line_attr(&d1->red_drawable->u.stroke.attr, > + &d2->red_drawable->u.stroke.attr) && > + is_equal_path(d1->red_drawable->u.stroke.path, > + d2->red_drawable->u.stroke.path); > + case QXL_DRAW_FILL: > + return rect_is_equal(&d1->red_drawable->bbox, &d2->red_drawable > ->bbox); > + default: > + return FALSE; > + } > +} > + > +static inline int is_same_drawable(Drawable *d1, Drawable *d2) > +{ > + if (!is_same_geometry(d1, d2)) { > + return FALSE; > + } > + > + switch (d1->red_drawable->type) { > + case QXL_DRAW_STROKE: > + return is_equal_brush(&d1->red_drawable->u.stroke.brush, > + &d2->red_drawable->u.stroke.brush); > + case QXL_DRAW_FILL: > + return is_equal_brush(&d1->red_drawable->u.fill.brush, > + &d2->red_drawable->u.fill.brush); > + default: > + return FALSE; > + } > +} > + > +static inline int is_primary_surface(DisplayChannel *display, uint32_t > surface_id) > +{ > + if (surface_id == 0) { > + return TRUE; > + } > + return FALSE; > +} > > > #endif /* DISPLAY_CHANNEL_H_ */ > diff --git a/server/red_worker.c b/server/red_worker.c > index 23c54e8..2360866 100644 > --- a/server/red_worker.c > +++ b/server/red_worker.c > @@ -75,7 +75,6 @@ > #define CMD_RING_POLL_RETRIES 200 > > #define DISPLAY_CLIENT_SHORT_TIMEOUT 15000000000ULL //nano > -#define DISPLAY_CLIENT_TIMEOUT 30000000000ULL //nano > #define DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT 10000000000ULL //nano, 10 sec > #define DISPLAY_CLIENT_RETRY_INTERVAL 10000 //micro > > @@ -112,6 +111,8 @@ static void rendering_incorrect(const char *msg) > > typedef unsigned long stat_time_t; > > +static stat_time_t stat_now(RedWorker *worker); > + > #if defined(RED_WORKER_STAT) || defined(COMPRESS_STAT) > double stat_cpu_time_to_sec(stat_time_t time) > { > @@ -300,30 +301,6 @@ struct RedGlzDrawable { > pthread_mutex_t glz_dictionary_list_lock = PTHREAD_MUTEX_INITIALIZER; > Ring glz_dictionary_list = {&glz_dictionary_list, &glz_dictionary_list}; > > -typedef struct DrawContext { > - SpiceCanvas *canvas; > - int canvas_draws_on_surface; > - int top_down; > - uint32_t width; > - uint32_t height; > - int32_t stride; > - uint32_t format; > - void *line_0; > -} DrawContext; > - > -typedef struct RedSurface { > - uint32_t refs; > - Ring current; > - Ring current_list; > - DrawContext context; > - > - Ring depend_on_me; > - QRegion draw_dirty_region; > - > - //fix me - better handling here > - QXLReleaseInfoExt create, destroy; > -} RedSurface; > - > typedef struct RedWorker { > pthread_t thread; > clockid_t clockid; > @@ -340,10 +317,6 @@ typedef struct RedWorker { > CursorChannel *cursor_channel; > uint32_t cursor_poll_tries; > > - RedSurface surfaces[NUM_SURFACES]; > - uint32_t n_surfaces; > - SpiceImageSurfaces image_surfaces; > - > uint32_t red_drawable_count; > uint32_t glz_drawable_count; > uint32_t bits_unique; > @@ -404,7 +377,7 @@ typedef struct BitmapData { > SpiceRect lossy_rect; > } BitmapData; > > -static inline int validate_surface(RedWorker *worker, uint32_t surface_id); > +static inline int validate_surface(DisplayChannel *display, uint32_t > surface_id); > > static stat_time_t stat_now(RedWorker *worker) > { > @@ -415,11 +388,11 @@ static stat_time_t stat_now(RedWorker *worker) > return ts.tv_nsec + ts.tv_sec * 1000 * 1000 * 1000; > } > > -static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable); > -static void red_current_flush(RedWorker *worker, int surface_id); > -static void red_draw_drawable(RedWorker *worker, Drawable *item); > -static void red_update_area(RedWorker *worker, const SpiceRect *area, int > surface_id); > -static void red_update_area_till(RedWorker *worker, const SpiceRect *area, > int surface_id, > +static void red_draw_qxl_drawable(DisplayChannel *display, Drawable > *drawable); > +static void red_current_flush(DisplayChannel *display, int surface_id); > +static void red_draw_drawable(DisplayChannel *display, Drawable *item); > +static void red_update_area(DisplayChannel *display, const SpiceRect *area, > int surface_id); > +static void red_update_area_till(DisplayChannel *display, const SpiceRect > *area, int surface_id, > Drawable *last); > static void detach_stream(DisplayChannel *display, Stream *stream, int > detach_sized); > static inline void display_channel_stream_maintenance(DisplayChannel > *display, Drawable *candidate, Drawable *sect); > @@ -436,22 +409,9 @@ static void > display_channel_client_release_item_before_push(DisplayChannelClient > PipeItem *item); > static void > display_channel_client_release_item_after_push(DisplayChannelClient *dcc, > PipeItem *item); > - > -/* > - * Macros to make iterating over stuff easier > - * The two collections we iterate over: > - * given a channel, iterate over it's clients > - */ > - > -#define LINK_TO_DCC(ptr) SPICE_CONTAINEROF(ptr, DisplayChannelClient, \ > - common.base.channel_link) > -#define DCC_FOREACH_SAFE(link, next, dcc, channel) \ > - SAFE_FOREACH(link, next, channel, &(channel)->clients, dcc, > LINK_TO_DCC(link)) > - > - > -#define FOREACH_DCC(display_channel, link, next, dcc) \ > - DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display_channel)) > - > +static void red_create_surface(DisplayChannel *display, uint32_t surface_id, > uint32_t width, > + uint32_t height, int32_t stride, uint32_t > format, > + void *line_0, int data_is_valid, int > send_client); > > #define LINK_TO_DPI(ptr) SPICE_CONTAINEROF((ptr), DrawablePipeItem, base) > #define DRAWABLE_FOREACH_DPI_SAFE(drawable, link, next, dpi) \ > @@ -464,38 +424,12 @@ static void > display_channel_client_release_item_after_push(DisplayChannelClient > SAFE_FOREACH(link, next, drawable, &(drawable)->glz_ring, glz, > LINK_TO_GLZ(link)) > > > -static int get_stream_id(DisplayChannel *display, Stream *stream) > -{ > - return (int)(stream - display->streams_buf); > -} > - > -static void display_stream_free(DisplayChannel *display, Stream *stream) > -{ > - stream->next = display->free_streams; > - display->free_streams = stream; > -} > - > -static void display_stream_unref(DisplayChannel *display, Stream *stream) > -{ > - if (--stream->refs != 0) > - return; > - > - spice_warn_if_fail(!ring_item_is_linked(&stream->link)); > - display_stream_free(display, stream); > - display->stream_count--; > -} > - > -static void display_stream_agent_unref(DisplayChannel *display, StreamAgent > *agent) > -{ > - display_stream_unref(display, agent->stream); > -} > - > static void display_stream_clip_unref(DisplayChannel *display, StreamClipItem > *item) > { > if (--item->refs != 0) > return; > > - display_stream_agent_unref(display, item->stream_agent); > + stream_agent_unref(display, item->stream_agent); > free(item->rects); > free(item); > } > @@ -560,40 +494,6 @@ void attach_stream(DisplayChannel *display, Drawable > *drawable, Stream *stream) > } > } > > -static void stop_stream(DisplayChannel *display, Stream *stream) > -{ > - DisplayChannelClient *dcc; > - RingItem *item, *next; > - > - spice_assert(ring_item_is_linked(&stream->link)); > - spice_assert(!stream->current); > - spice_debug("stream %d", get_stream_id(display, stream)); > - FOREACH_DCC(display, item, next, dcc) { > - StreamAgent *stream_agent; > - > - stream_agent = &dcc->stream_agents[get_stream_id(display, stream)]; > - region_clear(&stream_agent->vis_region); > - region_clear(&stream_agent->clip); > - spice_assert(!pipe_item_is_linked(&stream_agent->destroy_item)); > - if (stream_agent->mjpeg_encoder && dcc > ->use_mjpeg_encoder_rate_control) { > - uint64_t stream_bit_rate = > mjpeg_encoder_get_bit_rate(stream_agent->mjpeg_encoder); > - > - if (stream_bit_rate > dcc->streams_max_bit_rate) { > - spice_debug("old max-bit-rate=%.2f new=%.2f", > - dcc->streams_max_bit_rate / 8.0 / 1024.0 / 1024.0, > - stream_bit_rate / 8.0 / 1024.0 / 1024.0); > - dcc->streams_max_bit_rate = stream_bit_rate; > - } > - } > - stream->refs++; > - red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &stream_agent > ->destroy_item); > - stream_agent_stats_print(stream_agent); > - } > - display->streams_size_total -= stream->width * stream->height; > - ring_remove(&stream->link); > - display_stream_unref(display, stream); > -} > - > /* fixme: move to display channel */ > DrawablePipeItem *drawable_pipe_item_new(DisplayChannelClient *dcc, > Drawable *drawable) > @@ -639,14 +539,6 @@ QXLInstance* red_worker_get_qxl(RedWorker *worker) > return worker->qxl; > } > > -static inline int is_primary_surface(DisplayChannel *display, uint32_t > surface_id) > -{ > - if (surface_id == 0) { > - return TRUE; > - } > - return FALSE; > -} > - > static int validate_drawable_bbox(RedWorker *worker, RedDrawable *drawable) > { > DrawContext *context; > @@ -655,8 +547,8 @@ static int validate_drawable_bbox(RedWorker *worker, > RedDrawable *drawable) > /* surface_id must be validated before calling into > * validate_drawable_bbox > */ > - VALIDATE_SURFACE_RETVAL(worker, surface_id, FALSE); > - context = &worker->surfaces[surface_id].context; > + VALIDATE_SURFACE_RETVAL(worker->display_channel, surface_id, FALSE); > + context = &worker->display_channel->surfaces[surface_id].context; > > if (drawable->bbox.top < 0) > return FALSE; > @@ -674,15 +566,15 @@ static int validate_drawable_bbox(RedWorker *worker, > RedDrawable *drawable) > return TRUE; > } > > -static inline int validate_surface(RedWorker *worker, uint32_t surface_id) > +static inline int validate_surface(DisplayChannel *display, uint32_t > surface_id) > { > - if SPICE_UNLIKELY(surface_id >= worker->n_surfaces) { > + if SPICE_UNLIKELY(surface_id >= display->n_surfaces) { > spice_warning("invalid surface_id %u", surface_id); > return 0; > } > - if (!worker->surfaces[surface_id].context.canvas) { > + if (!display->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); > + &(display->surfaces[surface_id].context.canvas), > surface_id); > spice_warning("failed on %d", surface_id); > return 0; > } > @@ -695,7 +587,7 @@ static void red_push_surface_image(DisplayChannelClient > *dcc, int surface_id); > static inline void red_handle_drawable_surfaces_client_synced( > DisplayChannelClient *dcc, Drawable *drawable) > { > - RedWorker *worker = DCC_TO_WORKER(dcc); > + DisplayChannel *display = DCC_TO_DC(dcc); > int x; > > for (x = 0; x < 3; ++x) { > @@ -707,7 +599,7 @@ static inline void > red_handle_drawable_surfaces_client_synced( > continue; > } > red_create_surface_item(dcc, surface_id); > - red_current_flush(worker, surface_id); > + red_current_flush(display, surface_id); > red_push_surface_image(dcc, surface_id); > } > } > @@ -717,7 +609,7 @@ static inline void > red_handle_drawable_surfaces_client_synced( > } > > red_create_surface_item(dcc, drawable->surface_id); > - red_current_flush(worker, drawable->surface_id); > + red_current_flush(display, drawable->surface_id); > red_push_surface_image(dcc, drawable->surface_id); > } > > @@ -742,13 +634,13 @@ 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(RedWorker *worker, Drawable *drawable) > +static void red_pipes_add_drawable(DisplayChannel *display, Drawable > *drawable) > { > DisplayChannelClient *dcc; > RingItem *dcc_ring_item, *next; > > spice_warn_if(!ring_is_empty(&drawable->pipes)); > - FOREACH_DCC(worker->display_channel, dcc_ring_item, next, dcc) { > + FOREACH_DCC(display, dcc_ring_item, next, dcc) { > dcc_add_drawable(dcc, drawable); > } > } > @@ -765,7 +657,7 @@ 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(RedWorker *worker, > +static inline void red_pipes_add_drawable_after(DisplayChannel *display, > Drawable *drawable, Drawable > *pos_after) > { > DrawablePipeItem *dpi, *dpi_pos_after; > @@ -782,13 +674,13 @@ static inline void > red_pipes_add_drawable_after(RedWorker *worker, > &dpi_pos_after->dpi_pipe_item); > } > if (num_other_linked == 0) { > - red_pipes_add_drawable(worker, drawable); > + red_pipes_add_drawable(display, drawable); > return; > } > - if (num_other_linked != worker->display_channel->common.base.clients_num) > { > - RingItem *worker_item, *next; > + if (num_other_linked != display->common.base.clients_num) { > + RingItem *item, *next; > spice_debug("TODO: not O(n^2)"); > - FOREACH_DCC(worker->display_channel, worker_item, next, dcc) { > + FOREACH_DCC(display, item, next, dcc) { > int sent = 0; > DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next, > dpi_pos_after) { > if (dpi_pos_after->dcc == dcc) { > @@ -812,8 +704,6 @@ static inline PipeItem > *red_pipe_get_tail(DisplayChannelClient *dcc) > return (PipeItem*)ring_get_tail(&RED_CHANNEL_CLIENT(dcc)->pipe); > } > > -static void red_surface_unref(RedWorker *worker, uint32_t surface_id); > - > static inline void red_pipes_remove_drawable(Drawable *drawable) > { > DrawablePipeItem *dpi; > @@ -928,59 +818,6 @@ static void drawables_init(DisplayChannel *display) > } > > > -static void stop_streams(DisplayChannel *display) > -{ > - Ring *ring = &display->streams; > - RingItem *item = ring_get_head(ring); > - > - while (item) { > - Stream *stream = SPICE_CONTAINEROF(item, Stream, link); > - item = ring_next(ring, item); > - if (!stream->current) { > - stop_stream(display, stream); > - } else { > - spice_info("attached stream"); > - } > - } > - > - display->next_item_trace = 0; > - memset(display->items_trace, 0, sizeof(display->items_trace)); > -} > - > -static void red_surface_unref(RedWorker *worker, uint32_t surface_id) > -{ > - DisplayChannel *display = worker->display_channel; > - RedSurface *surface = &worker->surfaces[surface_id]; > - DisplayChannelClient *dcc; > - RingItem *link, *next; > - > - if (--surface->refs != 0) { > - return; > - } > - > - // only primary surface streams are supported > - if (is_primary_surface(worker->display_channel, surface_id)) { > - stop_streams(display); > - } > - spice_assert(surface->context.canvas); > - > - surface->context.canvas->ops->destroy(surface->context.canvas); > - if (surface->create.info) { > - worker->qxl->st->qif->release_resource(worker->qxl, surface->create); > - } > - if (surface->destroy.info) { > - worker->qxl->st->qif->release_resource(worker->qxl, surface > ->destroy); > - } > - > - region_destroy(&surface->draw_dirty_region); > - surface->context.canvas = NULL; > - FOREACH_DCC(worker->display_channel, link, next, dcc) { > - dcc_push_destroy_surface(dcc, surface_id); > - } > - > - spice_warn_if(!ring_is_empty(&surface->depend_on_me)); > -} > - > static inline void set_surface_release_info(QXLReleaseInfoExt > *release_info_ext, > QXLReleaseInfo *release_info, > uint32_t group_id) > { > @@ -1029,7 +866,7 @@ static void drawable_unref_surface_deps(DisplayChannel > *display, Drawable *drawa > if (surface_id == -1) { > continue; > } > - red_surface_unref(COMMON_CHANNEL(display)->worker, surface_id); > + display_channel_surface_unref(display, surface_id); > } > } > > @@ -1063,7 +900,7 @@ void display_channel_drawable_unref(DisplayChannel > *display, Drawable *drawable) > > drawable_remove_dependencies(display, drawable); > drawable_unref_surface_deps(display, drawable); > - red_surface_unref(COMMON_CHANNEL(display)->worker, drawable->surface_id); > + display_channel_surface_unref(display, drawable->surface_id); > > RING_FOREACH_SAFE(item, next, &drawable->glz_ring) { > SPICE_CONTAINEROF(item, RedGlzDrawable, drawable_link)->drawable = > NULL; > @@ -1089,7 +926,7 @@ static inline void remove_shadow(DrawItem *item) > free(shadow); > } > > -static inline void current_remove_container(RedWorker *worker, Container > *container) > +static inline void current_remove_container(DisplayChannel *display, > Container *container) > { > spice_assert(ring_is_empty(&container->items)); > ring_remove(&container->base.siblings_link); > @@ -1097,7 +934,7 @@ static inline void current_remove_container(RedWorker > *worker, Container *contai > free(container); > } > > -static inline void container_cleanup(RedWorker *worker, Container *container) > +static inline void container_cleanup(DisplayChannel *display, Container > *container) > { > while (container && container->items.next == container->items.prev) { > Container *next = container->base.container; > @@ -1108,7 +945,7 @@ static inline void container_cleanup(RedWorker *worker, > Container *container) > ring_add_after(&item->siblings_link, &container > ->base.siblings_link); > item->container = container->base.container; > } > - current_remove_container(worker, container); > + current_remove_container(display, container); > container = next; > } > } > @@ -1132,12 +969,12 @@ static void > display_stream_trace_add_drawable(DisplayChannel *display, Drawable > trace->dest_area = item->red_drawable->bbox; > } > > -static void surface_flush(RedWorker *worker, int surface_id, SpiceRect *rect) > +static void surface_flush(DisplayChannel *display, int surface_id, SpiceRect > *rect) > { > - red_update_area(worker, rect, surface_id); > + red_update_area(display, rect, surface_id); > } > > -static void red_flush_source_surfaces(RedWorker *worker, Drawable *drawable) > +static void red_flush_source_surfaces(DisplayChannel *display, Drawable > *drawable) > { > int x; > int surface_id; > @@ -1146,15 +983,13 @@ static void red_flush_source_surfaces(RedWorker > *worker, Drawable *drawable) > surface_id = drawable->surface_deps[x]; > if (surface_id != -1 && drawable->depend_items[x].drawable) { > remove_depended_item(&drawable->depend_items[x]); > - surface_flush(worker, surface_id, &drawable->red_drawable > ->surfaces_rects[x]); > + surface_flush(display, surface_id, &drawable->red_drawable > ->surfaces_rects[x]); > } > } > } > > -static inline void current_remove_drawable(RedWorker *worker, Drawable *item) > +static inline void current_remove_drawable(DisplayChannel *display, Drawable > *item) > { > - DisplayChannel *display = worker->display_channel; > - > display_stream_trace_add_drawable(display, item); > remove_shadow(&item->tree_item); > ring_remove(&item->tree_item.base.siblings_link); > @@ -1164,23 +999,24 @@ static inline void current_remove_drawable(RedWorker > *worker, Drawable *item) > display->current_size--; > } > > -static void remove_drawable(RedWorker *worker, Drawable *drawable) > +static void remove_drawable(DisplayChannel *display, Drawable *drawable) > { > red_pipes_remove_drawable(drawable); > - current_remove_drawable(worker, drawable); > + current_remove_drawable(display, drawable); > } > > -static inline void current_remove(RedWorker *worker, TreeItem *item) > +static inline void current_remove(DisplayChannel *display, TreeItem *item) > { > TreeItem *now = item; > > + /* depth-first tree traversal, todo: do a to tree_foreach()? */ > for (;;) { > Container *container = now->container; > RingItem *ring_item; > > if (now->type == TREE_ITEM_TYPE_DRAWABLE) { > ring_item = now->siblings_link.prev; > - remove_drawable(worker, SPICE_CONTAINEROF(now, Drawable, > tree_item)); > + remove_drawable(display, SPICE_CONTAINEROF(now, Drawable, > tree_item)); > } else { > Container *container = (Container *)now; > > @@ -1191,7 +1027,7 @@ static inline void current_remove(RedWorker *worker, > TreeItem *item) > continue; > } > ring_item = now->siblings_link.prev; > - current_remove_container(worker, container); > + current_remove_container(display, container); > } > if (now == item) { > return; > @@ -1205,13 +1041,14 @@ static inline void current_remove(RedWorker *worker, > TreeItem *item) > } > } > > -static void red_current_clear(RedWorker *worker, int surface_id) > +static void current_clear(DisplayChannel *display, int surface_id) > { > + Ring *ring = &display->surfaces[surface_id].current; > RingItem *ring_item; > > - while ((ring_item = ring_get_head(&worker > ->surfaces[surface_id].current))) { > + while ((ring_item = ring_get_head(ring))) { > TreeItem *now = SPICE_CONTAINEROF(ring_item, TreeItem, > siblings_link); > - current_remove(worker, now); > + current_remove(display, now); > } > } > > @@ -1296,14 +1133,14 @@ static int > red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int > return TRUE; > } > > -static void red_clear_surface_drawables_from_pipes(RedWorker *worker, > +static void red_clear_surface_drawables_from_pipes(DisplayChannel *display, > int surface_id, > int wait_if_used) > { > RingItem *item, *next; > DisplayChannelClient *dcc; > > - FOREACH_DCC(worker->display_channel, item, next, dcc) { > + FOREACH_DCC(display, item, next, dcc) { > if (!red_clear_surface_drawables_from_pipe(dcc, surface_id, > wait_if_used)) { > red_channel_client_disconnect(RED_CHANNEL_CLIENT(dcc)); > } > @@ -1343,8 +1180,8 @@ static inline int __contained_by(TreeItem *item, Ring > *ring) > return FALSE; > } > > -static inline void __exclude_region(RedWorker *worker, Ring *ring, TreeItem > *item, QRegion *rgn, > - Ring **top_ring, Drawable > *frame_candidate) > +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 > @@ -1383,7 +1220,7 @@ static inline void __exclude_region(RedWorker *worker, > Ring *ring, TreeItem *ite > } else { > if (frame_candidate) { > Drawable *drawable = SPICE_CONTAINEROF(draw, Drawable, > tree_item); > - display_channel_stream_maintenance(worker > ->display_channel, frame_candidate, drawable); > + display_channel_stream_maintenance(display, > frame_candidate, drawable); > } > region_exclude(&draw->base.rgn, &and_rgn); > } > @@ -1414,8 +1251,8 @@ static inline void __exclude_region(RedWorker *worker, > Ring *ring, TreeItem *ite > stat_add(&worker->__exclude_stat, start_time); > } > > -static void exclude_region(RedWorker *worker, Ring *ring, RingItem > *ring_item, QRegion *rgn, > - TreeItem **last, Drawable *frame_candidate) > +static void exclude_region(DisplayChannel *display, Ring *ring, RingItem > *ring_item, > + QRegion *rgn, TreeItem **last, Drawable > *frame_candidate) > { > #ifdef RED_WORKER_STAT > stat_time_t start_time = stat_now(worker); > @@ -1435,12 +1272,12 @@ static void exclude_region(RedWorker *worker, Ring > *ring, RingItem *ring_item, Q > spice_assert(!region_is_empty(&now->rgn)); > > if (region_intersects(rgn, &now->rgn)) { > - __exclude_region(worker, ring, now, rgn, &top_ring, > frame_candidate); > + __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(worker, now); > + current_remove(display, now); > if (last && *last == now) { > *last = (TreeItem *)ring_next(ring, ring_item); > } > @@ -1473,19 +1310,13 @@ static void exclude_region(RedWorker *worker, Ring > *ring, RingItem *ring_item, Q > } > } > > -static inline int is_opaque_item(TreeItem *item) > +static void __current_add_drawable(DisplayChannel *display, > + Drawable *drawable, RingItem *pos) > { > - return item->type == TREE_ITEM_TYPE_CONTAINER || > - (IS_DRAW_ITEM(item) && ((DrawItem *)item)->effect == > QXL_EFFECT_OPAQUE); > -} > - > -static inline void __current_add_drawable(RedWorker *worker, Drawable > *drawable, RingItem *pos) > -{ > - DisplayChannel *display = worker->display_channel; > RedSurface *surface; > uint32_t surface_id = drawable->surface_id; > > - surface = &worker->surfaces[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); > @@ -1493,87 +1324,6 @@ static inline void __current_add_drawable(RedWorker > *worker, Drawable *drawable, > drawable->refs++; > } > > -static int is_equal_path(RedWorker *worker, SpicePath *path1, SpicePath > *path2) > -{ > - SpicePathSeg *seg1, *seg2; > - int i, j; > - > - if (path1->num_segments != path2->num_segments) > - return FALSE; > - > - for (i = 0; i < path1->num_segments; i++) { > - seg1 = path1->segments[i]; > - seg2 = path2->segments[i]; > - > - if (seg1->flags != seg2->flags || > - seg1->count != seg2->count) { > - return FALSE; > - } > - for (j = 0; j < seg1->count; j++) { > - if (seg1->points[j].x != seg2->points[j].x || > - seg1->points[j].y != seg2->points[j].y) { > - return FALSE; > - } > - } > - } > - > - return TRUE; > -} > - > -// partial imp > -static int is_equal_brush(SpiceBrush *b1, SpiceBrush *b2) > -{ > - return b1->type == b2->type && > - b1->type == SPICE_BRUSH_TYPE_SOLID && > - b1->u.color == b2->u.color; > -} > - > -// partial imp > -static int is_equal_line_attr(SpiceLineAttr *a1, SpiceLineAttr *a2) > -{ > - return a1->flags == a2->flags && > - a1->style_nseg == a2->style_nseg && > - a1->style_nseg == 0; > -} > - > -// partial imp > -static int is_same_geometry(RedWorker *worker, Drawable *d1, Drawable *d2) > -{ > - if (d1->red_drawable->type != d2->red_drawable->type) { > - return FALSE; > - } > - > - switch (d1->red_drawable->type) { > - case QXL_DRAW_STROKE: > - return is_equal_line_attr(&d1->red_drawable->u.stroke.attr, > - &d2->red_drawable->u.stroke.attr) && > - is_equal_path(worker, d1->red_drawable->u.stroke.path, > - d2->red_drawable->u.stroke.path); > - case QXL_DRAW_FILL: > - return rect_is_equal(&d1->red_drawable->bbox, &d2->red_drawable > ->bbox); > - default: > - return FALSE; > - } > -} > - > -static int is_same_drawable(RedWorker *worker, Drawable *d1, Drawable *d2) > -{ > - if (!is_same_geometry(worker, d1, d2)) { > - return FALSE; > - } > - > - switch (d1->red_drawable->type) { > - case QXL_DRAW_STROKE: > - return is_equal_brush(&d1->red_drawable->u.stroke.brush, > - &d2->red_drawable->u.stroke.brush); > - case QXL_DRAW_FILL: > - return is_equal_brush(&d1->red_drawable->u.fill.brush, > - &d2->red_drawable->u.fill.brush); > - default: > - return FALSE; > - } > -} > - > static void detach_stream(DisplayChannel *display, Stream *stream, > int detach_sized) > { > @@ -1662,9 +1412,9 @@ static void > dcc_detach_stream_gracefully(DisplayChannelClient *dcc, > stream_id, stream->current != NULL); > rect_debug(&upgrade_area); > if (update_area_limit) { > - red_update_area_till(DCC_TO_WORKER(dcc), &upgrade_area, 0, > update_area_limit); > + red_update_area_till(DCC_TO_DC(dcc), &upgrade_area, 0, > update_area_limit); > } else { > - red_update_area(DCC_TO_WORKER(dcc), &upgrade_area, 0); > + red_update_area(DCC_TO_DC(dcc), &upgrade_area, 0); > } > red_add_surface_area_image(dcc, 0, &upgrade_area, NULL, FALSE); > } > @@ -1781,7 +1531,7 @@ static void > display_channel_streams_timeout(DisplayChannel *display) > item = ring_next(ring, item); > if (now >= (stream->last_time + RED_STREAM_TIMEOUT)) { > detach_stream_gracefully(display, stream, NULL); > - stop_stream(display, stream); > + stream_stop(display, stream); > } > } > } > @@ -2320,9 +2070,8 @@ static inline int > is_drawable_independent_from_surfaces(Drawable *drawable) > return TRUE; > } > > -static inline int red_current_add_equal(RedWorker *worker, DrawItem *item, > TreeItem *other) > +static inline int red_current_add_equal(DisplayChannel *display, DrawItem > *item, TreeItem *other) > { > - DisplayChannel *display = worker->display_channel; > DrawItem *other_draw_item; > Drawable *drawable; > Drawable *other_drawable; > @@ -2342,14 +2091,14 @@ static inline int red_current_add_equal(RedWorker > *worker, DrawItem *item, TreeI > if (item->effect == QXL_EFFECT_OPAQUE) { > int add_after = !!other_drawable->stream && > is_drawable_independent_from_surfaces(drawable); > - display_channel_stream_maintenance(worker->display_channel, drawable, > other_drawable); > - __current_add_drawable(worker, drawable, &other->siblings_link); > + display_channel_stream_maintenance(display, drawable, > other_drawable); > + __current_add_drawable(display, drawable, &other->siblings_link); > other_drawable->refs++; > - current_remove_drawable(worker, other_drawable); > + current_remove_drawable(display, other_drawable); > if (add_after) { > - red_pipes_add_drawable_after(worker, drawable, other_drawable); > + red_pipes_add_drawable_after(display, drawable, other_drawable); > } else { > - red_pipes_add_drawable(worker, drawable); > + red_pipes_add_drawable(display, drawable); > } > red_pipes_remove_drawable(other_drawable); > display_channel_drawable_unref(display, other_drawable); > @@ -2358,18 +2107,18 @@ static inline int red_current_add_equal(RedWorker > *worker, DrawItem *item, TreeI > > switch (item->effect) { > case QXL_EFFECT_REVERT_ON_DUP: > - if (is_same_drawable(worker, drawable, other_drawable)) { > + if (is_same_drawable(drawable, other_drawable)) { > > DisplayChannelClient *dcc; > DrawablePipeItem *dpi; > RingItem *worker_ring_item, *dpi_ring_item; > > other_drawable->refs++; > - current_remove_drawable(worker, other_drawable); > + 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(worker > ->display_channel)->clients); > + 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) { > @@ -2378,7 +2127,7 @@ static inline int red_current_add_equal(RedWorker > *worker, DrawItem *item, TreeI > 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(worker > ->display_channel)->clients, > + worker_ring_item = ring_next(&RED_CHANNEL(display) > ->clients, > worker_ring_item); > dcc = SPICE_CONTAINEROF(worker_ring_item, > DisplayChannelClient, > common.base.channel_link); > @@ -2388,7 +2137,7 @@ static inline int red_current_add_equal(RedWorker > *worker, DrawItem *item, TreeI > dpi_ring_item = ring_next(&other_drawable->pipes, > dpi_ring_item); > } > if (worker_ring_item) { > - worker_ring_item = ring_next(&RED_CHANNEL(worker > ->display_channel)->clients, > + worker_ring_item = ring_next(&RED_CHANNEL(display) > ->clients, > worker_ring_item); > } > } > @@ -2400,15 +2149,15 @@ static inline int red_current_add_equal(RedWorker > *worker, DrawItem *item, TreeI > } > break; > case QXL_EFFECT_OPAQUE_BRUSH: > - if (is_same_geometry(worker, drawable, other_drawable)) { > - __current_add_drawable(worker, drawable, &other->siblings_link); > - remove_drawable(worker, other_drawable); > - red_pipes_add_drawable(worker, drawable); > + 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(worker, drawable, other_drawable)) { > + if (is_same_drawable(drawable, other_drawable)) { > return TRUE; > } > break; > @@ -2471,7 +2220,7 @@ static void red_use_stream_trace(DisplayChannel > *display, Drawable *drawable) > } > } > > -static inline int red_current_add(RedWorker *worker, Ring *ring, Drawable > *drawable) > +static inline int red_current_add(DisplayChannel *display, Ring *ring, > Drawable *drawable) > { > DrawItem *item = &drawable->tree_item; > #ifdef RED_WORKER_STAT > @@ -2500,7 +2249,7 @@ static inline int red_current_add(RedWorker *worker, > Ring *ring, Drawable *drawa > } 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(worker, item, sibling)) { > + > red_current_add_equal(display, item, sibling)) { > stat_add(&worker->add_stat, start_time); > return FALSE; > } > @@ -2512,7 +2261,7 @@ static inline int red_current_add(RedWorker *worker, > Ring *ring, Drawable *drawa > if ((shadow = __find_shadow(sibling))) { > if (exclude_base) { > TreeItem *next = sibling; > - exclude_region(worker, ring, exclude_base, > &exclude_rgn, &next, NULL); > + exclude_region(display, ring, exclude_base, > &exclude_rgn, &next, NULL); > if (next != sibling) { > now = next ? &next->siblings_link : NULL; > exclude_base = NULL; > @@ -2522,7 +2271,7 @@ static inline int red_current_add(RedWorker *worker, > Ring *ring, Drawable *drawa > region_or(&exclude_rgn, &shadow->on_hold); > } > now = now->prev; > - current_remove(worker, sibling); > + current_remove(display, sibling); > now = ring_next(ring, now); > if (shadow || skip) { > exclude_base = now; > @@ -2534,7 +2283,7 @@ static inline int red_current_add(RedWorker *worker, > Ring *ring, Drawable *drawa > Container *container; > > if (exclude_base) { > - exclude_region(worker, ring, exclude_base, &exclude_rgn, > NULL, NULL); > + exclude_region(display, ring, exclude_base, &exclude_rgn, > NULL, NULL); > region_clear(&exclude_rgn); > exclude_base = NULL; > } > @@ -2565,24 +2314,24 @@ static inline int red_current_add(RedWorker *worker, > Ring *ring, Drawable *drawa > } > if (item->effect == QXL_EFFECT_OPAQUE) { > region_or(&exclude_rgn, &item->base.rgn); > - exclude_region(worker, ring, exclude_base, &exclude_rgn, NULL, > drawable); > - red_use_stream_trace(worker->display_channel, drawable); > - streams_update_visible_region(worker->display_channel, drawable); > + exclude_region(display, ring, exclude_base, &exclude_rgn, NULL, > drawable); > + red_use_stream_trace(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(worker, drawable, ring); > + __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(worker, drawable, ring); > - if (is_primary_surface(worker->display_channel, drawable > ->surface_id)) { > - detach_streams_behind(worker->display_channel, &drawable > ->tree_item.base.rgn, drawable); > + __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); > @@ -2599,9 +2348,8 @@ static void add_clip_rects(QRegion *rgn, SpiceClipRects > *data) > } > } > > -static inline int red_current_add_with_shadow(RedWorker *worker, Ring *ring, > Drawable *item) > +static int red_current_add_with_shadow(DisplayChannel *display, Ring *ring, > Drawable *item) > { > - DisplayChannel *display = worker->display_channel; > #ifdef RED_WORKER_STAT > stat_time_t start_time = stat_now(worker); > ++worker->add_with_shadow_count; > @@ -2627,11 +2375,11 @@ static inline int > red_current_add_with_shadow(RedWorker *worker, Ring *ring, Dra > } > > ring_add(ring, &shadow->base.siblings_link); > - __current_add_drawable(worker, item, ring); > + __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(worker, ring, &shadow->base.siblings_link, > &exclude_rgn, NULL, NULL); > + exclude_region(display, ring, &shadow->base.siblings_link, > &exclude_rgn, NULL, NULL); > region_destroy(&exclude_rgn); > streams_update_visible_region(display, item); > } else { > @@ -2687,7 +2435,7 @@ static void drawable_update_streamable(DisplayChannel > *display, Drawable *drawab > drawable->streamable = TRUE; > } > > -static void red_print_stats(RedWorker *worker) > +void red_worker_print_stats(RedWorker *worker) > { > #ifdef RED_WORKER_STAT > if ((++worker->add_count % 100) == 0) { > @@ -2715,33 +2463,32 @@ static void red_print_stats(RedWorker *worker) > #endif > } > > -static int red_add_drawable(RedWorker *worker, Drawable *drawable) > + static int red_add_drawable(DisplayChannel *display, Drawable *drawable) > { > - DisplayChannel *display = worker->display_channel; > int ret = FALSE, surface_id = drawable->surface_id; > RedDrawable *red_drawable = drawable->red_drawable; > - Ring *ring = &worker->surfaces[surface_id].current; > + Ring *ring = &display->surfaces[surface_id].current; > > if (has_shadow(red_drawable)) { > - ret = red_current_add_with_shadow(worker, ring, drawable); > + ret = red_current_add_with_shadow(display, ring, drawable); > } else { > drawable_update_streamable(display, drawable); > - ret = red_current_add(worker, ring, drawable); > + ret = red_current_add(display, ring, drawable); > } > > - red_print_stats(worker); > + red_worker_print_stats(COMMON_CHANNEL(display)->worker); > return ret; > } > > -static void red_get_area(RedWorker *worker, int surface_id, const SpiceRect > *area, uint8_t *dest, > - int dest_stride, int update) > +static void red_get_area(DisplayChannel *display, int surface_id, const > SpiceRect *area, > + uint8_t *dest, int dest_stride, int update) > { > SpiceCanvas *canvas; > RedSurface *surface; > > - surface = &worker->surfaces[surface_id]; > + surface = &display->surfaces[surface_id]; > if (update) { > - red_update_area(worker, area, surface_id); > + red_update_area(display, area, surface_id); > } > > canvas = surface->context.canvas; > @@ -2793,7 +2540,7 @@ static inline int red_handle_self_bitmap(RedWorker > *worker, Drawable *drawable) > return TRUE; > } > > - surface = &worker->surfaces[drawable->surface_id]; > + surface = &display->surfaces[drawable->surface_id]; > > bpp = SPICE_SURFACE_FMT_DEPTH(surface->context.format) / 8; > > @@ -2819,7 +2566,7 @@ static inline int red_handle_self_bitmap(RedWorker > *worker, Drawable *drawable) > image->u.bitmap.data = spice_chunks_new_linear(dest, height * > dest_stride); > image->u.bitmap.data->flags |= SPICE_CHUNKS_FLAGS_FREE; > > - red_get_area(worker, drawable->surface_id, > + red_get_area(display, drawable->surface_id, > &red_drawable->self_bitmap_area, dest, dest_stride, TRUE); > > /* For 32bit non-primary surfaces we need to keep any non-zero > @@ -2838,9 +2585,8 @@ static inline int red_handle_self_bitmap(RedWorker > *worker, Drawable *drawable) > return TRUE; > } > > -static bool free_one_drawable(RedWorker *worker, int force_glz_free) > +static bool free_one_drawable(DisplayChannel *display, int force_glz_free) > { > - DisplayChannel *display = worker->display_channel; > RingItem *ring_item = ring_get_tail(&display->current_list); > Drawable *drawable; > Container *container; > @@ -2856,12 +2602,11 @@ static bool free_one_drawable(RedWorker *worker, int > force_glz_free) > red_display_free_glz_drawable(glz->dcc, glz); > } > } > - red_draw_drawable(worker, drawable); > + red_draw_drawable(display, drawable); > container = drawable->tree_item.base.container; > > - current_remove_drawable(worker, drawable); > - container_cleanup(worker, container); > - > + current_remove_drawable(display, drawable); > + container_cleanup(display, container); > return TRUE; > } > > @@ -2872,19 +2617,19 @@ static Drawable *get_drawable(RedWorker *worker, > uint8_t effect, RedDrawable *re > Drawable *drawable; > int x; > > - VALIDATE_SURFACE_RETVAL(worker, red_drawable->surface_id, NULL) > + VALIDATE_SURFACE_RETVAL(display, red_drawable->surface_id, NULL) > if (!validate_drawable_bbox(worker, red_drawable)) { > rendering_incorrect(__func__); > return NULL; > } > for (x = 0; x < 3; ++x) { > if (red_drawable->surface_deps[x] != -1) { > - VALIDATE_SURFACE_RETVAL(worker, red_drawable->surface_deps[x], > NULL) > + VALIDATE_SURFACE_RETVAL(display, red_drawable->surface_deps[x], > NULL) > } > } > > while (!(drawable = drawable_try_new(display))) { > - if (!free_one_drawable(COMMON_CHANNEL(display)->worker, FALSE)) > + if (!free_one_drawable(display, FALSE)) > return NULL; > } > > @@ -2909,24 +2654,24 @@ static Drawable *get_drawable(RedWorker *worker, > uint8_t effect, RedDrawable *re > return drawable; > } > > -static inline int red_handle_depends_on_target_surface(RedWorker *worker, > uint32_t surface_id) > +static inline int red_handle_depends_on_target_surface(DisplayChannel > *display, uint32_t surface_id) > { > RedSurface *surface; > RingItem *ring_item; > > - surface = &worker->surfaces[surface_id]; > + surface = &display->surfaces[surface_id]; > > while ((ring_item = ring_get_tail(&surface->depend_on_me))) { > Drawable *drawable; > DependItem *depended_item = SPICE_CONTAINEROF(ring_item, DependItem, > ring_item); > drawable = depended_item->drawable; > - surface_flush(worker, drawable->surface_id, &drawable->red_drawable > ->bbox); > + surface_flush(display, drawable->surface_id, &drawable->red_drawable > ->bbox); > } > > return TRUE; > } > > -static inline void add_to_surface_dependency(RedWorker *worker, int > depend_on_surface_id, > +static inline void add_to_surface_dependency(DisplayChannel *display, int > depend_on_surface_id, > DependItem *depend_item, > Drawable *drawable) > { > RedSurface *surface; > @@ -2936,22 +2681,21 @@ static inline void add_to_surface_dependency(RedWorker > *worker, int depend_on_su > return; > } > > - surface = &worker->surfaces[depend_on_surface_id]; > + surface = &display->surfaces[depend_on_surface_id]; > > depend_item->drawable = drawable; > ring_add(&surface->depend_on_me, &depend_item->ring_item); > } > > -static inline int red_handle_surfaces_dependencies(RedWorker *worker, > Drawable *drawable) > +static inline int red_handle_surfaces_dependencies(DisplayChannel *display, > Drawable *drawable) > { > - DisplayChannel *display = worker->display_channel; > int x; > > for (x = 0; x < 3; ++x) { > // surface self dependency is handled by shadows in "current", or by > // handle_self_bitmap > if (drawable->surface_deps[x] != drawable->surface_id) { > - add_to_surface_dependency(worker, drawable->surface_deps[x], > + add_to_surface_dependency(display, drawable->surface_deps[x], > &drawable->depend_items[x], drawable); > > if (drawable->surface_deps[x] == 0) { > @@ -2966,7 +2710,7 @@ static inline int > red_handle_surfaces_dependencies(RedWorker *worker, Drawable * > return TRUE; > } > > -static inline void red_inc_surfaces_drawable_dependencies(RedWorker *worker, > Drawable *drawable) > +static inline void red_inc_surfaces_drawable_dependencies(DisplayChannel > *display, Drawable *drawable) > { > int x; > int surface_id; > @@ -2977,7 +2721,7 @@ static inline void > red_inc_surfaces_drawable_dependencies(RedWorker *worker, Dra > if (surface_id == -1) { > continue; > } > - surface = &worker->surfaces[surface_id]; > + surface = &display->surfaces[surface_id]; > surface->refs++; > } > } > @@ -2996,7 +2740,7 @@ static inline void red_process_draw(RedWorker *worker, > RedDrawable *red_drawable > red_drawable->mm_time = reds_get_mm_time(); > surface_id = drawable->surface_id; > > - worker->surfaces[surface_id].refs++; > + display->surfaces[surface_id].refs++; > > region_add(&drawable->tree_item.base.rgn, &red_drawable->bbox); > > @@ -3008,13 +2752,14 @@ static inline void red_process_draw(RedWorker *worker, > RedDrawable *red_drawable > region_and(&drawable->tree_item.base.rgn, &rgn); > region_destroy(&rgn); > } > + > /* > surface->refs is affected by a drawable (that is > dependent on the surface) as long as the drawable is alive. > However, surface->depend_on_me is affected by a drawable only > as long as it is in the current tree (hasn't been rendered yet). > */ > - red_inc_surfaces_drawable_dependencies(worker, drawable); > + red_inc_surfaces_drawable_dependencies(worker->display_channel, > drawable); > > if (region_is_empty(&drawable->tree_item.base.rgn)) { > goto cleanup; > @@ -3024,38 +2769,36 @@ static inline void red_process_draw(RedWorker *worker, > RedDrawable *red_drawable > goto cleanup; > } > > - if (!red_handle_depends_on_target_surface(worker, surface_id)) { > + if (!red_handle_depends_on_target_surface(worker->display_channel, > surface_id)) { > goto cleanup; > } > > - if (!red_handle_surfaces_dependencies(worker, drawable)) { > + if (!red_handle_surfaces_dependencies(worker->display_channel, drawable)) > { > goto cleanup; > } > > - if (red_add_drawable(worker, drawable)) { > - red_pipes_add_drawable(worker, drawable); > + if (red_add_drawable(worker->display_channel, drawable)) { > + red_pipes_add_drawable(worker->display_channel, drawable); > } > cleanup: > display_channel_drawable_unref(display, drawable); > } > > -static inline void red_create_surface(RedWorker *worker, uint32_t > surface_id,uint32_t width, > - uint32_t height, int32_t stride, > uint32_t format, > - void *line_0, int data_is_valid, int > send_client); > > static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd > *surface, > uint32_t group_id, int loadvm) > { > + DisplayChannel *display = worker->display_channel; > uint32_t surface_id; > RedSurface *red_surface; > uint8_t *data; > > surface_id = surface->surface_id; > - if SPICE_UNLIKELY(surface_id >= worker->n_surfaces) { > + if SPICE_UNLIKELY(surface_id >= display->n_surfaces) { > goto exit; > } > > - red_surface = &worker->surfaces[surface_id]; > + red_surface = &display->surfaces[surface_id]; > > switch (surface->type) { > case QXL_SURFACE_CMD_CREATE: { > @@ -3071,7 +2814,7 @@ static inline void red_process_surface(RedWorker > *worker, RedSurfaceCmd *surface > if (stride < 0) { > data -= (int32_t)(stride * (height - 1)); > } > - red_create_surface(worker, surface_id, surface > ->u.surface_create.width, > + red_create_surface(worker->display_channel, surface_id, surface > ->u.surface_create.width, > height, stride, surface->u.surface_create.format, > data, > reloaded_surface, > // reloaded surfaces will be sent on demand > @@ -3085,13 +2828,13 @@ static inline void red_process_surface(RedWorker > *worker, RedSurfaceCmd *surface > break; > } > set_surface_release_info(&red_surface->destroy, surface > ->release_info, group_id); > - red_handle_depends_on_target_surface(worker, surface_id); > - /* note that red_handle_depends_on_target_surface must be called > before red_current_clear. > + red_handle_depends_on_target_surface(display, surface_id); > + /* note that red_handle_depends_on_target_surface must be called > before current_clear. > otherwise "current" will hold items that other drawables may > depend on, and then > red_current_clear will remove them from the pipe. */ > - red_current_clear(worker, surface_id); > - red_clear_surface_drawables_from_pipes(worker, surface_id, FALSE); > - red_surface_unref(worker, surface_id); > + current_clear(display, surface_id); > + red_clear_surface_drawables_from_pipes(display, surface_id, FALSE); > + display_channel_surface_unref(display, surface_id); > break; > default: > spice_error("unknown surface command"); > @@ -3104,31 +2847,30 @@ exit: > static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces, > uint32_t surface_id) > { > - RedWorker *worker; > + DisplayChannel *display; > > - worker = SPICE_CONTAINEROF(surfaces, RedWorker, image_surfaces); > - VALIDATE_SURFACE_RETVAL(worker, surface_id, NULL); > + display = SPICE_CONTAINEROF(surfaces, DisplayChannel, image_surfaces); > + VALIDATE_SURFACE_RETVAL(display, surface_id, NULL); > > - return worker->surfaces[surface_id].context.canvas; > + return display->surfaces[surface_id].context.canvas; > } > > -static void image_surface_init(RedWorker *worker) > +static void image_surface_init(DisplayChannel *display) > { > static SpiceImageSurfacesOps image_surfaces_ops = { > image_surfaces_get, > }; > > - worker->image_surfaces.ops = &image_surfaces_ops; > + display->image_surfaces.ops = &image_surfaces_ops; > } > > -static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable) > +static void red_draw_qxl_drawable(DisplayChannel *display, Drawable > *drawable) > { > - DisplayChannel *display = worker->display_channel; > RedSurface *surface; > SpiceCanvas *canvas; > SpiceClip clip = drawable->red_drawable->clip; > > - surface = &worker->surfaces[drawable->surface_id]; > + surface = &display->surfaces[drawable->surface_id]; > canvas = surface->context.canvas; > > image_cache_aging(&display->image_cache); > @@ -3259,17 +3001,17 @@ static void red_draw_qxl_drawable(RedWorker *worker, > Drawable *drawable) > } > } > > -static void red_draw_drawable(RedWorker *worker, Drawable *drawable) > +static void red_draw_drawable(DisplayChannel *display, Drawable *drawable) > { > - red_flush_source_surfaces(worker, drawable); > - red_draw_qxl_drawable(worker, drawable); > + red_flush_source_surfaces(display, drawable); > + red_draw_qxl_drawable(display, drawable); > } > > -static void validate_area(RedWorker *worker, const SpiceRect *area, uint32_t > surface_id) > +static void validate_area(DisplayChannel *display, const SpiceRect *area, > uint32_t surface_id) > { > RedSurface *surface; > > - surface = &worker->surfaces[surface_id]; > + surface = &display->surfaces[surface_id]; > if (!surface->context.canvas_draws_on_surface) { > SpiceCanvas *canvas = surface->context.canvas; > int h; > @@ -3291,10 +3033,9 @@ static void validate_area(RedWorker *worker, const > SpiceRect *area, uint32_t sur > Renders drawables for updating the requested area, but only drawables > that are older > than 'last' (exclusive). > */ > -static void red_update_area_till(RedWorker *worker, const SpiceRect *area, > int surface_id, > +static void red_update_area_till(DisplayChannel *display, const SpiceRect > *area, int surface_id, > Drawable *last) > { > - DisplayChannel *display = worker->display_channel; > RedSurface *surface; > Drawable *surface_last = NULL; > Ring *ring; > @@ -3305,7 +3046,7 @@ static void red_update_area_till(RedWorker *worker, > const SpiceRect *area, int s > spice_assert(last); > spice_assert(ring_item_is_linked(&last->list_link)); > > - surface = &worker->surfaces[surface_id]; > + surface = &display->surfaces[surface_id]; > > if (surface_id != last->surface_id) { > // find the nearest older drawable from the appropriate surface > @@ -3357,22 +3098,21 @@ static void red_update_area_till(RedWorker *worker, > const SpiceRect *area, int s > now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link); > now->refs++; > container = now->tree_item.base.container; > - current_remove_drawable(worker, now); > - container_cleanup(worker, container); > + current_remove_drawable(display, now); > + container_cleanup(display, container); > /* red_draw_drawable may call red_update_area for the surfaces 'now' > depends on. Notice, > that it is valid to call red_update_area in this case and not > red_update_area_till: > It is impossible that there was newer item then 'last' in one of > the surfaces > that red_update_area is called for, Otherwise, 'now' would have > already been rendered. > See the call for red_handle_depends_on_target_surface in > red_process_draw */ > - red_draw_drawable(worker, now); > + red_draw_drawable(display, now); > display_channel_drawable_unref(display, now); > } while (now != surface_last); > - validate_area(worker, area, surface_id); > + validate_area(display, area, surface_id); > } > > -static void red_update_area(RedWorker *worker, const SpiceRect *area, int > surface_id) > +static void red_update_area(DisplayChannel *display, const SpiceRect *area, > int surface_id) > { > - DisplayChannel *display = worker->display_channel; > RedSurface *surface; > Ring *ring; > RingItem *ring_item; > @@ -3387,7 +3127,7 @@ static void red_update_area(RedWorker *worker, const > SpiceRect *area, int surfac > spice_return_if_fail(area->left >= 0 && area->top >= 0 && > area->left < area->right && area->top < area > ->bottom); > > - surface = &worker->surfaces[surface_id]; > + surface = &display->surfaces[surface_id]; > > last = NULL; > ring = &surface->current_list; > @@ -3405,7 +3145,7 @@ static void red_update_area(RedWorker *worker, const > SpiceRect *area, int surfac > region_destroy(&rgn); > > if (!last) { > - validate_area(worker, area, surface_id); > + validate_area(display, area, surface_id); > return; > } > > @@ -3416,12 +3156,12 @@ static void red_update_area(RedWorker *worker, const > SpiceRect *area, int surfac > now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link); > now->refs++; > container = now->tree_item.base.container; > - current_remove_drawable(worker, now); > - container_cleanup(worker, container); > - red_draw_drawable(worker, now); > + current_remove_drawable(display, now); > + container_cleanup(display, container); > + red_draw_drawable(display, now); > display_channel_drawable_unref(display, now); > } while (now != last); > - validate_area(worker, area, surface_id); > + validate_area(display, area, surface_id); > } > > static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int > *ring_is_empty) > @@ -3540,11 +3280,11 @@ static int red_process_commands(RedWorker *worker, > uint32_t max_pipe_size, int * > &update, ext_cmd.cmd.data)) { > break; > } > - if (!validate_surface(worker, update.surface_id)) { > + if (!validate_surface(worker->display_channel, > update.surface_id)) { > rendering_incorrect("QXL_CMD_UPDATE"); > break; > } > - red_update_area(worker, &update.area, update.surface_id); > + red_update_area(worker->display_channel, &update.area, > update.surface_id); > worker->qxl->st->qif->notify_update(worker->qxl, > update.update_id); > release_info_ext.group_id = ext_cmd.group_id; > release_info_ext.info = update.release_info; > @@ -3618,7 +3358,7 @@ static void red_free_some(RedWorker *worker) > } > > while (!ring_is_empty(&display->current_list) && n++ < > RED_RELEASE_BUNCH_SIZE) { > - free_one_drawable(worker, TRUE); > + free_one_drawable(display, TRUE); > } > > FOREACH_DCC(worker->display_channel, item, next, dcc) { > @@ -3630,12 +3370,12 @@ static void red_free_some(RedWorker *worker) > } > } > > -static void red_current_flush(RedWorker *worker, int surface_id) > +static void red_current_flush(DisplayChannel *display, int surface_id) > { > - while (!ring_is_empty(&worker->surfaces[surface_id].current_list)) { > - free_one_drawable(worker, FALSE); > + while (!ring_is_empty(&display->surfaces[surface_id].current_list)) { > + free_one_drawable(display, FALSE); > } > - red_current_clear(worker, surface_id); > + current_clear(display, surface_id); > } > > // adding the pipe item after pos. If pos == NULL, adding to head. > @@ -3644,8 +3384,7 @@ static ImageItem > *red_add_surface_area_image(DisplayChannelClient *dcc, int surf > { > DisplayChannel *display = DCC_TO_DC(dcc); > RedChannel *channel = RED_CHANNEL(display); > - RedWorker *worker = DCC_TO_WORKER(dcc); > - RedSurface *surface = &worker->surfaces[surface_id]; > + RedSurface *surface = &display->surfaces[surface_id]; > SpiceCanvas *canvas = surface->context.canvas; > ImageItem *item; > int stride; > @@ -3705,15 +3444,11 @@ static ImageItem > *red_add_surface_area_image(DisplayChannelClient *dcc, int surf > > static void red_push_surface_image(DisplayChannelClient *dcc, int surface_id) > { > + DisplayChannel *display = DCC_TO_DC(dcc); > SpiceRect area; > RedSurface *surface; > - RedWorker *worker; > > - if (!dcc) { > - return; > - } > - worker = DCC_TO_WORKER(dcc); > - surface = &worker->surfaces[surface_id]; > + surface = &display->surfaces[surface_id]; > if (!surface->context.canvas) { > return; > } > @@ -5140,8 +4875,7 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, > SpiceMarshaller *m, > SpiceImage *simage, Drawable *drawable, int > can_lossy) > { > RedChannelClient *rcc = RED_CHANNEL_CLIENT(dcc); > - DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, > DisplayChannel, common.base); > - RedWorker *worker = DCC_TO_WORKER(dcc); > + DisplayChannel *display = DCC_TO_DC(dcc); > SpiceImage image; > compress_send_data_t comp_send_data = {0}; > SpiceMarshaller *bitmap_palette_out, *lzplt_palette_out; > @@ -5164,7 +4898,7 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, > SpiceMarshaller *m, > dcc->send_data.pixmap_cache_items[dcc > ->send_data.num_pixmap_cache_items++] = > > image.descriptor.id; > if (can_lossy || !lossy_cache_item) { > - if (!display_channel->enable_jpeg || lossy_cache_item) { > + if (!display->enable_jpeg || lossy_cache_item) { > image.descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE; > } else { > // making sure, in multiple monitor scenario, that lossy > items that > @@ -5176,7 +4910,7 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, > SpiceMarshaller *m, > &bitmap_palette_out, > &lzplt_palette_out); > spice_assert(bitmap_palette_out == NULL); > spice_assert(lzplt_palette_out == NULL); > - stat_inc_counter(display_channel->cache_hits_counter, 1); > + stat_inc_counter(display->cache_hits_counter, 1); > pthread_mutex_unlock(&dcc->pixmap_cache->lock); > return FILL_BITS_TYPE_CACHE; > } else { > @@ -5193,13 +4927,13 @@ static FillBitsType fill_bits(DisplayChannelClient > *dcc, SpiceMarshaller *m, > RedSurface *surface; > > surface_id = simage->u.surface.surface_id; > - if (!validate_surface(worker, surface_id)) { > + if (!validate_surface(display, surface_id)) { > rendering_incorrect("SPICE_IMAGE_TYPE_SURFACE"); > pthread_mutex_unlock(&dcc->pixmap_cache->lock); > return FILL_BITS_TYPE_SURFACE; > } > > - surface = &worker->surfaces[surface_id]; > + surface = &display->surfaces[surface_id]; > image.descriptor.type = SPICE_IMAGE_TYPE_SURFACE; > image.descriptor.flags = 0; > image.descriptor.width = surface->context.width; > @@ -5286,16 +5020,16 @@ static FillBitsType fill_bits(DisplayChannelClient > *dcc, SpiceMarshaller *m, > static void fill_mask(RedChannelClient *rcc, SpiceMarshaller *m, > SpiceImage *mask_bitmap, Drawable *drawable) > { > - DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, > DisplayChannel, common.base); > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > + DisplayChannel *display = DCC_TO_DC(dcc); > > if (mask_bitmap && m) { > - if (display_channel->common.worker->image_compression != > SPICE_IMAGE_COMPRESSION_OFF) { > + if (display->common.worker->image_compression != > SPICE_IMAGE_COMPRESSION_OFF) { > SpiceImageCompression save_img_comp = > - display_channel->common.worker->image_compression; > - display_channel->common.worker->image_compression = > SPICE_IMAGE_COMPRESSION_OFF; > + display->common.worker->image_compression; > + display->common.worker->image_compression = > SPICE_IMAGE_COMPRESSION_OFF; > fill_bits(dcc, m, mask_bitmap, drawable, FALSE); > - display_channel->common.worker->image_compression = > save_img_comp; > + display->common.worker->image_compression = save_img_comp; > } else { > fill_bits(dcc, m, mask_bitmap, drawable, FALSE); > } > @@ -5328,10 +5062,10 @@ static int is_surface_area_lossy(DisplayChannelClient > *dcc, uint32_t surface_id, > RedSurface *surface; > QRegion *surface_lossy_region; > QRegion lossy_region; > - RedWorker *worker = DCC_TO_WORKER(dcc); > + DisplayChannel *display = DCC_TO_DC(dcc); > > - VALIDATE_SURFACE_RETVAL(worker, surface_id, FALSE); > - surface = &worker->surfaces[surface_id]; > + VALIDATE_SURFACE_RETVAL(display, surface_id, FALSE); > + surface = &display->surfaces[surface_id]; > surface_lossy_region = &dcc->surface_client_lossy_region[surface_id]; > > if (!area) { > @@ -5421,7 +5155,7 @@ static int is_brush_lossy(RedChannelClient *rcc, > SpiceBrush *brush, > } > } > > -static void surface_lossy_region_update(RedWorker *worker, > DisplayChannelClient *dcc, > +static void surface_lossy_region_update(DisplayChannelClient *dcc, > Drawable *item, int has_mask, int > lossy) > { > QRegion *surface_lossy_region; > @@ -5532,8 +5266,7 @@ static inline int drawable_depends_on_areas(Drawable > *drawable, > } > > > -static int pipe_rendered_drawables_intersect_with_areas(RedWorker *worker, > - DisplayChannelClient > *dcc, > +static int pipe_rendered_drawables_intersect_with_areas(DisplayChannelClient > *dcc, > int surface_ids[], > SpiceRect > *surface_areas[], > int num_surfaces) > @@ -5565,8 +5298,7 @@ static int > pipe_rendered_drawables_intersect_with_areas(RedWorker *worker, > return FALSE; > } > > -static void red_pipe_replace_rendered_drawables_with_images(RedWorker > *worker, > - > DisplayChannelClient *dcc, > +static void > red_pipe_replace_rendered_drawables_with_images(DisplayChannelClient *dcc, > int > first_surface_id, > SpiceRect > *first_area) > { > @@ -5621,15 +5353,15 @@ static void > red_pipe_replace_rendered_drawables_with_images(RedWorker *worker, > } > } > > -static void red_add_lossless_drawable_dependencies(RedWorker *worker, > - RedChannelClient *rcc, > +static void red_add_lossless_drawable_dependencies(RedChannelClient *rcc, > Drawable *item, > int deps_surfaces_ids[], > SpiceRect *deps_areas[], > int num_deps) > { > - RedDrawable *drawable = item->red_drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > + DisplayChannel *display = DCC_TO_DC(dcc); > + RedDrawable *drawable = item->red_drawable; > int sync_rendered = FALSE; > int i; > > @@ -5642,7 +5374,7 @@ static void > red_add_lossless_drawable_dependencies(RedWorker *worker, > // that were rendered, affected the areas that need to be resent > if (!drawable_intersects_with_areas(item, deps_surfaces_ids, > deps_areas, num_deps)) { > - if (pipe_rendered_drawables_intersect_with_areas(worker, dcc, > + if (pipe_rendered_drawables_intersect_with_areas(dcc, > > deps_surfaces_ids, > deps_areas, > num_deps)) { > @@ -5654,7 +5386,7 @@ static void > red_add_lossless_drawable_dependencies(RedWorker *worker, > } else { > sync_rendered = FALSE; > for (i = 0; i < num_deps; i++) { > - red_update_area_till(worker, deps_areas[i], > + red_update_area_till(display, deps_areas[i], > deps_surfaces_ids[i], item); > } > } > @@ -5677,11 +5409,11 @@ static void > red_add_lossless_drawable_dependencies(RedWorker *worker, > drawable_bbox[0] = &drawable->bbox; > > // check if the other rendered images in the pipe have updated the > drawable bbox > - if (pipe_rendered_drawables_intersect_with_areas(worker, dcc, > + if (pipe_rendered_drawables_intersect_with_areas(dcc, > drawable_surface_id, > drawable_bbox, > 1)) { > - red_pipe_replace_rendered_drawables_with_images(worker, dcc, > + red_pipe_replace_rendered_drawables_with_images(dcc, > drawable > ->surface_id, > &drawable->bbox); > } > @@ -5691,10 +5423,9 @@ static void > red_add_lossless_drawable_dependencies(RedWorker *worker, > } > } > > -static void red_marshall_qxl_draw_fill(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_marshall_qxl_draw_fill(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > @@ -5719,13 +5450,12 @@ static void red_marshall_qxl_draw_fill(RedWorker > *worker, > } > > > -static void red_lossy_marshall_qxl_draw_fill(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *m, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_draw_fill(RedChannelClient *rcc, > + SpiceMarshaller *m, > + DrawablePipeItem *dpi) > { > - Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > + Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > > int dest_allowed_lossy = FALSE; > @@ -5752,9 +5482,9 @@ static void red_lossy_marshall_qxl_draw_fill(RedWorker > *worker, > !(brush_is_lossy && (brush_bitmap_data.type == > BITMAP_DATA_TYPE_SURFACE))) { > int has_mask = !!drawable->u.fill.mask.bitmap; > > - red_marshall_qxl_draw_fill(worker, rcc, m, dpi); > + red_marshall_qxl_draw_fill(rcc, m, dpi); > // either the brush operation is opaque, or the dest is not lossy > - surface_lossy_region_update(worker, dcc, item, has_mask, FALSE); > + surface_lossy_region_update(dcc, item, has_mask, FALSE); > } else { > int resend_surface_ids[2]; > SpiceRect *resend_areas[2]; > @@ -5772,18 +5502,17 @@ static void red_lossy_marshall_qxl_draw_fill(RedWorker > *worker, > num_resend++; > } > > - red_add_lossless_drawable_dependencies(worker, rcc, item, > + red_add_lossless_drawable_dependencies(rcc, item, > resend_surface_ids, > resend_areas, num_resend); > } > } > > -static FillBitsType red_marshall_qxl_draw_opaque(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller > *base_marshaller, > - DrawablePipeItem *dpi, int > src_allowed_lossy) > +static FillBitsType red_marshall_qxl_draw_opaque(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi, int > src_allowed_lossy) > { > - Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > + Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > SpiceMarshaller *brush_pat_out; > SpiceMarshaller *src_bitmap_out; > @@ -5811,13 +5540,12 @@ static FillBitsType > red_marshall_qxl_draw_opaque(RedWorker *worker, > return src_send_type; > } > > -static void red_lossy_marshall_qxl_draw_opaque(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *m, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_draw_opaque(RedChannelClient *rcc, > + SpiceMarshaller *m, > + DrawablePipeItem *dpi) > { > - Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > + Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > > int src_allowed_lossy; > @@ -5847,14 +5575,14 @@ static void > red_lossy_marshall_qxl_draw_opaque(RedWorker *worker, > FillBitsType src_send_type; > int has_mask = !!drawable->u.opaque.mask.bitmap; > > - src_send_type = red_marshall_qxl_draw_opaque(worker, rcc, m, dpi, > src_allowed_lossy); > + src_send_type = red_marshall_qxl_draw_opaque(rcc, m, dpi, > src_allowed_lossy); > if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSY) { > src_is_lossy = TRUE; > } else if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSLESS) { > src_is_lossy = FALSE; > } > > - surface_lossy_region_update(worker, dcc, item, has_mask, > src_is_lossy); > + surface_lossy_region_update(dcc, item, has_mask, src_is_lossy); > } else { > int resend_surface_ids[2]; > SpiceRect *resend_areas[2]; > @@ -5872,19 +5600,18 @@ static void > red_lossy_marshall_qxl_draw_opaque(RedWorker *worker, > num_resend++; > } > > - red_add_lossless_drawable_dependencies(worker, rcc, item, > + red_add_lossless_drawable_dependencies(rcc, item, > resend_surface_ids, > resend_areas, num_resend); > } > } > > -static FillBitsType red_marshall_qxl_draw_copy(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi, int > src_allowed_lossy) > +static FillBitsType red_marshall_qxl_draw_copy(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi, int > src_allowed_lossy) > { > + DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > - DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > SpiceMarshaller *src_bitmap_out; > SpiceMarshaller *mask_bitmap_out; > SpiceCopy copy; > @@ -5904,13 +5631,12 @@ static FillBitsType > red_marshall_qxl_draw_copy(RedWorker *worker, > return src_send_type; > } > > -static void red_lossy_marshall_qxl_draw_copy(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_draw_copy(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi) > { > - Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > + Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > int has_mask = !!drawable->u.copy.mask.bitmap; > int src_is_lossy; > @@ -5920,23 +5646,22 @@ static void red_lossy_marshall_qxl_draw_copy(RedWorker > *worker, > src_is_lossy = is_bitmap_lossy(rcc, drawable->u.copy.src_bitmap, > &drawable->u.copy.src_area, item, > &src_bitmap_data); > > - src_send_type = red_marshall_qxl_draw_copy(worker, rcc, base_marshaller, > dpi, TRUE); > + src_send_type = red_marshall_qxl_draw_copy(rcc, base_marshaller, dpi, > TRUE); > if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSY) { > src_is_lossy = TRUE; > } else if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSLESS) { > src_is_lossy = FALSE; > } > - surface_lossy_region_update(worker, dcc, item, has_mask, > + surface_lossy_region_update(dcc, item, has_mask, > src_is_lossy); > } > > -static void red_marshall_qxl_draw_transparent(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_marshall_qxl_draw_transparent(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi) > { > - Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > + Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > SpiceMarshaller *src_bitmap_out; > SpiceTransparent transparent; > @@ -5951,10 +5676,9 @@ static void red_marshall_qxl_draw_transparent(RedWorker > *worker, > fill_bits(dcc, src_bitmap_out, transparent.src_bitmap, item, FALSE); > } > > -static void red_lossy_marshall_qxl_draw_transparent(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller > *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_draw_transparent(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > @@ -5965,7 +5689,7 @@ static void > red_lossy_marshall_qxl_draw_transparent(RedWorker *worker, > &drawable->u.transparent.src_area, item, > &src_bitmap_data); > > if (!src_is_lossy || (src_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)) > { > - red_marshall_qxl_draw_transparent(worker, rcc, base_marshaller, dpi); > + red_marshall_qxl_draw_transparent(rcc, base_marshaller, dpi); > // don't update surface lossy region since transperent areas might be > lossy > } else { > int resend_surface_ids[1]; > @@ -5974,16 +5698,15 @@ static void > red_lossy_marshall_qxl_draw_transparent(RedWorker *worker, > resend_surface_ids[0] = src_bitmap_data.id; > resend_areas[0] = &src_bitmap_data.lossy_rect; > > - red_add_lossless_drawable_dependencies(worker, rcc, item, > + red_add_lossless_drawable_dependencies(rcc, item, > resend_surface_ids, > resend_areas, 1); > } > } > > -static FillBitsType red_marshall_qxl_draw_alpha_blend(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller > *base_marshaller, > - DrawablePipeItem *dpi, > - int src_allowed_lossy) > +static FillBitsType red_marshall_qxl_draw_alpha_blend(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi, > + int src_allowed_lossy) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6005,10 +5728,9 @@ static FillBitsType > red_marshall_qxl_draw_alpha_blend(RedWorker *worker, > return src_send_type; > } > > -static void red_lossy_marshall_qxl_draw_alpha_blend(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller > *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_draw_alpha_blend(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6020,7 +5742,7 @@ static void > red_lossy_marshall_qxl_draw_alpha_blend(RedWorker *worker, > src_is_lossy = is_bitmap_lossy(rcc, drawable->u.alpha_blend.src_bitmap, > &drawable->u.alpha_blend.src_area, item, > &src_bitmap_data); > > - src_send_type = red_marshall_qxl_draw_alpha_blend(worker, rcc, > base_marshaller, dpi, TRUE); > + src_send_type = red_marshall_qxl_draw_alpha_blend(rcc, base_marshaller, > dpi, TRUE); > > if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSY) { > src_is_lossy = TRUE; > @@ -6029,14 +5751,13 @@ static void > red_lossy_marshall_qxl_draw_alpha_blend(RedWorker *worker, > } > > if (src_is_lossy) { > - surface_lossy_region_update(worker, dcc, item, FALSE, src_is_lossy); > + surface_lossy_region_update(dcc, item, FALSE, src_is_lossy); > } // else, the area stays lossy/lossless as the destination > } > > -static void red_marshall_qxl_copy_bits(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_marshall_qxl_copy_bits(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > @@ -6049,10 +5770,9 @@ static void red_marshall_qxl_copy_bits(RedWorker > *worker, > ©_bits); > } > > -static void red_lossy_marshall_qxl_copy_bits(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_copy_bits(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6063,7 +5783,7 @@ static void red_lossy_marshall_qxl_copy_bits(RedWorker > *worker, > int src_is_lossy; > SpiceRect src_lossy_area; > > - red_marshall_qxl_copy_bits(worker, rcc, base_marshaller, dpi); > + red_marshall_qxl_copy_bits(rcc, base_marshaller, dpi); > > horz_offset = drawable->u.copy_bits.src_pos.x - drawable->bbox.left; > vert_offset = drawable->u.copy_bits.src_pos.y - drawable->bbox.top; > @@ -6076,14 +5796,12 @@ static void red_lossy_marshall_qxl_copy_bits(RedWorker > *worker, > src_is_lossy = is_surface_area_lossy(dcc, item->surface_id, > &src_rect, &src_lossy_area); > > - surface_lossy_region_update(worker, dcc, item, FALSE, > - src_is_lossy); > + surface_lossy_region_update(dcc, item, FALSE, src_is_lossy); > } > > -static void red_marshall_qxl_draw_blend(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_marshall_qxl_draw_blend(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6105,10 +5823,9 @@ static void red_marshall_qxl_draw_blend(RedWorker > *worker, > fill_mask(rcc, mask_bitmap_out, blend.mask.bitmap, item); > } > > -static void red_lossy_marshall_qxl_draw_blend(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_draw_blend(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6125,7 +5842,7 @@ static void red_lossy_marshall_qxl_draw_blend(RedWorker > *worker, > > if (!dest_is_lossy && > (!src_is_lossy || (src_bitmap_data.type != > BITMAP_DATA_TYPE_SURFACE))) { > - red_marshall_qxl_draw_blend(worker, rcc, base_marshaller, dpi); > + red_marshall_qxl_draw_blend(rcc, base_marshaller, dpi); > } else { > int resend_surface_ids[2]; > SpiceRect *resend_areas[2]; > @@ -6143,15 +5860,14 @@ static void > red_lossy_marshall_qxl_draw_blend(RedWorker *worker, > num_resend++; > } > > - red_add_lossless_drawable_dependencies(worker, rcc, item, > + red_add_lossless_drawable_dependencies(rcc, item, > resend_surface_ids, > resend_areas, num_resend); > } > } > > -static void red_marshall_qxl_draw_blackness(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_marshall_qxl_draw_blackness(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > @@ -6169,25 +5885,23 @@ static void red_marshall_qxl_draw_blackness(RedWorker > *worker, > fill_mask(rcc, mask_bitmap_out, blackness.mask.bitmap, item); > } > > -static void red_lossy_marshall_qxl_draw_blackness(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller > *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_draw_blackness(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > RedDrawable *drawable = item->red_drawable; > int has_mask = !!drawable->u.blackness.mask.bitmap; > > - red_marshall_qxl_draw_blackness(worker, rcc, base_marshaller, dpi); > + red_marshall_qxl_draw_blackness(rcc, base_marshaller, dpi); > > - surface_lossy_region_update(worker, dcc, item, has_mask, FALSE); > + surface_lossy_region_update(dcc, item, has_mask, FALSE); > } > > -static void red_marshall_qxl_draw_whiteness(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_marshall_qxl_draw_whiteness(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > @@ -6205,25 +5919,23 @@ static void red_marshall_qxl_draw_whiteness(RedWorker > *worker, > fill_mask(rcc, mask_bitmap_out, whiteness.mask.bitmap, item); > } > > -static void red_lossy_marshall_qxl_draw_whiteness(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller > *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_draw_whiteness(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > RedDrawable *drawable = item->red_drawable; > int has_mask = !!drawable->u.whiteness.mask.bitmap; > > - red_marshall_qxl_draw_whiteness(worker, rcc, base_marshaller, dpi); > + red_marshall_qxl_draw_whiteness(rcc, base_marshaller, dpi); > > - surface_lossy_region_update(worker, dcc, item, has_mask, FALSE); > + surface_lossy_region_update(dcc, item, has_mask, FALSE); > } > > -static void red_marshall_qxl_draw_inverse(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - Drawable *item) > +static void red_marshall_qxl_draw_inverse(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + Drawable *item) > { > RedDrawable *drawable = item->red_drawable; > SpiceMarshaller *mask_bitmap_out; > @@ -6240,18 +5952,16 @@ static void red_marshall_qxl_draw_inverse(RedWorker > *worker, > fill_mask(rcc, mask_bitmap_out, inverse.mask.bitmap, item); > } > > -static void red_lossy_marshall_qxl_draw_inverse(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - Drawable *item) > +static void red_lossy_marshall_qxl_draw_inverse(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + Drawable *item) > { > - red_marshall_qxl_draw_inverse(worker, rcc, base_marshaller, item); > + red_marshall_qxl_draw_inverse(rcc, base_marshaller, item); > } > > -static void red_marshall_qxl_draw_rop3(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_marshall_qxl_draw_rop3(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6278,10 +5988,9 @@ static void red_marshall_qxl_draw_rop3(RedWorker > *worker, > fill_mask(rcc, mask_bitmap_out, rop3.mask.bitmap, item); > } > > -static void red_lossy_marshall_qxl_draw_rop3(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_draw_rop3(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6304,8 +6013,8 @@ static void red_lossy_marshall_qxl_draw_rop3(RedWorker > *worker, > (!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); > + red_marshall_qxl_draw_rop3(rcc, base_marshaller, dpi); > + surface_lossy_region_update(dcc, item, has_mask, FALSE); > } else { > int resend_surface_ids[3]; > SpiceRect *resend_areas[3]; > @@ -6329,15 +6038,14 @@ static void red_lossy_marshall_qxl_draw_rop3(RedWorker > *worker, > num_resend++; > } > > - red_add_lossless_drawable_dependencies(worker, rcc, item, > + red_add_lossless_drawable_dependencies(rcc, item, > resend_surface_ids, > resend_areas, num_resend); > } > } > > -static void red_marshall_qxl_draw_composite(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_marshall_qxl_draw_composite(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6360,8 +6068,7 @@ static void red_marshall_qxl_draw_composite(RedWorker > *worker, > } > } > > -static void red_lossy_marshall_qxl_draw_composite(RedWorker *worker, > - RedChannelClient *rcc, > +static void red_lossy_marshall_qxl_draw_composite(RedChannelClient *rcc, > SpiceMarshaller > *base_marshaller, > DrawablePipeItem *dpi) > { > @@ -6386,8 +6093,8 @@ static void > red_lossy_marshall_qxl_draw_composite(RedWorker *worker, > 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); > + red_marshall_qxl_draw_composite(rcc, base_marshaller, dpi); > + surface_lossy_region_update(dcc, item, FALSE, FALSE); > } > else { > int resend_surface_ids[3]; > @@ -6412,15 +6119,14 @@ static void > red_lossy_marshall_qxl_draw_composite(RedWorker *worker, > num_resend++; > } > > - red_add_lossless_drawable_dependencies(worker, rcc, item, > + red_add_lossless_drawable_dependencies(rcc, item, > resend_surface_ids, > resend_areas, num_resend); > } > } > > -static void red_marshall_qxl_draw_stroke(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_marshall_qxl_draw_stroke(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6443,10 +6149,9 @@ static void red_marshall_qxl_draw_stroke(RedWorker > *worker, > } > } > > -static void red_lossy_marshall_qxl_draw_stroke(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_draw_stroke(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6475,7 +6180,7 @@ static void red_lossy_marshall_qxl_draw_stroke(RedWorker > *worker, > if (!dest_is_lossy && > (!brush_is_lossy || (brush_bitmap_data.type != > BITMAP_DATA_TYPE_SURFACE))) > { > - red_marshall_qxl_draw_stroke(worker, rcc, base_marshaller, dpi); > + red_marshall_qxl_draw_stroke(rcc, base_marshaller, dpi); > } else { > int resend_surface_ids[2]; > SpiceRect *resend_areas[2]; > @@ -6494,15 +6199,14 @@ static void > red_lossy_marshall_qxl_draw_stroke(RedWorker *worker, > num_resend++; > } > > - red_add_lossless_drawable_dependencies(worker, rcc, item, > + red_add_lossless_drawable_dependencies(rcc, item, > resend_surface_ids, > resend_areas, num_resend); > } > } > > -static void red_marshall_qxl_draw_text(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_marshall_qxl_draw_text(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6527,10 +6231,9 @@ static void red_marshall_qxl_draw_text(RedWorker > *worker, > } > } > > -static void red_lossy_marshall_qxl_draw_text(RedWorker *worker, > - RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > - DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_draw_text(RedChannelClient *rcc, > + SpiceMarshaller > *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > @@ -6567,7 +6270,7 @@ static void red_lossy_marshall_qxl_draw_text(RedWorker > *worker, > if (!dest_is_lossy && > (!fg_is_lossy || (fg_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)) > && > (!bg_is_lossy || (bg_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE))) > { > - red_marshall_qxl_draw_text(worker, rcc, base_marshaller, dpi); > + red_marshall_qxl_draw_text(rcc, base_marshaller, dpi); > } else { > int resend_surface_ids[3]; > SpiceRect *resend_areas[3]; > @@ -6590,111 +6293,112 @@ static void > red_lossy_marshall_qxl_draw_text(RedWorker *worker, > resend_areas[num_resend] = &dest_lossy_area; > num_resend++; > } > - red_add_lossless_drawable_dependencies(worker, rcc, item, > + red_add_lossless_drawable_dependencies(rcc, item, > resend_surface_ids, > resend_areas, num_resend); > } > } > > -static void red_lossy_marshall_qxl_drawable(RedWorker *worker, > RedChannelClient *rcc, > - SpiceMarshaller *base_marshaller, > DrawablePipeItem *dpi) > +static void red_lossy_marshall_qxl_drawable(RedChannelClient *rcc, > + SpiceMarshaller *base_marshaller, > + DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > switch (item->red_drawable->type) { > case QXL_DRAW_FILL: > - red_lossy_marshall_qxl_draw_fill(worker, rcc, base_marshaller, dpi); > + red_lossy_marshall_qxl_draw_fill(rcc, base_marshaller, dpi); > break; > case QXL_DRAW_OPAQUE: > - red_lossy_marshall_qxl_draw_opaque(worker, rcc, base_marshaller, > dpi); > + red_lossy_marshall_qxl_draw_opaque(rcc, base_marshaller, dpi); > break; > case QXL_DRAW_COPY: > - red_lossy_marshall_qxl_draw_copy(worker, rcc, base_marshaller, dpi); > + red_lossy_marshall_qxl_draw_copy(rcc, base_marshaller, dpi); > break; > case QXL_DRAW_TRANSPARENT: > - red_lossy_marshall_qxl_draw_transparent(worker, rcc, base_marshaller, > dpi); > + red_lossy_marshall_qxl_draw_transparent(rcc, base_marshaller, dpi); > break; > case QXL_DRAW_ALPHA_BLEND: > - red_lossy_marshall_qxl_draw_alpha_blend(worker, rcc, base_marshaller, > dpi); > + red_lossy_marshall_qxl_draw_alpha_blend(rcc, base_marshaller, dpi); > break; > case QXL_COPY_BITS: > - red_lossy_marshall_qxl_copy_bits(worker, rcc, base_marshaller, dpi); > + red_lossy_marshall_qxl_copy_bits(rcc, base_marshaller, dpi); > break; > case QXL_DRAW_BLEND: > - red_lossy_marshall_qxl_draw_blend(worker, rcc, base_marshaller, dpi); > + red_lossy_marshall_qxl_draw_blend(rcc, base_marshaller, dpi); > break; > case QXL_DRAW_BLACKNESS: > - red_lossy_marshall_qxl_draw_blackness(worker, rcc, base_marshaller, > dpi); > + red_lossy_marshall_qxl_draw_blackness(rcc, base_marshaller, dpi); > break; > case QXL_DRAW_WHITENESS: > - red_lossy_marshall_qxl_draw_whiteness(worker, rcc, base_marshaller, > dpi); > + red_lossy_marshall_qxl_draw_whiteness(rcc, base_marshaller, dpi); > break; > case QXL_DRAW_INVERS: > - red_lossy_marshall_qxl_draw_inverse(worker, rcc, base_marshaller, > item); > + red_lossy_marshall_qxl_draw_inverse(rcc, base_marshaller, item); > break; > case QXL_DRAW_ROP3: > - red_lossy_marshall_qxl_draw_rop3(worker, rcc, base_marshaller, dpi); > + red_lossy_marshall_qxl_draw_rop3(rcc, base_marshaller, dpi); > break; > case QXL_DRAW_COMPOSITE: > - red_lossy_marshall_qxl_draw_composite(worker, rcc, base_marshaller, > dpi); > + red_lossy_marshall_qxl_draw_composite(rcc, base_marshaller, dpi); > break; > case QXL_DRAW_STROKE: > - red_lossy_marshall_qxl_draw_stroke(worker, rcc, base_marshaller, > dpi); > + red_lossy_marshall_qxl_draw_stroke(rcc, base_marshaller, dpi); > break; > case QXL_DRAW_TEXT: > - red_lossy_marshall_qxl_draw_text(worker, rcc, base_marshaller, dpi); > + red_lossy_marshall_qxl_draw_text(rcc, base_marshaller, dpi); > break; > default: > spice_error("invalid type"); > } > } > > -static inline void red_marshall_qxl_drawable(RedWorker *worker, > RedChannelClient *rcc, > - SpiceMarshaller *m, DrawablePipeItem *dpi) > +static inline void red_marshall_qxl_drawable(RedChannelClient *rcc, > + SpiceMarshaller *m, > DrawablePipeItem *dpi) > { > Drawable *item = dpi->drawable; > RedDrawable *drawable = item->red_drawable; > > switch (drawable->type) { > case QXL_DRAW_FILL: > - red_marshall_qxl_draw_fill(worker, rcc, m, dpi); > + red_marshall_qxl_draw_fill(rcc, m, dpi); > break; > case QXL_DRAW_OPAQUE: > - red_marshall_qxl_draw_opaque(worker, rcc, m, dpi, FALSE); > + red_marshall_qxl_draw_opaque(rcc, m, dpi, FALSE); > break; > case QXL_DRAW_COPY: > - red_marshall_qxl_draw_copy(worker, rcc, m, dpi, FALSE); > + red_marshall_qxl_draw_copy(rcc, m, dpi, FALSE); > break; > case QXL_DRAW_TRANSPARENT: > - red_marshall_qxl_draw_transparent(worker, rcc, m, dpi); > + red_marshall_qxl_draw_transparent(rcc, m, dpi); > break; > case QXL_DRAW_ALPHA_BLEND: > - red_marshall_qxl_draw_alpha_blend(worker, rcc, m, dpi, FALSE); > + red_marshall_qxl_draw_alpha_blend(rcc, m, dpi, FALSE); > break; > case QXL_COPY_BITS: > - red_marshall_qxl_copy_bits(worker, rcc, m, dpi); > + red_marshall_qxl_copy_bits(rcc, m, dpi); > break; > case QXL_DRAW_BLEND: > - red_marshall_qxl_draw_blend(worker, rcc, m, dpi); > + red_marshall_qxl_draw_blend(rcc, m, dpi); > break; > case QXL_DRAW_BLACKNESS: > - red_marshall_qxl_draw_blackness(worker, rcc, m, dpi); > + red_marshall_qxl_draw_blackness(rcc, m, dpi); > break; > case QXL_DRAW_WHITENESS: > - red_marshall_qxl_draw_whiteness(worker, rcc, m, dpi); > + red_marshall_qxl_draw_whiteness(rcc, m, dpi); > break; > case QXL_DRAW_INVERS: > - red_marshall_qxl_draw_inverse(worker, rcc, m, item); > + red_marshall_qxl_draw_inverse(rcc, m, item); > break; > case QXL_DRAW_ROP3: > - red_marshall_qxl_draw_rop3(worker, rcc, m, dpi); > + red_marshall_qxl_draw_rop3(rcc, m, dpi); > break; > case QXL_DRAW_STROKE: > - red_marshall_qxl_draw_stroke(worker, rcc, m, dpi); > + red_marshall_qxl_draw_stroke(rcc, m, dpi); > break; > case QXL_DRAW_COMPOSITE: > - red_marshall_qxl_draw_composite(worker, rcc, m, dpi); > + red_marshall_qxl_draw_composite(rcc, m, dpi); > break; > case QXL_DRAW_TEXT: > - red_marshall_qxl_draw_text(worker, rcc, m, dpi); > + red_marshall_qxl_draw_text(rcc, m, dpi); > break; > default: > spice_error("invalid type"); > @@ -6993,9 +6697,9 @@ static inline void > marshall_qxl_drawable(RedChannelClient *rcc, > return; > } > if (!display_channel->enable_jpeg) > - red_marshall_qxl_drawable(display_channel->common.worker, rcc, m, > dpi); > + red_marshall_qxl_drawable(rcc, m, dpi); > else > - red_lossy_marshall_qxl_drawable(display_channel->common.worker, rcc, > m, dpi); > + red_lossy_marshall_qxl_drawable(rcc, m, dpi); > } > > static inline void red_marshall_inval_palette(RedChannelClient *rcc, > @@ -7551,24 +7255,6 @@ static inline void red_push(RedWorker *worker) > } > } > > -void red_show_tree(RedWorker *worker) > -{ > - int x; > - > - for (x = 0; x < NUM_SURFACES; ++x) { > - if (!worker->surfaces[x].context.canvas) > - continue; > - > - RingItem *it; > - Ring *ring = &worker->surfaces[x].current; > - RING_FOREACH(it, ring) { > - TreeItem *now = SPICE_CONTAINEROF(it, TreeItem, siblings_link); > - tree_item_dump(now); > - } > - > - } > -} > - > static void display_channel_client_on_disconnect(RedChannelClient *rcc) > { > DisplayChannel *display; > @@ -7623,7 +7309,7 @@ static void detach_and_stop_streams(DisplayChannel > *display) > Stream *stream = SPICE_CONTAINEROF(stream_item, Stream, link); > > detach_stream_gracefully(display, stream, NULL); > - stop_stream(display, stream); > + stream_stop(display, stream); > } > } > > @@ -7646,15 +7332,15 @@ static void red_migrate_display(DisplayChannel > *display, RedChannelClient *rcc) > } > > #ifdef USE_OPENGL > -static SpiceCanvas *create_ogl_context_common(RedWorker *worker, OGLCtx *ctx, > uint32_t width, > - uint32_t height, int32_t > stride, uint8_t depth) > +static SpiceCanvas *create_ogl_context_common(DisplayChannel *display, OGLCtx > *ctx, > + uint32_t width, uint32_t > height, > + int32_t stride, uint8_t depth) > { > - DisplayChannel *display = worker->display_channel; > SpiceCanvas *canvas; > > oglctx_make_current(ctx); > if (!(canvas = gl_canvas_create(width, height, depth, &display > ->image_cache.base, > - &worker->image_surfaces, NULL, NULL, > NULL))) { > + &display->image_surfaces, NULL, NULL, > NULL))) { > return NULL; > } > > @@ -7665,8 +7351,8 @@ static SpiceCanvas *create_ogl_context_common(RedWorker > *worker, OGLCtx *ctx, ui > return canvas; > } > > -static SpiceCanvas *create_ogl_pbuf_context(RedWorker *worker, uint32_t > width, uint32_t height, > - int32_t stride, uint8_t depth) > +static SpiceCanvas *create_ogl_pbuf_context(DisplayChannel *display, uint32_t > width, > + uint32_t height, int32_t stride, > uint8_t depth) > { > OGLCtx *ctx; > SpiceCanvas *canvas; > @@ -7675,7 +7361,7 @@ static SpiceCanvas *create_ogl_pbuf_context(RedWorker > *worker, uint32_t width, u > return NULL; > } > > - if (!(canvas = create_ogl_context_common(worker, ctx, width, height, > stride, depth))) { > + if (!(canvas = create_ogl_context_common(display, ctx, width, height, > stride, depth))) { > oglctx_destroy(ctx); > return NULL; > } > @@ -7683,8 +7369,9 @@ static SpiceCanvas *create_ogl_pbuf_context(RedWorker > *worker, uint32_t width, u > return canvas; > } > > -static SpiceCanvas *create_ogl_pixmap_context(RedWorker *worker, uint32_t > width, uint32_t height, > - int32_t stride, uint8_t depth) > { > +static SpiceCanvas *create_ogl_pixmap_context(DisplayChannel *display, > uint32_t width, > + uint32_t height, int32_t > stride, uint8_t depth) > +{ > OGLCtx *ctx; > SpiceCanvas *canvas; > > @@ -7692,7 +7379,7 @@ static SpiceCanvas *create_ogl_pixmap_context(RedWorker > *worker, uint32_t width, > return NULL; > } > > - if (!(canvas = create_ogl_context_common(worker, ctx, width, height, > stride, depth))) { > + if (!(canvas = create_ogl_context_common(display, ctx, width, height, > stride, depth))) { > oglctx_destroy(ctx); > return NULL; > } > @@ -7701,11 +7388,10 @@ static SpiceCanvas > *create_ogl_pixmap_context(RedWorker *worker, uint32_t width, > } > #endif > > -static inline void *create_canvas_for_surface(RedWorker *worker, RedSurface > *surface, > +static inline void *create_canvas_for_surface(DisplayChannel *display, > RedSurface *surface, > uint32_t renderer, uint32_t > width, uint32_t height, > int32_t stride, uint32_t > format, void *line_0) > { > - DisplayChannel *display = worker->display_channel; > SpiceCanvas *canvas; > > switch (renderer) { > @@ -7713,18 +7399,18 @@ static inline void > *create_canvas_for_surface(RedWorker *worker, RedSurface *sur > canvas = canvas_create_for_data(width, height, format, > line_0, stride, > &display->image_cache.base, > - &worker->image_surfaces, NULL, NULL, > NULL); > + &display->image_surfaces, NULL, NULL, > NULL); > surface->context.top_down = TRUE; > surface->context.canvas_draws_on_surface = TRUE; > return canvas; > #ifdef USE_OPENGL > case RED_RENDERER_OGL_PBUF: > - canvas = create_ogl_pbuf_context(worker, width, height, stride, > + canvas = create_ogl_pbuf_context(display, width, height, stride, > SPICE_SURFACE_FMT_DEPTH(format)); > surface->context.top_down = FALSE; > return canvas; > case RED_RENDERER_OGL_PIXMAP: > - canvas = create_ogl_pixmap_context(worker, width, height, stride, > + canvas = create_ogl_pixmap_context(display, width, height, stride, > SPICE_SURFACE_FMT_DEPTH(format)); > surface->context.top_down = FALSE; > return canvas; > @@ -7758,17 +7444,17 @@ static SurfaceCreateItem *get_surface_create_item( > > static inline void red_create_surface_item(DisplayChannelClient *dcc, int > surface_id) > { > + DisplayChannel *display = dcc ? DCC_TO_DC(dcc) : NULL; > RedSurface *surface; > SurfaceCreateItem *create; > - RedWorker *worker = dcc ? DCC_TO_WORKER(dcc) : NULL; > uint32_t flags = is_primary_surface(DCC_TO_DC(dcc), surface_id) ? > SPICE_SURFACE_FLAGS_PRIMARY : 0; > > /* don't send redundant create surface commands to client */ > - if (!dcc || worker->display_channel->common.during_target_migrate || > + if (!dcc || display->common.during_target_migrate || > dcc->surface_client_created[surface_id]) { > return; > } > - surface = &worker->surfaces[surface_id]; > + surface = &display->surfaces[surface_id]; > create = get_surface_create_item(RED_CHANNEL_CLIENT(dcc)->channel, > surface_id, surface->context.width, surface->context.height, > surface->context.format, flags); > @@ -7776,33 +7462,32 @@ static inline void > red_create_surface_item(DisplayChannelClient *dcc, int surfac > red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &create->pipe_item); > } > > -static void red_worker_create_surface_item(RedWorker *worker, int surface_id) > +static void red_worker_create_surface_item(DisplayChannel *display, int > surface_id) > { > DisplayChannelClient *dcc; > RingItem *item, *next; > > - FOREACH_DCC(worker->display_channel, item, next, dcc) { > + FOREACH_DCC(display, item, next, dcc) { > red_create_surface_item(dcc, surface_id); > } > } > > > -static void red_worker_push_surface_image(RedWorker *worker, int surface_id) > +static void red_worker_push_surface_image(DisplayChannel *display, int > surface_id) > { > DisplayChannelClient *dcc; > RingItem *item, *next; > > - FOREACH_DCC(worker->display_channel, item, next, dcc) { > + FOREACH_DCC(display, item, next, dcc) { > red_push_surface_image(dcc, surface_id); > } > } > > -static inline void red_create_surface(RedWorker *worker, uint32_t surface_id, > uint32_t width, > - uint32_t height, int32_t stride, > uint32_t format, > - void *line_0, int data_is_valid, int > send_client) > +static void red_create_surface(DisplayChannel *display, uint32_t surface_id, > uint32_t width, > + uint32_t height, int32_t stride, uint32_t > format, > + void *line_0, int data_is_valid, int > send_client) > { > - RedSurface *surface = &worker->surfaces[surface_id]; > - DisplayChannel*display = worker->display_channel; > + RedSurface *surface = &display->surfaces[surface_id]; > uint32_t i; > > spice_warn_if(surface->context.canvas); > @@ -7828,7 +7513,7 @@ static inline void red_create_surface(RedWorker *worker, > uint32_t surface_id, ui > region_init(&surface->draw_dirty_region); > surface->refs = 1; > if (display->renderer != RED_RENDERER_INVALID) { > - surface->context.canvas = create_canvas_for_surface(worker, surface, > display->renderer, > + surface->context.canvas = create_canvas_for_surface(display, surface, > display->renderer, > width, height, > stride, > surface > ->context.format, line_0); > if (!surface->context.canvas) { > @@ -7836,24 +7521,24 @@ static inline void red_create_surface(RedWorker > *worker, uint32_t surface_id, ui > } > > if (send_client) { > - red_worker_create_surface_item(worker, surface_id); > + red_worker_create_surface_item(display, surface_id); > if (data_is_valid) { > - red_worker_push_surface_image(worker, surface_id); > + red_worker_push_surface_image(display, surface_id); > } > } > return; > } > > for (i = 0; i < display->num_renderers; i++) { > - surface->context.canvas = create_canvas_for_surface(worker, surface, > display->renderers[i], > + surface->context.canvas = create_canvas_for_surface(display, surface, > display->renderers[i], > width, height, > stride, > surface > ->context.format, line_0); > if (surface->context.canvas) { //no need canvas check > display->renderer = display->renderers[i]; > if (send_client) { > - red_worker_create_surface_item(worker, surface_id); > + red_worker_create_surface_item(display, surface_id); > if (data_is_valid) { > - red_worker_push_surface_image(worker, surface_id); > + red_worker_push_surface_image(display, surface_id); > } > } > return; > @@ -8000,8 +7685,7 @@ static int > display_channel_client_wait_for_init(DisplayChannelClient *dcc) > > static void on_new_display_channel_client(DisplayChannelClient *dcc) > { > - DisplayChannel *display_channel = DCC_TO_DC(dcc); > - RedWorker *worker = display_channel->common.worker; > + DisplayChannel *display = DCC_TO_DC(dcc); > RedChannelClient *rcc = RED_CHANNEL_CLIENT(dcc); > > red_channel_client_push_set_ack(RED_CHANNEL_CLIENT(dcc)); > @@ -8014,8 +7698,8 @@ static void > on_new_display_channel_client(DisplayChannelClient *dcc) > return; > } > red_channel_client_ack_zero_messages_window(RED_CHANNEL_CLIENT(dcc)); > - if (worker->surfaces[0].context.canvas) { > - red_current_flush(worker, 0); > + if (display->surfaces[0].context.canvas) { > + red_current_flush(display, 0); > push_new_primary_surface(dcc); > red_push_surface_image(dcc, 0); > dcc_push_monitors_config(dcc); > @@ -8686,7 +8370,7 @@ static void > display_channel_client_release_item_before_push(DisplayChannelClient > } > case PIPE_ITEM_TYPE_STREAM_CREATE: { > StreamAgent *agent = SPICE_CONTAINEROF(item, StreamAgent, > create_item); > - display_stream_agent_unref(display, agent); > + stream_agent_unref(display, agent); > break; > } > case PIPE_ITEM_TYPE_STREAM_CLIP: > @@ -8694,7 +8378,7 @@ static void > display_channel_client_release_item_before_push(DisplayChannelClient > break; > case PIPE_ITEM_TYPE_STREAM_DESTROY: { > StreamAgent *agent = SPICE_CONTAINEROF(item, StreamAgent, > destroy_item); > - display_stream_agent_unref(display, agent); > + stream_agent_unref(display, agent); > break; > } > case PIPE_ITEM_TYPE_UPGRADE: > @@ -8749,20 +8433,7 @@ static void > display_channel_release_item(RedChannelClient *rcc, PipeItem *item, > } > } > > -static void init_streams(DisplayChannel *display) > -{ > - int i; > - > - ring_init(&display->streams); > - display->free_streams = NULL; > - for (i = 0; i < NUM_STREAMS; i++) { > - Stream *stream = &display->streams_buf[i]; > - ring_item_init(&stream->link); > - display_stream_free(display, stream); > - } > -} > - > -static void display_channel_create(RedWorker *worker, int migrate) > +static void display_channel_create(RedWorker *worker, int migrate, uint32_t > n_surfaces) > { > DisplayChannel *display_channel; > ChannelCbs cbs = { > @@ -8804,13 +8475,16 @@ static void display_channel_create(RedWorker *worker, > int migrate) > stat_compress_init(&display_channel->jpeg_alpha_stat, > jpeg_alpha_stat_name); > stat_compress_init(&display_channel->lz4_stat, lz4_stat_name); > > + display_channel->n_surfaces = n_surfaces; > display_channel->num_renderers = num_renderers; > memcpy(display_channel->renderers, renderers, sizeof(display_channel > ->renderers)); > display_channel->renderer = RED_RENDERER_INVALID; > - init_streams(display_channel); > - image_cache_init(&display_channel->image_cache); > + > ring_init(&display_channel->current_list); > + image_surface_init(display_channel); > drawables_init(display_channel); > + image_cache_init(&display_channel->image_cache); > + stream_init(display_channel); > } > > static void guest_set_client_capabilities(RedWorker *worker) > @@ -8943,14 +8617,13 @@ static void red_connect_cursor(RedWorker *worker, > RedClient *client, RedsStream > > // TODO: why do we check for context.canvas? defer this to after display > cc is connected > // and test it's canvas? this is just a test to see if there is an active > renderer? > - if (worker->surfaces[0].context.canvas) > + if (display_channel_surface_has_canvas(worker->display_channel, 0)) > cursor_channel_init(channel, ccc); > } > > static void surface_dirty_region_to_rects(RedSurface *surface, > QXLRect *qxl_dirty_rects, > - uint32_t num_dirty_rects, > - int clear_dirty_region) > + uint32_t num_dirty_rects) > { > QRegion *surface_dirty_region; > SpiceRect *dirty_rects; > @@ -8959,9 +8632,6 @@ static void surface_dirty_region_to_rects(RedSurface > *surface, > surface_dirty_region = &surface->draw_dirty_region; > dirty_rects = spice_new0(SpiceRect, num_dirty_rects); > region_ret_rects(surface_dirty_region, dirty_rects, num_dirty_rects); > - if (clear_dirty_region) { > - region_clear(surface_dirty_region); > - } > for (i = 0; i < num_dirty_rects; i++) { > qxl_dirty_rects[i].top = dirty_rects[i].top; > qxl_dirty_rects[i].left = dirty_rects[i].left; > @@ -8971,67 +8641,60 @@ static void surface_dirty_region_to_rects(RedSurface > *surface, > free(dirty_rects); > } > > -static void handle_dev_update_async(void *opaque, void *payload) > +void display_channel_update(DisplayChannel *display, > + uint32_t surface_id, const QXLRect *area, > uint32_t clear_dirty, > + QXLRect **qxl_dirty_rects, uint32_t > *num_dirty_rects) > { > - RedWorker *worker = opaque; > - RedWorkerMessageUpdateAsync *msg = payload; > SpiceRect rect; > - QXLRect *qxl_dirty_rects; > - uint32_t num_dirty_rects; > RedSurface *surface; > - uint32_t surface_id = msg->surface_id; > - QXLRect qxl_area = msg->qxl_area; > - uint32_t clear_dirty_region = msg->clear_dirty_region; > > - red_get_rect_ptr(&rect, &qxl_area); > - flush_display_commands(worker); > + spice_return_if_fail(validate_surface(display, surface_id)); > > - spice_assert(worker->running); > + red_get_rect_ptr(&rect, area); > + red_update_area(display, &rect, surface_id); > > - VALIDATE_SURFACE_RET(worker, surface_id); > - red_update_area(worker, &rect, surface_id); > - if (!worker->qxl->st->qif->update_area_complete) { > - return; > - } > - surface = &worker->surfaces[surface_id]; > - num_dirty_rects = pixman_region32_n_rects(&surface->draw_dirty_region); > - if (num_dirty_rects == 0) { > - return; > + surface = &display->surfaces[surface_id]; > + if (!*qxl_dirty_rects) { > + *num_dirty_rects = pixman_region32_n_rects(&surface > ->draw_dirty_region); > + *qxl_dirty_rects = spice_new0(QXLRect, *num_dirty_rects); > } > - qxl_dirty_rects = spice_new0(QXLRect, num_dirty_rects); > - surface_dirty_region_to_rects(surface, qxl_dirty_rects, num_dirty_rects, > - clear_dirty_region); > - worker->qxl->st->qif->update_area_complete(worker->qxl, surface_id, > - qxl_dirty_rects, num_dirty_rects); > - free(qxl_dirty_rects); > + > + surface_dirty_region_to_rects(surface, *qxl_dirty_rects, > *num_dirty_rects); > + if (clear_dirty) > + region_clear(&surface->draw_dirty_region); > } > > -static void handle_dev_update(void *opaque, void *payload) > +static void handle_dev_update_async(void *opaque, void *payload) > { > RedWorker *worker = opaque; > - RedWorkerMessageUpdate *msg = payload; > - SpiceRect *rect; > - RedSurface *surface; > - uint32_t surface_id = msg->surface_id; > - const QXLRect *qxl_area = msg->qxl_area; > - uint32_t num_dirty_rects = msg->num_dirty_rects; > - QXLRect *qxl_dirty_rects = msg->qxl_dirty_rects; > - uint32_t clear_dirty_region = msg->clear_dirty_region; > + RedWorkerMessageUpdateAsync *msg = payload; > + QXLRect *qxl_dirty_rects = NULL; > + uint32_t num_dirty_rects = 0; > > - VALIDATE_SURFACE_RET(worker, surface_id); > + spice_return_if_fail(worker->running); > + spice_return_if_fail(worker->qxl->st->qif->update_area_complete); > > - rect = spice_new0(SpiceRect, 1); > - surface = &worker->surfaces[surface_id]; > - red_get_rect_ptr(rect, qxl_area); > flush_display_commands(worker); > + display_channel_update(worker->display_channel, > + msg->surface_id, &msg->qxl_area, msg > ->clear_dirty_region, > + &qxl_dirty_rects, &num_dirty_rects); > > - spice_assert(worker->running); > + worker->qxl->st->qif->update_area_complete(worker->qxl, msg->surface_id, > + qxl_dirty_rects, > num_dirty_rects); > + free(qxl_dirty_rects); > +} > > - red_update_area(worker, rect, surface_id); > - free(rect); > +static void handle_dev_update(void *opaque, void *payload) > +{ > + RedWorker *worker = opaque; > + RedWorkerMessageUpdate *msg = payload; > + > + spice_return_if_fail(worker->running); > > - surface_dirty_region_to_rects(surface, qxl_dirty_rects, num_dirty_rects, > - clear_dirty_region); > + flush_display_commands(worker); > + display_channel_update(worker->display_channel, > + msg->surface_id, msg->qxl_area, msg > ->clear_dirty_region, > + &msg->qxl_dirty_rects, &msg->num_dirty_rects); > } > > static void handle_dev_del_memslot(void *opaque, void *payload) > @@ -9044,32 +8707,18 @@ static void handle_dev_del_memslot(void *opaque, void > *payload) > red_memslot_info_del_slot(&worker->mem_slots, slot_group_id, slot_id); > } > > -/* TODO: destroy_surface_wait, dev_destroy_surface_wait - confusing. one > asserts > - * surface_id == 0, maybe move the assert upward and merge the two functions? > */ > -static inline void destroy_surface_wait(RedWorker *worker, int surface_id) > +void display_channel_destroy_surface_wait(DisplayChannel *display, int > surface_id) > { > - VALIDATE_SURFACE_RET(worker, surface_id); > - if (!worker->surfaces[surface_id].context.canvas) { > + VALIDATE_SURFACE_RET(display, surface_id); > + if (!display->surfaces[surface_id].context.canvas) > return; > - } > > - red_handle_depends_on_target_surface(worker, surface_id); > - /* note that red_handle_depends_on_target_surface must be called before > red_current_clear. > + red_handle_depends_on_target_surface(display, surface_id); > + /* note that red_handle_depends_on_target_surface must be called before > current_clear. > otherwise "current" will hold items that other drawables may depend > on, and then > - red_current_clear will remove them from the pipe. */ > - red_current_clear(worker, surface_id); > - red_clear_surface_drawables_from_pipes(worker, surface_id, TRUE); > -} > - > -static void dev_destroy_surface_wait(RedWorker *worker, uint32_t surface_id) > -{ > - spice_assert(surface_id == 0); > - > - flush_all_qxl_commands(worker); > - > - if (worker->surfaces[0].context.canvas) { > - destroy_surface_wait(worker, 0); > - } > + current_clear will remove them from the pipe. */ > + current_clear(display, surface_id); > + red_clear_surface_drawables_from_pipes(display, surface_id, TRUE); > } > > static void handle_dev_destroy_surface_wait(void *opaque, void *payload) > @@ -9077,48 +8726,47 @@ static void handle_dev_destroy_surface_wait(void > *opaque, void *payload) > RedWorkerMessageDestroySurfaceWait *msg = payload; > RedWorker *worker = opaque; > > - dev_destroy_surface_wait(worker, msg->surface_id); > + spice_return_if_fail(msg->surface_id == 0); > + > + flush_all_qxl_commands(worker); > + display_channel_destroy_surface_wait(worker->display_channel, msg > ->surface_id); > } > > /* called upon device reset */ > > /* TODO: split me*/ > -static inline void dev_destroy_surfaces(RedWorker *worker) > +void display_channel_destroy_surfaces(DisplayChannel *display) > { > - DisplayChannel *display = worker->display_channel; > int i; > > spice_debug(NULL); > - flush_all_qxl_commands(worker); > //to handle better > for (i = 0; i < NUM_SURFACES; ++i) { > - if (worker->surfaces[i].context.canvas) { > - destroy_surface_wait(worker, i); > - if (worker->surfaces[i].context.canvas) { > - red_surface_unref(worker, i); > + if (display->surfaces[i].context.canvas) { > + display_channel_destroy_surface_wait(display, i); > + if (display->surfaces[i].context.canvas) { > + display_channel_surface_unref(display, i); > } > - spice_assert(!worker->surfaces[i].context.canvas); > + spice_assert(!display->surfaces[i].context.canvas); > } > } > - spice_assert(ring_is_empty(&display->streams)); > + spice_warn_if_fail(ring_is_empty(&display->streams)); > > - if (display_is_connected(worker)) { > - red_channel_pipes_add_type(RED_CHANNEL(worker->display_channel), > - PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE); > - red_pipes_add_verb(RED_CHANNEL(worker->display_channel), > - SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL); > + if (red_channel_is_connected(RED_CHANNEL(display))) { > + red_channel_pipes_add_type(RED_CHANNEL(display), > PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE); > + red_pipes_add_verb(RED_CHANNEL(display), > SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL); > } > > - red_display_clear_glz_drawables(worker->display_channel); > - > - cursor_channel_reset(worker->cursor_channel); > + red_display_clear_glz_drawables(display); > } > > static void handle_dev_destroy_surfaces(void *opaque, void *payload) > { > RedWorker *worker = opaque; > > - dev_destroy_surfaces(worker); > + flush_all_qxl_commands(worker); > + display_channel_destroy_surfaces(worker->display_channel); > + cursor_channel_reset(worker->cursor_channel); > } > > static void display_update_monitors_config(DisplayChannel *display, > @@ -9143,13 +8791,12 @@ static void red_worker_push_monitors_config(RedWorker > *worker) > } > } > > -static void set_monitors_config_to_primary(RedWorker *worker) > +static void set_monitors_config_to_primary(DisplayChannel *display) > { > - DrawContext *context = &worker->surfaces[0].context; > - DisplayChannel *display = worker->display_channel; > + DrawContext *context = &display->surfaces[0].context; > QXLHead head = { 0, }; > > - spice_return_if_fail(worker->surfaces[0].context.canvas); > + spice_return_if_fail(display->surfaces[0].context.canvas); > > if (display->monitors_config) > monitors_config_unref(display->monitors_config); > @@ -9162,6 +8809,7 @@ static void set_monitors_config_to_primary(RedWorker > *worker) > static void dev_create_primary_surface(RedWorker *worker, uint32_t > surface_id, > QXLDevSurfaceCreate surface) > { > + DisplayChannel *display = worker->display_channel; > uint8_t *line_0; > int error; > > @@ -9186,9 +8834,9 @@ static void dev_create_primary_surface(RedWorker > *worker, uint32_t surface_id, > line_0 -= (int32_t)(surface.stride * (surface.height -1)); > } > > - red_create_surface(worker, 0, surface.width, surface.height, > surface.stride, surface.format, > + red_create_surface(display, 0, surface.width, surface.height, > surface.stride, surface.format, > line_0, surface.flags & QXL_SURF_FLAG_KEEP_DATA, > TRUE); > - set_monitors_config_to_primary(worker); > + set_monitors_config_to_primary(display); > > if (display_is_connected(worker) && !worker->display_channel > ->common.during_target_migrate) { > /* guest created primary, so it will (hopefully) send a > monitors_config > @@ -9212,25 +8860,25 @@ static void handle_dev_create_primary_surface(void > *opaque, void *payload) > dev_create_primary_surface(worker, msg->surface_id, msg->surface); > } > > -static void dev_destroy_primary_surface(RedWorker *worker, uint32_t > surface_id) > +static void destroy_primary_surface(RedWorker *worker, uint32_t surface_id) > { > DisplayChannel *display = worker->display_channel; > > - VALIDATE_SURFACE_RET(worker, surface_id); > + VALIDATE_SURFACE_RET(display, surface_id); > spice_warn_if(surface_id != 0); > > spice_debug(NULL); > - if (!worker->surfaces[surface_id].context.canvas) { > + if (!display->surfaces[surface_id].context.canvas) { > spice_warning("double destroy of primary surface"); > return; > } > > flush_all_qxl_commands(worker); > - dev_destroy_surface_wait(worker, 0); > - red_surface_unref(worker, 0); > - spice_warn_if_fail(ring_is_empty(&display->streams)); > + display_channel_destroy_surface_wait(display, 0); > + display_channel_surface_unref(display, 0); > > - spice_assert(!worker->surfaces[surface_id].context.canvas); > + spice_warn_if_fail(ring_is_empty(&display->streams)); > + spice_warn_if_fail(!display->surfaces[surface_id].context.canvas); > > cursor_channel_reset(worker->cursor_channel); > } > @@ -9241,7 +8889,7 @@ static void handle_dev_destroy_primary_surface(void > *opaque, void *payload) > RedWorker *worker = opaque; > uint32_t surface_id = msg->surface_id; > > - dev_destroy_primary_surface(worker, surface_id); > + destroy_primary_surface(worker, surface_id); > } > > static void handle_dev_destroy_primary_surface_async(void *opaque, void > *payload) > @@ -9250,16 +8898,16 @@ static void > handle_dev_destroy_primary_surface_async(void *opaque, void *payload > RedWorker *worker = opaque; > uint32_t surface_id = msg->surface_id; > > - dev_destroy_primary_surface(worker, surface_id); > + destroy_primary_surface(worker, surface_id); > } > > -static void flush_all_surfaces(RedWorker *worker) > +static void flush_all_surfaces(DisplayChannel *display) > { > int x; > > for (x = 0; x < NUM_SURFACES; ++x) { > - if (worker->surfaces[x].context.canvas) { > - red_current_flush(worker, x); > + if (display->surfaces[x].context.canvas) { > + red_current_flush(display, x); > } > } > } > @@ -9267,7 +8915,7 @@ static void flush_all_surfaces(RedWorker *worker) > static void dev_flush_surfaces(RedWorker *worker) > { > flush_all_qxl_commands(worker); > - flush_all_surfaces(worker); > + flush_all_surfaces(worker->display_channel); > } > > static void handle_dev_flush_surfaces_async(void *opaque, void *payload) > @@ -9285,7 +8933,7 @@ static void handle_dev_stop(void *opaque, void *payload) > spice_assert(worker->running); > worker->running = FALSE; > red_display_clear_glz_drawables(worker->display_channel); > - flush_all_surfaces(worker); > + flush_all_surfaces(worker->display_channel); > /* todo: when the waiting is expected to take long (slow connection and > * overloaded pipe), don't wait, and in case of migration, > * purge the pipe, send destroy_all_surfaces > @@ -9414,14 +9062,16 @@ static void handle_dev_destroy_surface_wait_async(void > *opaque, void *payload) > RedWorkerMessageDestroySurfaceWaitAsync *msg = payload; > RedWorker *worker = opaque; > > - dev_destroy_surface_wait(worker, msg->surface_id); > + display_channel_destroy_surface_wait(worker->display_channel, msg > ->surface_id); > } > > static void handle_dev_destroy_surfaces_async(void *opaque, void *payload) > { > RedWorker *worker = opaque; > > - dev_destroy_surfaces(worker); > + flush_all_qxl_commands(worker); > + display_channel_destroy_surfaces(worker->display_channel); > + cursor_channel_reset(worker->cursor_channel); > } > > static void handle_dev_create_primary_surface_async(void *opaque, void > *payload) > @@ -9935,7 +9585,6 @@ RedWorker* red_worker_new(QXLInstance *qxl, > RedDispatcher *red_dispatcher) > worker->jpeg_state = jpeg_state; > worker->zlib_glz_state = zlib_glz_state; > worker->driver_cap_monitors_config = 0; > - image_surface_init(worker); > stat_init(&worker->add_stat, add_stat_name); > stat_init(&worker->exclude_stat, exclude_stat_name); > stat_init(&worker->__exclude_stat, __exclude_stat_name); > @@ -9964,7 +9613,6 @@ RedWorker* red_worker_new(QXLInstance *qxl, > RedDispatcher *red_dispatcher) > init_info.internal_groupslot_id); > > spice_warn_if(init_info.n_surfaces > NUM_SURFACES); > - worker->n_surfaces = init_info.n_surfaces; > > red_init_quic(worker); > red_init_lz(worker); > @@ -9977,7 +9625,7 @@ RedWorker* red_worker_new(QXLInstance *qxl, > RedDispatcher *red_dispatcher) > > worker->cursor_channel = cursor_channel_new(worker); > // TODO: handle seemless migration. Temp, setting migrate to FALSE > - display_channel_create(worker, FALSE); > + display_channel_create(worker, FALSE, init_info.n_surfaces); > > return worker; > } > diff --git a/server/red_worker.h b/server/red_worker.h > index 2995b8f..3604dfd 100644 > --- a/server/red_worker.h > +++ b/server/red_worker.h > @@ -22,6 +22,7 @@ > #include <errno.h> > #include "red_common.h" > #include "red_dispatcher.h" > +#include "red_parse_qxl.h" > > typedef struct RedWorker RedWorker; > > @@ -108,6 +109,7 @@ bool red_worker_run(RedWorker *worker); > QXLInstance* red_worker_get_qxl(RedWorker *worker); > RedChannel* red_worker_get_cursor_channel(RedWorker *worker); > RedChannel* red_worker_get_display_channel(RedWorker *worker); > +void red_worker_print_stats(RedWorker *worker); > > RedChannel *red_worker_new_channel(RedWorker *worker, int size, > const char *name, > diff --git a/server/stream.c b/server/stream.c > index 6203f3d..0d8cbd9 100644 > --- a/server/stream.c > +++ b/server/stream.c > @@ -53,6 +53,76 @@ void stream_agent_stats_print(StreamAgent *agent) > #endif > } > > +void stream_stop(DisplayChannel *display, Stream *stream) > +{ > + DisplayChannelClient *dcc; > + RingItem *item, *next; > + > + spice_return_if_fail(ring_item_is_linked(&stream->link)); > + spice_return_if_fail(!stream->current); > + > + spice_debug("stream %d", get_stream_id(display, stream)); > + FOREACH_DCC(display, item, next, dcc) { > + StreamAgent *stream_agent; > + > + stream_agent = &dcc->stream_agents[get_stream_id(display, stream)]; > + region_clear(&stream_agent->vis_region); > + region_clear(&stream_agent->clip); > + spice_assert(!pipe_item_is_linked(&stream_agent->destroy_item)); > + if (stream_agent->mjpeg_encoder && dcc > ->use_mjpeg_encoder_rate_control) { > + uint64_t stream_bit_rate = > mjpeg_encoder_get_bit_rate(stream_agent->mjpeg_encoder); > + > + if (stream_bit_rate > dcc->streams_max_bit_rate) { > + spice_debug("old max-bit-rate=%.2f new=%.2f", > + dcc->streams_max_bit_rate / 8.0 / 1024.0 / 1024.0, > + stream_bit_rate / 8.0 / 1024.0 / 1024.0); > + dcc->streams_max_bit_rate = stream_bit_rate; > + } > + } > + stream->refs++; > + red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &stream_agent > ->destroy_item); > + stream_agent_stats_print(stream_agent); > + } > + display->streams_size_total -= stream->width * stream->height; > + ring_remove(&stream->link); > + stream_unref(display, stream); > +} > + > +static void stream_free(DisplayChannel *display, Stream *stream) > +{ > + stream->next = display->free_streams; > + display->free_streams = stream; > +} > + > +void stream_init(DisplayChannel *display) > +{ > + int i; > + > + ring_init(&display->streams); > + display->free_streams = NULL; > + for (i = 0; i < NUM_STREAMS; i++) { > + Stream *stream = &display->streams_buf[i]; > + ring_item_init(&stream->link); > + stream_free(display, stream); > + } > +} > + > +void stream_unref(DisplayChannel *display, Stream *stream) > +{ > + if (--stream->refs != 0) > + return; > + > + spice_warn_if_fail(!ring_item_is_linked(&stream->link)); > + > + stream_free(display, stream); > + display->stream_count--; > +} > + > +void stream_agent_unref(DisplayChannel *display, StreamAgent *agent) > +{ > + stream_unref(display, agent->stream); > +} > + > StreamClipItem *stream_clip_item_new(DisplayChannelClient* dcc, StreamAgent > *agent) > { > StreamClipItem *item = spice_new(StreamClipItem, 1); > diff --git a/server/stream.h b/server/stream.h > index f77fa96..4704937 100644 > --- a/server/stream.h > +++ b/server/stream.h > @@ -40,6 +40,9 @@ > #define RED_STREAM_DEFAULT_HIGH_START_BIT_RATE (10 * 1024 * 1024) // 10Mbps > #define RED_STREAM_DEFAULT_LOW_START_BIT_RATE (2.5 * 1024 * 1024) // 2.5Mbps > > +/* move back to display_channel once struct private */ > +typedef struct DisplayChannel DisplayChannel; > + > typedef struct Stream Stream; > > typedef struct StreamActivateReportItem { > @@ -132,6 +135,13 @@ struct Stream { > uint32_t input_fps; > }; > > -void stream_agent_stats_print(StreamAgent *agent); > +void stream_init > (DisplayChannel *display); > +void stream_stop > (DisplayChannel *display, > + Stream > *stream); > +void stream_unref > (DisplayChannel *display, > + Stream > *stream); > +void stream_agent_unref > (DisplayChannel *display, > + > StreamAgent *agent); > +void stream_agent_stats_print > (StreamAgent *agent); > > #endif /* STREAM_H */ > diff --git a/server/tree.h b/server/tree.h > index 6e83f7a..6249c28 100644 > --- a/server/tree.h > +++ b/server/tree.h > @@ -73,6 +73,12 @@ struct DrawItem { > #define IS_DRAW_ITEM(item) ((item)->type == TREE_ITEM_TYPE_DRAWABLE) > #define DRAW_ITEM(item) ((DrawItem*)(item)) > > +static inline int is_opaque_item(TreeItem *item) > +{ > + return item->type == TREE_ITEM_TYPE_CONTAINER || > + (IS_DRAW_ITEM(item) && ((DrawItem *)item)->effect == > QXL_EFFECT_OPAQUE); > +} > + > void tree_item_dump (TreeItem *item); > Shadow* shadow_new (DrawItem *item, const > SpicePoint *delta); > Container* container_new (DrawItem *item); _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel