[Spice-devel] [PATCH 12/18] worker: move display_channel_new
Fabiano FidĂȘncio
fidencio at redhat.com
Wed Dec 2 06:47:51 PST 2015
On Wed, Nov 25, 2015 at 11:29 AM, Frediano Ziglio <fziglio at redhat.com> 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
Acked-by: Fabiano FidĂȘncio <fidencio at redhat.com>
More information about the Spice-devel
mailing list