On Wed, Nov 25, 2015 at 11:29 AM, Frediano Ziglio <fziglio@xxxxxxxxxx> wrote: > > --- > server/dcc.c | 26 ++++++ > server/dcc.h | 3 + > server/display-channel.c | 149 ++++++++++++++++++++++++++++++++ > server/display-channel.h | 19 +++++ > server/red_worker.c | 215 +++-------------------------------------------- > 5 files changed, 209 insertions(+), 203 deletions(-) > > diff --git a/server/dcc.c b/server/dcc.c > index 5d666cb..e3b0c55 100644 > --- a/server/dcc.c > +++ b/server/dcc.c > @@ -372,6 +372,32 @@ 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); > + dcc_encoders_free(dcc); > +} > > void dcc_stream_agent_clip(DisplayChannelClient* dcc, StreamAgent *agent) > { > diff --git a/server/dcc.h b/server/dcc.h > index 62261e8..dc6f1e7 100644 > --- a/server/dcc.h > +++ b/server/dcc.h > @@ -161,6 +161,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); > @@ -198,6 +199,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 855b65a..9e2375c 100644 > --- a/server/display-channel.c > +++ b/server/display-channel.c > @@ -1402,3 +1402,152 @@ 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; > + > + spice_info(NULL); > + spice_return_if_fail(rcc != NULL); > + > + dcc = RCC_TO_DCC(rcc); > + display = DCC_TO_DC(dcc); > + > + dcc_stop(dcc); // TODO: start/stop -> connect/disconnect? > + display_channel_compress_stats_print(display); > + > + // this was the last channel client > + spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d", > + display->drawable_count, display->red_drawable_count, > + display->glz_drawable_count); > +} > + > +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); > + > + spice_return_if_fail(item != NULL); > + dcc_release_item(dcc, item, item_pushed); > +} > + > +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, int stream_video, > + 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"); > + stat_compress_init(&display->lz4_stat, "lz4"); > + > + 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); > + display->stream_video = stream_video; > + display_channel_init_streams(display); > + > + return display; > +} > diff --git a/server/display-channel.h b/server/display-channel.h > index 0a6f120..42b3850 100644 > --- a/server/display-channel.h > +++ b/server/display-channel.h > @@ -251,6 +251,10 @@ typedef struct UpgradeItem { > } UpgradeItem; > > > +DisplayChannel* display_channel_new (RedWorker *worker, > + int migrate, > + int stream_video, > + uint32_t n_surfaces); > void display_channel_draw (DisplayChannel *display, > const SpiceRect *area, > int surface_id); > @@ -281,6 +285,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 SPICE_UNLIKELY(surface_id >= display->n_surfaces) { > + spice_warning("invalid surface_id %u", surface_id); > + return 0; > + } > + 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 67978ac..8db2f78 100644 > --- a/server/red_worker.c > +++ b/server/red_worker.c > @@ -135,8 +135,6 @@ typedef struct BitmapData { > SpiceRect lossy_rect; > } BitmapData; > > -static inline int validate_surface(DisplayChannel *display, uint32_t surface_id); > - > static inline void display_begin_send_message(RedChannelClient *rcc); > static void red_create_surface(DisplayChannel *display, uint32_t surface_id, uint32_t width, > uint32_t height, int32_t stride, uint32_t format, > @@ -178,21 +176,6 @@ static int validate_drawable_bbox(DisplayChannel *display, RedDrawable *drawable > return TRUE; > } > > -static inline int validate_surface(DisplayChannel *display, uint32_t surface_id) > -{ > - if SPICE_UNLIKELY(surface_id >= display->n_surfaces) { > - spice_warning("invalid surface_id %u", surface_id); > - return 0; > - } > - 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 int display_is_connected(RedWorker *worker) > { > return (worker->display_channel && red_channel_is_connected( > @@ -606,21 +589,6 @@ static void display_channel_streams_timeout(DisplayChannel *display) > } > } > > -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) > { > @@ -918,24 +886,6 @@ exit: > 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 void image_surface_init(DisplayChannel *display) > -{ > - static SpiceImageSurfacesOps image_surfaces_ops = { > - image_surfaces_get, > - }; > - > - display->image_surfaces.ops = &image_surfaces_ops; > -} > - > static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int *ring_is_empty) > { > QXLCommandExt ext_cmd; > @@ -1367,13 +1317,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) > @@ -3446,12 +3389,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); > @@ -3545,37 +3495,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); > - dcc_encoders_free(dcc); > - > - // this was the last channel client > - spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d", > - display->drawable_count, display->red_drawable_count, > - display->glz_drawable_count); > -} > - > void red_disconnect_all_display_TODO_remove_me(RedChannel *channel) > { > // TODO: we need to record the client that actually causes the timeout. So > @@ -3822,29 +3741,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); > @@ -4027,94 +3923,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); > - > - spice_return_if_fail(item != NULL); > - dcc_release_item(dcc, item, item_pushed); > -} > - > -static void display_channel_create(RedWorker *worker, int migrate, int stream_video, > - 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"); > - stat_compress_init(&display_channel->lz4_stat, "lz4"); > - > - 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); > - display_channel->stream_video = stream_video; > - display_channel_init_streams(display_channel); > -} > - > static void guest_set_client_capabilities(RedWorker *worker) > { > int i; > @@ -5172,7 +4980,8 @@ 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, streaming_video, init_info.n_surfaces); > + worker->display_channel = display_channel_new(worker, FALSE, streaming_video, > + init_info.n_surfaces); > > return worker; > } > -- > 2.4.3 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel Acked-by: Fabiano Fidêncio <fidencio@xxxxxxxxxx> _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel