[Spice-devel] [PATCH 12/18] worker: move display_channel_new

Frediano Ziglio fziglio at redhat.com
Tue Nov 24 03:13:16 PST 2015


From: Marc-André Lureau <marcandre.lureau at gmail.com>

---
 server/dcc.c             |  26 ++++++
 server/dcc.h             |   3 +
 server/display-channel.c | 151 +++++++++++++++++++++++++++++++++
 server/display-channel.h |  19 +++++
 server/red_worker.c      | 215 +++--------------------------------------------
 5 files changed, 211 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..66b661e 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1402,3 +1402,154 @@ 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
+    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 6761e6f..cef546e 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;
@@ -5174,7 +4982,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



More information about the Spice-devel mailing list