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 | 11 +- server/tree.h | 6 + 7 files changed, 793 insertions(+), 844 deletions(-) diff --git a/server/display-channel.c b/server/display-channel.c index edef3c0..39330b4 100644 --- a/server/display-channel.c +++ b/server/display-channel.c @@ -301,3 +301,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 f981d27..5202a2f 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 + 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 0be5c29..8f6ef95 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; - #define NUM_CURSORS 100 typedef struct RedWorker { @@ -342,10 +319,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; @@ -406,7 +379,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) { @@ -417,11 +390,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 inline void display_channel_stream_maintenance(DisplayChannel *display, Drawable *candidate, Drawable *sect); static inline void display_begin_send_message(RedChannelClient *rcc); @@ -437,22 +410,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) \ @@ -465,38 +425,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); } @@ -561,40 +495,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) @@ -640,14 +540,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; @@ -656,8 +548,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; @@ -675,15 +567,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; } @@ -696,7 +588,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) { @@ -708,7 +600,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); } } @@ -718,7 +610,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); } @@ -743,13 +635,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); } } @@ -766,7 +658,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; @@ -783,13 +675,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) { @@ -813,8 +705,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; @@ -929,59 +819,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) { @@ -1030,7 +867,7 @@ static void drawable_unref_surfaces_dest(DisplayChannel *display, Drawable *draw if (surface_id == -1) { continue; } - red_surface_unref(COMMON_CHANNEL(display)->worker, surface_id); + display_channel_surface_unref(display, surface_id); } } @@ -1067,7 +904,7 @@ void display_channel_drawable_unref(DisplayChannel *display, Drawable *drawable) drawable_remove_dependencies(display, drawable); drawable_unref_surfaces_dest(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; @@ -1093,7 +930,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); @@ -1101,7 +938,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; @@ -1112,7 +949,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; } } @@ -1136,12 +973,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; @@ -1150,15 +987,13 @@ static void red_flush_source_surfaces(RedWorker *worker, Drawable *drawable) surface_id = drawable->surfaces_dest[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); @@ -1168,23 +1003,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; @@ -1195,7 +1031,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; @@ -1209,13 +1045,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); } } @@ -1300,14 +1137,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)); } @@ -1347,8 +1184,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 @@ -1387,7 +1224,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); } @@ -1418,8 +1255,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); @@ -1439,12 +1276,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); } @@ -1477,19 +1314,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); @@ -1497,87 +1328,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) { @@ -1666,9 +1416,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); } @@ -1785,7 +1535,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); } } } @@ -2324,9 +2074,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; @@ -2346,14 +2095,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); @@ -2362,18 +2111,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) { @@ -2382,7 +2131,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); @@ -2392,7 +2141,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); } } @@ -2404,15 +2153,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; @@ -2475,7 +2224,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 @@ -2504,7 +2253,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; } @@ -2516,7 +2265,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; @@ -2526,7 +2275,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; @@ -2538,7 +2287,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; } @@ -2569,24 +2318,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); @@ -2603,9 +2352,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; @@ -2631,11 +2379,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 { @@ -2691,7 +2439,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) { @@ -2719,33 +2467,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; @@ -2797,7 +2544,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; @@ -2823,7 +2570,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 @@ -2842,9 +2589,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; @@ -2860,12 +2606,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; } @@ -2876,19 +2621,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->surfaces_dest[x] != -1) { - VALIDATE_SURFACE_RETVAL(worker, red_drawable->surfaces_dest[x], NULL) + VALIDATE_SURFACE_RETVAL(display, red_drawable->surfaces_dest[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; } @@ -2913,24 +2658,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; @@ -2940,22 +2685,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->surfaces_dest[x] != drawable->surface_id) { - add_to_surface_dependency(worker, drawable->surfaces_dest[x], + add_to_surface_dependency(display, drawable->surfaces_dest[x], &drawable->depend_items[x], drawable); if (drawable->surfaces_dest[x] == 0) { @@ -2970,7 +2714,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; @@ -2981,7 +2725,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++; } } @@ -3000,7 +2744,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); @@ -3012,13 +2756,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; @@ -3028,38 +2773,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: { @@ -3075,7 +2818,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 @@ -3089,13 +2832,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"); @@ -3108,31 +2851,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); @@ -3263,17 +3005,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; @@ -3295,10 +3037,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; @@ -3309,7 +3050,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 @@ -3361,22 +3102,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; @@ -3391,7 +3131,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; @@ -3409,7 +3149,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; } @@ -3420,12 +3160,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) @@ -3544,11 +3284,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; @@ -3622,7 +3362,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) { @@ -3634,12 +3374,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. @@ -3648,8 +3388,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; @@ -3709,15 +3448,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; } @@ -5144,8 +4879,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; @@ -5168,7 +4902,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 @@ -5180,7 +4914,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 { @@ -5197,13 +4931,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; @@ -5290,16 +5024,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); } @@ -5332,10 +5066,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) { @@ -5425,7 +5159,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; @@ -5536,8 +5270,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) @@ -5569,8 +5302,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) { @@ -5625,15 +5357,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; @@ -5646,7 +5378,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)) { @@ -5658,7 +5390,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); } } @@ -5681,11 +5413,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); } @@ -5695,10 +5427,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; @@ -5723,13 +5454,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; @@ -5756,9 +5486,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]; @@ -5776,18 +5506,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; @@ -5815,13 +5544,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; @@ -5851,14 +5579,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]; @@ -5876,19 +5604,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; @@ -5908,13 +5635,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; @@ -5924,23 +5650,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; @@ -5955,10 +5680,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; @@ -5969,7 +5693,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]; @@ -5978,16 +5702,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); @@ -6009,10 +5732,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); @@ -6024,7 +5746,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; @@ -6033,14 +5755,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; @@ -6053,10 +5774,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); @@ -6067,7 +5787,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; @@ -6080,14 +5800,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); @@ -6109,10 +5827,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); @@ -6129,7 +5846,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]; @@ -6147,15 +5864,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; @@ -6173,25 +5889,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; @@ -6209,25 +5923,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; @@ -6244,18 +5956,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); @@ -6282,10 +5992,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); @@ -6308,8 +6017,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]; @@ -6333,15 +6042,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); @@ -6364,8 +6072,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) { @@ -6390,8 +6097,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]; @@ -6416,15 +6123,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); @@ -6447,10 +6153,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); @@ -6479,7 +6184,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]; @@ -6498,15 +6203,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); @@ -6531,10 +6235,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); @@ -6571,7 +6274,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]; @@ -6594,111 +6297,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"); @@ -6997,9 +6701,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, @@ -7555,24 +7259,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; @@ -7627,7 +7313,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); } } @@ -7650,15 +7336,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; } @@ -7669,8 +7355,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; @@ -7679,7 +7365,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; } @@ -7687,8 +7373,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; @@ -7696,7 +7383,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; } @@ -7705,11 +7392,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) { @@ -7717,18 +7403,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; @@ -7762,17 +7448,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); @@ -7780,33 +7466,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); @@ -7832,7 +7517,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) { @@ -7840,24 +7525,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; @@ -8004,8 +7689,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)); @@ -8018,8 +7702,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); @@ -8690,7 +8374,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: @@ -8698,7 +8382,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: @@ -8753,20 +8437,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 = { @@ -8808,13 +8479,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) @@ -8947,14 +8621,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; @@ -8963,9 +8636,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; @@ -8975,67 +8645,60 @@ static void surface_dirty_region_to_rects(RedSurface *surface, free(dirty_rects); } -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); } -void handle_dev_update(void *opaque, void *payload) +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); +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 dev_add_memslot(RedWorker *worker, QXLDevMemSlot mem_slot) @@ -9066,32 +8729,18 @@ 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); } void handle_dev_destroy_surface_wait(void *opaque, void *payload) @@ -9099,48 +8748,47 @@ 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); } 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, @@ -9165,13 +8813,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); @@ -9184,6 +8831,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; @@ -9208,9 +8856,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 @@ -9234,25 +8882,25 @@ 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); } @@ -9263,7 +8911,7 @@ 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); } void handle_dev_destroy_primary_surface_async(void *opaque, void *payload) @@ -9272,16 +8920,16 @@ 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); } } } @@ -9289,7 +8937,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); } void handle_dev_flush_surfaces(void *opaque, void *payload) @@ -9314,7 +8962,7 @@ 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 @@ -9443,14 +9091,16 @@ 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); } 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); } void handle_dev_create_primary_surface_async(void *opaque, void *payload) @@ -9946,7 +9596,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); @@ -9975,7 +9624,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); @@ -9988,7 +9636,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 d2f2206..45fb55b 100644 --- a/server/red_worker.h +++ b/server/red_worker.h @@ -23,6 +23,7 @@ #include <glib.h> #include "red_common.h" #include "red_dispatcher.h" +#include "red_parse_qxl.h" typedef struct RedWorker RedWorker; @@ -109,6 +110,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 5500414..e8d4f75 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 { @@ -133,7 +136,13 @@ struct Stream { uint32_t input_fps; }; - +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); -- 2.4.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel