> > 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> > Merged (was already merged) Frediano _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel