summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@gmail.com>2013-09-27 17:23:02 +0200
committerChristophe Fergeau <cfergeau@redhat.com>2014-02-13 17:38:00 +0100
commit63bed98ce194be31caeee967bf522195a3192695 (patch)
tree9328f5146a51dd105836f4b144ca773605c224bd
parent52d941308bd9d8cfcf499008e52990fc81fa066a (diff)
worker: move display_channel_new
-rw-r--r--server/dcc.c25
-rw-r--r--server/dcc.h3
-rw-r--r--server/display_channel.c152
-rw-r--r--server/display_channel.h19
-rw-r--r--server/red_worker.c212
-rw-r--r--server/red_worker.h1
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);