diff options
author | Marc-André Lureau <marcandre.lureau@gmail.com> | 2013-09-27 17:23:02 +0200 |
---|---|---|
committer | Christophe Fergeau <cfergeau@redhat.com> | 2014-02-13 17:38:00 +0100 |
commit | 63bed98ce194be31caeee967bf522195a3192695 (patch) | |
tree | 9328f5146a51dd105836f4b144ca773605c224bd | |
parent | 52d941308bd9d8cfcf499008e52990fc81fa066a (diff) |
worker: move display_channel_new
-rw-r--r-- | server/dcc.c | 25 | ||||
-rw-r--r-- | server/dcc.h | 3 | ||||
-rw-r--r-- | server/display_channel.c | 152 | ||||
-rw-r--r-- | server/display_channel.h | 19 | ||||
-rw-r--r-- | server/red_worker.c | 212 | ||||
-rw-r--r-- | server/red_worker.h | 1 |
6 files changed, 214 insertions, 198 deletions
diff --git a/server/dcc.c b/server/dcc.c index 7b80a484..120fc144 100644 --- a/server/dcc.c +++ b/server/dcc.c @@ -335,6 +335,31 @@ void dcc_start(DisplayChannelClient *dcc) } } +static void dcc_destroy_stream_agents(DisplayChannelClient *dcc) +{ + int i; + + for (i = 0; i < NUM_STREAMS; i++) { + StreamAgent *agent = &dcc->stream_agents[i]; + region_destroy(&agent->vis_region); + region_destroy(&agent->clip); + if (agent->mjpeg_encoder) { + mjpeg_encoder_destroy(agent->mjpeg_encoder); + agent->mjpeg_encoder = NULL; + } + } +} + +void dcc_stop(DisplayChannelClient *dcc) +{ + pixmap_cache_unref(dcc->pixmap_cache); + dcc->pixmap_cache = NULL; + dcc_release_glz(dcc); + dcc_palette_cache_reset(dcc); + free(dcc->send_data.stream_outbuf); + free(dcc->send_data.free_list.res); + dcc_destroy_stream_agents(dcc); +} void dcc_stream_agent_clip(DisplayChannelClient* dcc, StreamAgent *agent) { diff --git a/server/dcc.h b/server/dcc.h index 59e4b01f..b5a57e58 100644 --- a/server/dcc.h +++ b/server/dcc.h @@ -141,6 +141,7 @@ DisplayChannelClient* dcc_new (DisplayCha spice_wan_compression_t jpeg_state, spice_wan_compression_t zlib_glz_state); void dcc_start (DisplayChannelClient *dcc); +void dcc_stop (DisplayChannelClient *dcc); int dcc_handle_message (RedChannelClient *rcc, uint32_t size, uint16_t type, void *msg); @@ -177,6 +178,8 @@ void dcc_add_drawable_after (DisplayCha void dcc_release_item (DisplayChannelClient *dcc, PipeItem *item, int item_pushed); +void dcc_send_item (DisplayChannelClient *dcc, + PipeItem *item); typedef struct compress_send_data_t { void* comp_buf; diff --git a/server/display_channel.c b/server/display_channel.c index f9587e7a..dcfde9a5 100644 --- a/server/display_channel.c +++ b/server/display_channel.c @@ -1389,3 +1389,155 @@ void display_channel_draw(DisplayChannel *display, const SpiceRect *area, int su draw_until(display, surface, last); surface_update_dest(surface, area); } + +static void on_disconnect(RedChannelClient *rcc) +{ + DisplayChannel *display; + DisplayChannelClient *dcc = RCC_TO_DCC(rcc); + RedWorker *worker; + + spice_info(NULL); + spice_return_if_fail(rcc != NULL); + + display = DCC_TO_DC(dcc); + worker = COMMON_CHANNEL(display)->worker; + spice_return_if_fail(rcc->channel == red_worker_get_display_channel(worker)); + + dcc_stop(dcc); // TODO: start/stop -> connect/disconnect? + display_channel_compress_stats_print(display); + + // this was the last channel client +#if FIXME + spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d", + display->drawable_count, worker->red_drawable_count, + worker->glz_drawable_count); +#endif +} + +static void send_item(RedChannelClient *rcc, PipeItem *item) +{ + dcc_send_item(RCC_TO_DCC(rcc), item); +} + +static void hold_item(RedChannelClient *rcc, PipeItem *item) +{ + spice_return_if_fail(item); + + switch (item->type) { + case PIPE_ITEM_TYPE_DRAW: + drawable_pipe_item_ref(SPICE_CONTAINEROF(item, DrawablePipeItem, dpi_pipe_item)); + break; + case PIPE_ITEM_TYPE_STREAM_CLIP: + ((StreamClipItem *)item)->refs++; + break; + case PIPE_ITEM_TYPE_UPGRADE: + ((UpgradeItem *)item)->refs++; + break; + case PIPE_ITEM_TYPE_IMAGE: + ((ImageItem *)item)->refs++; + break; + default: + spice_warn_if_reached(); + } +} + +static void release_item(RedChannelClient *rcc, PipeItem *item, int item_pushed) +{ + DisplayChannelClient *dcc = RCC_TO_DCC(rcc); + RedWorker *worker = DCC_TO_WORKER(dcc); + + spice_return_if_fail(item != NULL); + dcc_release_item(dcc, item, item_pushed); + red_worker_update_timeout(worker, 0); +} + +static int handle_migrate_flush_mark(RedChannelClient *rcc) +{ + DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base); + RedChannel *channel = RED_CHANNEL(display_channel); + + red_channel_pipes_add_type(channel, PIPE_ITEM_TYPE_MIGRATE_DATA); + return TRUE; +} + +static uint64_t handle_migrate_data_get_serial(RedChannelClient *rcc, uint32_t size, void *message) +{ + SpiceMigrateDataDisplay *migrate_data; + + migrate_data = (SpiceMigrateDataDisplay *)((uint8_t *)message + sizeof(SpiceMigrateDataHeader)); + + return migrate_data->message_serial; +} + +static int handle_migrate_data(RedChannelClient *rcc, uint32_t size, void *message) +{ + return dcc_handle_migrate_data(RCC_TO_DCC(rcc), size, message); +} + +static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces, uint32_t surface_id) +{ + DisplayChannel *display = SPICE_CONTAINEROF(surfaces, DisplayChannel, image_surfaces); + + spice_return_val_if_fail(validate_surface(display, surface_id), NULL); + + return display->surfaces[surface_id].context.canvas; +} + +DisplayChannel* display_channel_new(RedWorker *worker, int migrate, uint32_t n_surfaces) +{ + DisplayChannel *display; + ChannelCbs cbs = { + .on_disconnect = on_disconnect, + .send_item = send_item, + .hold_item = hold_item, + .release_item = release_item, + .handle_migrate_flush_mark = handle_migrate_flush_mark, + .handle_migrate_data = handle_migrate_data, + .handle_migrate_data_get_serial = handle_migrate_data_get_serial + }; + static SpiceImageSurfacesOps image_surfaces_ops = { + image_surfaces_get, + }; + + spice_return_val_if_fail(num_renderers > 0, NULL); + + spice_info("create display channel"); + display = (DisplayChannel *)red_worker_new_channel( + worker, sizeof(*display), "display_channel", + SPICE_CHANNEL_DISPLAY, + SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER, + &cbs, dcc_handle_message); + spice_return_val_if_fail(display, NULL); + + stat_init(&display->add_stat, "add", red_worker_get_clockid(worker)); + stat_init(&display->exclude_stat, "exclude", red_worker_get_clockid(worker)); + stat_init(&display->__exclude_stat, "__exclude", red_worker_get_clockid(worker)); +#ifdef RED_STATISTICS + RedChannel *channel = RED_CHANNEL(display); + display->cache_hits_counter = stat_add_counter(channel->stat, + "cache_hits", TRUE); + display->add_to_cache_counter = stat_add_counter(channel->stat, + "add_to_cache", TRUE); + display->non_cache_counter = stat_add_counter(channel->stat, + "non_cache", TRUE); +#endif + stat_compress_init(&display->lz_stat, "lz"); + stat_compress_init(&display->glz_stat, "glz"); + stat_compress_init(&display->quic_stat, "quic"); + stat_compress_init(&display->jpeg_stat, "jpeg"); + stat_compress_init(&display->zlib_glz_stat, "zlib"); + stat_compress_init(&display->jpeg_alpha_stat, "jpeg_alpha"); + + display->n_surfaces = n_surfaces; + display->num_renderers = num_renderers; + memcpy(display->renderers, renderers, sizeof(display->renderers)); + display->renderer = RED_RENDERER_INVALID; + + ring_init(&display->current_list); + display->image_surfaces.ops = &image_surfaces_ops; + drawables_init(display); + image_cache_init(&display->image_cache); + stream_init(display); + + return display; +} diff --git a/server/display_channel.h b/server/display_channel.h index 1865eca0..153a4377 100644 --- a/server/display_channel.h +++ b/server/display_channel.h @@ -233,7 +233,9 @@ typedef struct UpgradeItem { SpiceClipRects *rects; } UpgradeItem; - +DisplayChannel* display_channel_new (RedWorker *worker, + int migrate, + uint32_t n_surfaces); void display_channel_draw (DisplayChannel *display, const SpiceRect *area, int surface_id); @@ -270,6 +272,21 @@ void display_channel_flush_all_surfaces (DisplayCha void display_channel_free_glz_drawables_to_free(DisplayChannel *display); void display_channel_free_glz_drawables (DisplayChannel *display); +static inline int validate_surface(DisplayChannel *display, uint32_t surface_id) +{ + if (surface_id == G_MAXUINT32) + return 1; + + spice_warn_if(surface_id >= display->n_surfaces); + if (!display->surfaces[surface_id].context.canvas) { + spice_warning("canvas address is %p for %d (and is NULL)\n", + &(display->surfaces[surface_id].context.canvas), surface_id); + spice_warning("failed on %d", surface_id); + return 0; + } + return 1; +} + static inline int is_equal_path(SpicePath *path1, SpicePath *path2) { SpicePathSeg *seg1, *seg2; diff --git a/server/red_worker.c b/server/red_worker.c index ccb07fe9..4f388fa1 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -147,19 +147,12 @@ QXLInstance* red_worker_get_qxl(RedWorker *worker) return worker->qxl; } -static inline int validate_surface(DisplayChannel *display, uint32_t surface_id) +void red_worker_update_timeout(RedWorker *worker, gint timeout) { - if (surface_id == G_MAXUINT32) - return 1; + spice_return_if_fail(worker != NULL); + spice_return_if_fail(timeout >= 0); - spice_warn_if(surface_id >= display->n_surfaces); - if (!display->surfaces[surface_id].context.canvas) { - spice_warning("canvas address is %p for %d (and is NULL)\n", - &(display->surfaces[surface_id].context.canvas), surface_id); - spice_warning("failed on %d", surface_id); - return 0; - } - return 1; + worker->timeout = MIN(worker->timeout, timeout); } static int display_is_connected(RedWorker *worker) @@ -551,21 +544,6 @@ void detach_streams_behind(DisplayChannel *display, QRegion *region, Drawable *d } } -static void dcc_destroy_stream_agents(DisplayChannelClient *dcc) -{ - int i; - - for (i = 0; i < NUM_STREAMS; i++) { - StreamAgent *agent = &dcc->stream_agents[i]; - region_destroy(&agent->vis_region); - region_destroy(&agent->clip); - if (agent->mjpeg_encoder) { - mjpeg_encoder_destroy(agent->mjpeg_encoder); - agent->mjpeg_encoder = NULL; - } - } -} - static void red_get_area(DisplayChannel *display, int surface_id, const SpiceRect *area, uint8_t *dest, int dest_stride, int update) { @@ -852,15 +830,6 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface free(surface); } -static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces, uint32_t surface_id) -{ - DisplayChannel *display = SPICE_CONTAINEROF(surfaces, DisplayChannel, image_surfaces); - - spice_return_val_if_fail(validate_surface(display, surface_id), NULL); - - return display->surfaces[surface_id].context.canvas; -} - static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int *ring_is_empty) { QXLCommandExt ext_cmd; @@ -1316,13 +1285,6 @@ static void fill_attr(SpiceMarshaller *m, SpiceLineAttr *attr, uint32_t group_id } } -static inline void red_display_reset_send_data(DisplayChannelClient *dcc) -{ - dcc->send_data.free_list.res->count = 0; - dcc->send_data.num_pixmap_cache_items = 0; - memset(dcc->send_data.free_list.sync, 0, sizeof(dcc->send_data.free_list.sync)); -} - /* set area=NULL for testing the whole surface */ static int is_surface_area_lossy(DisplayChannelClient *dcc, uint32_t surface_id, const SpiceRect *area, SpiceRect *out_lossy_area) @@ -3414,12 +3376,19 @@ static void red_marshall_stream_activate_report(RedChannelClient *rcc, spice_marshall_msg_display_stream_activate_report(base_marshaller, &msg); } -static void send_item(RedChannelClient *rcc, PipeItem *pipe_item) +static void reset_send_data(DisplayChannelClient *dcc) +{ + dcc->send_data.free_list.res->count = 0; + dcc->send_data.num_pixmap_cache_items = 0; + memset(dcc->send_data.free_list.sync, 0, sizeof(dcc->send_data.free_list.sync)); +} + +void dcc_send_item(DisplayChannelClient *dcc, PipeItem *pipe_item) { + RedChannelClient *rcc = RED_CHANNEL_CLIENT(dcc); SpiceMarshaller *m = red_channel_client_get_marshaller(rcc); - DisplayChannelClient *dcc = RCC_TO_DCC(rcc); - red_display_reset_send_data(dcc); + reset_send_data(dcc); switch (pipe_item->type) { case PIPE_ITEM_TYPE_DRAW: { DrawablePipeItem *dpi = SPICE_CONTAINEROF(pipe_item, DrawablePipeItem, dpi_pipe_item); @@ -3510,38 +3479,6 @@ static inline void red_push(RedWorker *worker) } } -static void on_disconnect(RedChannelClient *rcc) -{ - DisplayChannel *display; - DisplayChannelClient *dcc = RCC_TO_DCC(rcc); - CommonChannel *common; - RedWorker *worker; - - if (!rcc) { - return; - } - spice_info(NULL); - common = SPICE_CONTAINEROF(rcc->channel, CommonChannel, base); - worker = common->worker; - display = (DisplayChannel *)rcc->channel; - spice_assert(display == worker->display_channel); - display_channel_compress_stats_print(display); - pixmap_cache_unref(dcc->pixmap_cache); - dcc->pixmap_cache = NULL; - dcc_release_glz(dcc); - dcc_palette_cache_reset(dcc); - free(dcc->send_data.stream_outbuf); - free(dcc->send_data.free_list.res); - dcc_destroy_stream_agents(dcc); - - // this was the last channel client -#if FIXME - spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d", - display->drawable_count, worker->red_drawable_count, - worker->glz_drawable_count); -#endif -} - void red_disconnect_all_display_TODO_remove_me(RedChannel *channel) { // TODO: we need to record the client that actually causes the timeout. So @@ -3784,29 +3721,6 @@ static inline void flush_all_qxl_commands(RedWorker *worker) flush_cursor_commands(worker); } -static int handle_migrate_flush_mark(RedChannelClient *rcc) -{ - DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base); - RedChannel *channel = RED_CHANNEL(display_channel); - - red_channel_pipes_add_type(channel, PIPE_ITEM_TYPE_MIGRATE_DATA); - return TRUE; -} - -static uint64_t handle_migrate_data_get_serial(RedChannelClient *rcc, uint32_t size, void *message) -{ - SpiceMigrateDataDisplay *migrate_data; - - migrate_data = (SpiceMigrateDataDisplay *)((uint8_t *)message + sizeof(SpiceMigrateDataHeader)); - - return migrate_data->message_serial; -} - -static int handle_migrate_data(RedChannelClient *rcc, uint32_t size, void *message) -{ - return dcc_handle_migrate_data(RCC_TO_DCC(rcc), size, message); -} - static int common_channel_config_socket(RedChannelClient *rcc) { RedClient *client = red_channel_client_get_client(rcc); @@ -4069,102 +3983,6 @@ RedChannel *red_worker_new_channel(RedWorker *worker, int size, return channel; } -static void hold_item(RedChannelClient *rcc, PipeItem *item) -{ - spice_assert(item); - switch (item->type) { - case PIPE_ITEM_TYPE_DRAW: - drawable_pipe_item_ref(SPICE_CONTAINEROF(item, DrawablePipeItem, dpi_pipe_item)); - break; - case PIPE_ITEM_TYPE_STREAM_CLIP: - ((StreamClipItem *)item)->refs++; - break; - case PIPE_ITEM_TYPE_UPGRADE: - ((UpgradeItem *)item)->refs++; - break; - case PIPE_ITEM_TYPE_IMAGE: - ((ImageItem *)item)->refs++; - break; - default: - spice_critical("invalid item type"); - } -} - -static void release_item(RedChannelClient *rcc, PipeItem *item, int item_pushed) -{ - DisplayChannelClient *dcc = RCC_TO_DCC(rcc); - RedWorker *worker = DCC_TO_WORKER(dcc); - - spice_return_if_fail(item != NULL); - dcc_release_item(dcc, item, item_pushed); - worker->timeout = 0; -} - -static void image_surface_init(DisplayChannel *display) -{ - static SpiceImageSurfacesOps image_surfaces_ops = { - image_surfaces_get, - }; - - display->image_surfaces.ops = &image_surfaces_ops; -} - -static void display_channel_create(RedWorker *worker, int migrate, uint32_t n_surfaces) -{ - DisplayChannel *display_channel; - ChannelCbs cbs = { - .on_disconnect = on_disconnect, - .send_item = send_item, - .hold_item = hold_item, - .release_item = release_item, - .handle_migrate_flush_mark = handle_migrate_flush_mark, - .handle_migrate_data = handle_migrate_data, - .handle_migrate_data_get_serial = handle_migrate_data_get_serial - }; - - spice_return_if_fail(num_renderers > 0); - - spice_info("create display channel"); - if (!(display_channel = (DisplayChannel *)red_worker_new_channel( - worker, sizeof(*display_channel), "display_channel", - SPICE_CHANNEL_DISPLAY, - SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER, - &cbs, dcc_handle_message))) { - spice_warning("failed to create display channel"); - return; - } - worker->display_channel = display_channel; - stat_init(&display_channel->add_stat, "add", worker->clockid); - stat_init(&display_channel->exclude_stat, "exclude", worker->clockid); - stat_init(&display_channel->__exclude_stat, "__exclude", worker->clockid); -#ifdef RED_STATISTICS - RedChannel *channel = RED_CHANNEL(display_channel); - display_channel->cache_hits_counter = stat_add_counter(channel->stat, - "cache_hits", TRUE); - display_channel->add_to_cache_counter = stat_add_counter(channel->stat, - "add_to_cache", TRUE); - display_channel->non_cache_counter = stat_add_counter(channel->stat, - "non_cache", TRUE); -#endif - stat_compress_init(&display_channel->lz_stat, "lz"); - stat_compress_init(&display_channel->glz_stat, "glz"); - stat_compress_init(&display_channel->quic_stat, "quic"); - stat_compress_init(&display_channel->jpeg_stat, "jpeg"); - stat_compress_init(&display_channel->zlib_glz_stat, "zlib"); - stat_compress_init(&display_channel->jpeg_alpha_stat, "jpeg_alpha"); - - 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; - - 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) { int i; @@ -5261,7 +5079,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, init_info.n_surfaces); + worker->display_channel = display_channel_new(worker, FALSE, init_info.n_surfaces); worker->wait_for_clients = !g_getenv("SPICE_NOWAIT_CLIENTS"); diff --git a/server/red_worker.h b/server/red_worker.h index 7e92882c..89912285 100644 --- a/server/red_worker.h +++ b/server/red_worker.h @@ -112,6 +112,7 @@ static inline void red_pipes_add_verb(RedChannel *channel, uint16_t verb) RedWorker* red_worker_new(QXLInstance *qxl, RedDispatcher *red_dispatcher); bool red_worker_run(RedWorker *worker); +void red_worker_update_timeout(RedWorker *worker, gint timeout); QXLInstance* red_worker_get_qxl(RedWorker *worker); RedChannel* red_worker_get_cursor_channel(RedWorker *worker); RedChannel* red_worker_get_display_channel(RedWorker *worker); |