[Spice-commits] 5 commits - server/dcc.c server/dcc.h server/display-channel.c server/display-channel.h server/red_worker.c
Frediano Ziglio
fziglio at kemper.freedesktop.org
Wed Nov 25 06:15:52 PST 2015
server/dcc.c | 106 +++++++++
server/dcc.h | 5
server/display-channel.c | 341 +++++++++++++++++++++++++++++
server/display-channel.h | 49 ++++
server/red_worker.c | 552 ++---------------------------------------------
5 files changed, 525 insertions(+), 528 deletions(-)
New commits:
commit 7d38c28a0aef29567bf6b87188cbdd10a5fcb8e9
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date: Wed Nov 25 08:58:25 2015 +0100
display: Remove extra parameters from create_canvas_for_surface
Get them from the surface
Acked-by: Pavel Grunt <pgrunt at redhat.com>
diff --git a/server/display-channel.c b/server/display-channel.c
index 39d944f..1496f07 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1538,16 +1538,14 @@ static void send_create_surface(DisplayChannel *display, int surface_id, int ima
}
static SpiceCanvas*
-create_canvas_for_surface(DisplayChannel *display, RedSurface *surface,
- uint32_t renderer, uint32_t width, uint32_t height,
- int32_t stride, uint32_t format, void *line_0)
+create_canvas_for_surface(DisplayChannel *display, RedSurface *surface, uint32_t renderer)
{
SpiceCanvas *canvas;
switch (renderer) {
case RED_RENDERER_SW:
- canvas = canvas_create_for_data(width, height, format,
- line_0, stride,
+ canvas = canvas_create_for_data(surface->context.width, surface->context.height, surface->context.format,
+ surface->context.line_0, surface->context.stride,
&display->image_cache.base,
&display->image_surfaces, NULL, NULL, NULL);
surface->context.top_down = TRUE;
@@ -1590,9 +1588,7 @@ void display_channel_create_surface(DisplayChannel *display, uint32_t surface_id
region_init(&surface->draw_dirty_region);
surface->refs = 1;
if (display->renderer != RED_RENDERER_INVALID) {
- surface->context.canvas = create_canvas_for_surface(display, surface, display->renderer,
- width, height, stride,
- surface->context.format, line_0);
+ surface->context.canvas = create_canvas_for_surface(display, surface, display->renderer);
if (!surface->context.canvas) {
spice_critical("drawing canvas creating failed - can`t create same type canvas");
}
@@ -1603,9 +1599,7 @@ void display_channel_create_surface(DisplayChannel *display, uint32_t surface_id
}
for (i = 0; i < display->num_renderers; i++) {
- surface->context.canvas = create_canvas_for_surface(display, surface, display->renderers[i],
- width, height, stride,
- surface->context.format, line_0);
+ surface->context.canvas = create_canvas_for_surface(display, surface, display->renderers[i]);
if (surface->context.canvas) { //no need canvas check
display->renderer = display->renderers[i];
if (send_client)
commit 4e35645fb05cb82e1f8b90215a5024a6d83f7474
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date: Fri Sep 27 19:10:03 2013 +0200
worker: move display_channel_create_surface
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/server/display-channel.c b/server/display-channel.c
index 55dd37b..39d944f 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1525,6 +1525,98 @@ void display_channel_destroy_surfaces(DisplayChannel *display)
display_channel_free_glz_drawables(display);
}
+static void send_create_surface(DisplayChannel *display, int surface_id, int image_ready)
+{
+ DisplayChannelClient *dcc;
+ RingItem *item, *next;
+
+ FOREACH_DCC(display, item, next, dcc) {
+ dcc_create_surface(dcc, surface_id);
+ if (image_ready)
+ dcc_push_surface_image(dcc, surface_id);
+ }
+}
+
+static SpiceCanvas*
+create_canvas_for_surface(DisplayChannel *display, RedSurface *surface,
+ uint32_t renderer, uint32_t width, uint32_t height,
+ int32_t stride, uint32_t format, void *line_0)
+{
+ SpiceCanvas *canvas;
+
+ switch (renderer) {
+ case RED_RENDERER_SW:
+ canvas = canvas_create_for_data(width, height, format,
+ line_0, stride,
+ &display->image_cache.base,
+ &display->image_surfaces, NULL, NULL, NULL);
+ surface->context.top_down = TRUE;
+ surface->context.canvas_draws_on_surface = TRUE;
+ return canvas;
+ default:
+ spice_warn_if_reached();
+ };
+
+ return NULL;
+}
+
+void display_channel_create_surface(DisplayChannel *display, uint32_t surface_id, uint32_t width,
+ uint32_t height, int32_t stride, uint32_t format,
+ void *line_0, int data_is_valid, int send_client)
+{
+ RedSurface *surface = &display->surfaces[surface_id];
+ uint32_t i;
+
+ spice_warn_if(surface->context.canvas);
+
+ surface->context.canvas_draws_on_surface = FALSE;
+ surface->context.width = width;
+ surface->context.height = height;
+ surface->context.format = format;
+ surface->context.stride = stride;
+ surface->context.line_0 = line_0;
+ if (!data_is_valid) {
+ char *data = line_0;
+ if (stride < 0) {
+ data -= abs(stride) * (height - 1);
+ }
+ memset(data, 0, height*abs(stride));
+ }
+ surface->create.info = NULL;
+ surface->destroy.info = NULL;
+ ring_init(&surface->current);
+ ring_init(&surface->current_list);
+ ring_init(&surface->depend_on_me);
+ region_init(&surface->draw_dirty_region);
+ surface->refs = 1;
+ if (display->renderer != RED_RENDERER_INVALID) {
+ surface->context.canvas = create_canvas_for_surface(display, surface, display->renderer,
+ width, height, stride,
+ surface->context.format, line_0);
+ if (!surface->context.canvas) {
+ spice_critical("drawing canvas creating failed - can`t create same type canvas");
+ }
+
+ if (send_client)
+ send_create_surface(display, surface_id, data_is_valid);
+ return;
+ }
+
+ for (i = 0; i < display->num_renderers; i++) {
+ surface->context.canvas = create_canvas_for_surface(display, surface, display->renderers[i],
+ width, height, stride,
+ surface->context.format, line_0);
+ if (surface->context.canvas) { //no need canvas check
+ display->renderer = display->renderers[i];
+ if (send_client)
+ send_create_surface(display, surface_id, data_is_valid);
+ return;
+ }
+ }
+
+ spice_critical("unable to create drawing canvas");
+}
+
static void on_disconnect(RedChannelClient *rcc)
{
DisplayChannel *display;
diff --git a/server/display-channel.h b/server/display-channel.h
index 0bdf9dc..33caabe 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -255,6 +255,10 @@ DisplayChannel* display_channel_new (RedWorker
int migrate,
int stream_video,
uint32_t n_surfaces);
+void display_channel_create_surface (DisplayChannel *display, uint32_t surface_id,
+ uint32_t width, uint32_t height,
+ int32_t stride, uint32_t format, void *line_0,
+ int data_is_valid, int send_client);
void display_channel_draw (DisplayChannel *display,
const SpiceRect *area,
int surface_id);
diff --git a/server/red_worker.c b/server/red_worker.c
index 0c3ab30..678b581 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -134,9 +134,6 @@ typedef struct BitmapData {
} BitmapData;
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,
- void *line_0, int data_is_valid, int send_client);
QXLInstance* red_worker_get_qxl(RedWorker *worker)
{
@@ -740,11 +737,11 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface
if (stride < 0) {
data -= (int32_t)(stride * (height - 1));
}
- red_create_surface(worker->display_channel, surface_id, surface->u.surface_create.width,
- height, stride, surface->u.surface_create.format, data,
- reloaded_surface,
- // reloaded surfaces will be sent on demand
- !reloaded_surface);
+ display_channel_create_surface(worker->display_channel, surface_id, surface->u.surface_create.width,
+ height, stride, surface->u.surface_create.format, data,
+ reloaded_surface,
+ // reloaded surfaces will be sent on demand
+ !reloaded_surface);
set_surface_release_info(&red_surface->create, surface->release_info, group_id);
break;
}
@@ -3416,114 +3413,6 @@ static void red_migrate_display(DisplayChannel *display, RedChannelClient *rcc)
}
}
-static inline void *create_canvas_for_surface(DisplayChannel *display, RedSurface *surface,
- uint32_t renderer, uint32_t width, uint32_t height,
- int32_t stride, uint32_t format, void *line_0)
-{
- SpiceCanvas *canvas;
-
- switch (renderer) {
- case RED_RENDERER_SW:
- canvas = canvas_create_for_data(width, height, format,
- line_0, stride,
- &display->image_cache.base,
- &display->image_surfaces, NULL, NULL, NULL);
- surface->context.top_down = TRUE;
- surface->context.canvas_draws_on_surface = TRUE;
- return canvas;
- default:
- spice_error("invalid renderer type");
- };
-
- return NULL;
-}
-
-static void red_worker_create_surface_item(DisplayChannel *display, int surface_id)
-{
- DisplayChannelClient *dcc;
- RingItem *item, *next;
-
- FOREACH_DCC(display, item, next, dcc) {
- dcc_create_surface(dcc, surface_id);
- }
-}
-
-
-static void red_worker_push_surface_image(DisplayChannel *display, int surface_id)
-{
- DisplayChannelClient *dcc;
- RingItem *item, *next;
-
- FOREACH_DCC(display, item, next, dcc) {
- dcc_push_surface_image(dcc, surface_id);
- }
-}
-
-static void red_create_surface(DisplayChannel *display, uint32_t surface_id, uint32_t width,
- uint32_t height, int32_t stride, uint32_t format,
- void *line_0, int data_is_valid, int send_client)
-{
- RedSurface *surface = &display->surfaces[surface_id];
- uint32_t i;
-
- spice_warn_if(surface->context.canvas);
-
- surface->context.canvas_draws_on_surface = FALSE;
- surface->context.width = width;
- surface->context.height = height;
- surface->context.format = format;
- surface->context.stride = stride;
- surface->context.line_0 = line_0;
- if (!data_is_valid) {
- char *data = line_0;
- if (stride < 0) {
- data -= abs(stride) * (height - 1);
- }
- memset(data, 0, height*abs(stride));
- }
- surface->create.info = NULL;
- surface->destroy.info = NULL;
- ring_init(&surface->current);
- ring_init(&surface->current_list);
- ring_init(&surface->depend_on_me);
- region_init(&surface->draw_dirty_region);
- surface->refs = 1;
- if (display->renderer != RED_RENDERER_INVALID) {
- surface->context.canvas = create_canvas_for_surface(display, surface, display->renderer,
- width, height, stride,
- surface->context.format, line_0);
- if (!surface->context.canvas) {
- spice_critical("drawing canvas creating failed - can`t create same type canvas");
- }
-
- if (send_client) {
- red_worker_create_surface_item(display, surface_id);
- if (data_is_valid) {
- red_worker_push_surface_image(display, surface_id);
- }
- }
- return;
- }
-
- for (i = 0; i < display->num_renderers; i++) {
- surface->context.canvas = create_canvas_for_surface(display, surface, display->renderers[i],
- width, height, stride,
- surface->context.format, line_0);
- if (surface->context.canvas) { //no need canvas check
- display->renderer = display->renderers[i];
- if (send_client) {
- red_worker_create_surface_item(display, surface_id);
- if (data_is_valid) {
- red_worker_push_surface_image(display, surface_id);
- }
- }
- return;
- }
- }
-
- spice_critical("unable to create drawing canvas");
-}
-
static inline void flush_display_commands(RedWorker *worker)
{
RedChannel *display_red_channel = RED_CHANNEL(worker->display_channel);
@@ -4043,8 +3932,8 @@ static void dev_create_primary_surface(RedWorker *worker, uint32_t surface_id,
line_0 -= (int32_t)(surface.stride * (surface.height -1));
}
- red_create_surface(display, 0, surface.width, surface.height, surface.stride, surface.format,
- line_0, surface.flags & QXL_SURF_FLAG_KEEP_DATA, TRUE);
+ display_channel_create_surface(display, 0, surface.width, surface.height, surface.stride, surface.format,
+ line_0, surface.flags & QXL_SURF_FLAG_KEEP_DATA, TRUE);
set_monitors_config_to_primary(display);
if (display_is_connected(worker) && !worker->display_channel->common.during_target_migrate) {
commit fd9c97a83328d98cbf80734c5d694b600b5db815
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date: Fri Sep 27 19:29:45 2013 +0200
worker: move display_channel_update
Acked-by: Pavel Grunt <pgrunt at redhat.com>
diff --git a/server/display-channel.c b/server/display-channel.c
index 1ed0568..55dd37b 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1419,6 +1419,45 @@ void display_channel_draw(DisplayChannel *display, const SpiceRect *area, int su
surface_update_dest(surface, area);
}
+static void region_to_qxlrects(QRegion *region, QXLRect *qxl_rects, uint32_t num_rects)
+{
+ SpiceRect *rects;
+ int i;
+
+ rects = spice_new0(SpiceRect, num_rects);
+ region_ret_rects(region, rects, num_rects);
+ for (i = 0; i < num_rects; i++) {
+ qxl_rects[i].top = rects[i].top;
+ qxl_rects[i].left = rects[i].left;
+ qxl_rects[i].bottom = rects[i].bottom;
+ qxl_rects[i].right = rects[i].right;
+ }
+ free(rects);
+}
+
+void display_channel_update(DisplayChannel *display,
+ uint32_t surface_id, const QXLRect *area, uint32_t clear_dirty,
+ QXLRect **qxl_dirty_rects, uint32_t *num_dirty_rects)
+{
+ SpiceRect rect;
+ RedSurface *surface;
+
+ spice_return_if_fail(validate_surface(display, surface_id));
+
+ red_get_rect_ptr(&rect, area);
+ display_channel_draw(display, &rect, surface_id);
+
+ surface = &display->surfaces[surface_id];
+ if (*qxl_dirty_rects == NULL) {
+ *num_dirty_rects = pixman_region32_n_rects(&surface->draw_dirty_region);
+ *qxl_dirty_rects = spice_new0(QXLRect, *num_dirty_rects);
+ }
+
+ region_to_qxlrects(&surface->draw_dirty_region, *qxl_dirty_rects, *num_dirty_rects);
+ if (clear_dirty)
+ region_clear(&surface->draw_dirty_region);
+}
+
static void clear_surface_drawables_from_pipes(DisplayChannel *display, int surface_id,
int wait_if_used)
{
diff --git a/server/display-channel.h b/server/display-channel.h
index e74941a..0bdf9dc 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -262,6 +262,12 @@ void display_channel_draw_till (DisplayCha
const SpiceRect *area,
int surface_id,
Drawable *last);
+void display_channel_update (DisplayChannel *display,
+ uint32_t surface_id,
+ const QXLRect *area,
+ uint32_t clear_dirty,
+ QXLRect **qxl_dirty_rects,
+ uint32_t *num_dirty_rects);
void display_channel_free_some (DisplayChannel *display);
void display_channel_set_stream_video (DisplayChannel *display,
int stream_video);
diff --git a/server/red_worker.c b/server/red_worker.c
index 3709691..0c3ab30 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -3915,45 +3915,6 @@ static void cursor_connect(RedWorker *worker, RedClient *client, RedsStream *str
cursor_channel_init(channel, ccc);
}
-static void region_to_qxlrects(QRegion *region, QXLRect *qxl_rects, uint32_t num_rects)
-{
- SpiceRect *rects;
- int i;
-
- rects = spice_new0(SpiceRect, num_rects);
- region_ret_rects(region, rects, num_rects);
- for (i = 0; i < num_rects; i++) {
- qxl_rects[i].top = rects[i].top;
- qxl_rects[i].left = rects[i].left;
- qxl_rects[i].bottom = rects[i].bottom;
- qxl_rects[i].right = rects[i].right;
- }
- free(rects);
-}
-
-void display_channel_update(DisplayChannel *display,
- uint32_t surface_id, const QXLRect *area, uint32_t clear_dirty,
- QXLRect **qxl_dirty_rects, uint32_t *num_dirty_rects)
-{
- SpiceRect rect;
- RedSurface *surface;
-
- spice_return_if_fail(validate_surface(display, surface_id));
-
- red_get_rect_ptr(&rect, area);
- display_channel_draw(display, &rect, surface_id);
-
- surface = &display->surfaces[surface_id];
- if (!*qxl_dirty_rects) {
- *num_dirty_rects = pixman_region32_n_rects(&surface->draw_dirty_region);
- *qxl_dirty_rects = spice_new0(QXLRect, *num_dirty_rects);
- }
-
- region_to_qxlrects(&surface->draw_dirty_region, *qxl_dirty_rects, *num_dirty_rects);
- if (clear_dirty)
- region_clear(&surface->draw_dirty_region);
-}
-
static void handle_dev_update_async(void *opaque, void *payload)
{
RedWorker *worker = opaque;
commit 0ebb539f48f3a504191d9a7429893cf7cf75c640
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date: Fri Sep 27 17:54:44 2013 +0200
worker: move destroy_surface() familly
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/server/dcc.c b/server/dcc.c
index e3b0c55..6c089da 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -22,6 +22,8 @@
#include "dcc.h"
#include "display-channel.h"
+#define DISPLAY_CLIENT_SHORT_TIMEOUT 15000000000ULL //nano
+
static SurfaceCreateItem *surface_create_item_new(RedChannel* channel,
uint32_t surface_id, uint32_t width,
uint32_t height, uint32_t format, uint32_t flags)
@@ -41,6 +43,84 @@ static SurfaceCreateItem *surface_create_item_new(RedChannel* channel,
return create;
}
+/*
+ * Return: TRUE if wait_if_used == FALSE, or otherwise, if all of the pipe items that
+ * are related to the surface have been cleared (or sent) from the pipe.
+ */
+int dcc_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface_id,
+ int wait_if_used)
+{
+ Ring *ring;
+ PipeItem *item;
+ int x;
+ RedChannelClient *rcc;
+
+ spice_return_val_if_fail(dcc != NULL, TRUE);
+ /* removing the newest drawables that their destination is surface_id and
+ no other drawable depends on them */
+
+ rcc = RED_CHANNEL_CLIENT(dcc);
+ ring = &rcc->pipe;
+ item = (PipeItem *) ring;
+ while ((item = (PipeItem *)ring_next(ring, (RingItem *)item))) {
+ Drawable *drawable;
+ DrawablePipeItem *dpi = NULL;
+ int depend_found = FALSE;
+
+ if (item->type == PIPE_ITEM_TYPE_DRAW) {
+ dpi = SPICE_CONTAINEROF(item, DrawablePipeItem, dpi_pipe_item);
+ drawable = dpi->drawable;
+ } else if (item->type == PIPE_ITEM_TYPE_UPGRADE) {
+ drawable = ((UpgradeItem *)item)->drawable;
+ } else {
+ continue;
+ }
+
+ if (drawable->surface_id == surface_id) {
+ PipeItem *tmp_item = item;
+ item = (PipeItem *)ring_prev(ring, (RingItem *)item);
+ red_channel_client_pipe_remove_and_release(rcc, tmp_item);
+ if (!item) {
+ item = (PipeItem *)ring;
+ }
+ continue;
+ }
+
+ for (x = 0; x < 3; ++x) {
+ if (drawable->surface_deps[x] == surface_id) {
+ depend_found = TRUE;
+ break;
+ }
+ }
+
+ if (depend_found) {
+ spice_debug("surface %d dependent item found %p, %p", surface_id, drawable, item);
+ if (wait_if_used) {
+ break;
+ } else {
+ return TRUE;
+ }
+ }
+ }
+
+ if (!wait_if_used) {
+ return TRUE;
+ }
+
+ if (item) {
+ return red_channel_client_wait_pipe_item_sent(RED_CHANNEL_CLIENT(dcc), item,
+ DISPLAY_CLIENT_TIMEOUT);
+ } else {
+ /*
+ * in case that the pipe didn't contain any item that is dependent on the surface, but
+ * there is one during sending. Use a shorter timeout, since it is just one item
+ */
+ return red_channel_client_wait_outgoing_item(RED_CHANNEL_CLIENT(dcc),
+ DISPLAY_CLIENT_SHORT_TIMEOUT);
+ }
+ return TRUE;
+}
+
void dcc_create_surface(DisplayChannelClient *dcc, int surface_id)
{
DisplayChannel *display;
diff --git a/server/dcc.h b/server/dcc.h
index dc6f1e7..c5767c9 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -201,6 +201,8 @@ void dcc_release_item (DisplayCha
int item_pushed);
void dcc_send_item (DisplayChannelClient *dcc,
PipeItem *item);
+int dcc_clear_surface_drawables_from_pipe (DisplayChannelClient *dcc,
+ int surface_id, int force);
typedef struct compress_send_data_t {
void* comp_buf;
diff --git a/server/display-channel.c b/server/display-channel.c
index 4190ac4..1ed0568 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1419,6 +1419,73 @@ void display_channel_draw(DisplayChannel *display, const SpiceRect *area, int su
surface_update_dest(surface, area);
}
+static void clear_surface_drawables_from_pipes(DisplayChannel *display, int surface_id,
+ int wait_if_used)
+{
+ RingItem *item, *next;
+ DisplayChannelClient *dcc;
+
+ FOREACH_DCC(display, item, next, dcc) {
+ if (!dcc_clear_surface_drawables_from_pipe(dcc, surface_id, wait_if_used)) {
+ red_channel_client_disconnect(RED_CHANNEL_CLIENT(dcc));
+ }
+ }
+}
+
+/* TODO: cleanup/refactor destroy functions */
+void display_channel_destroy_surface(DisplayChannel *display, uint32_t surface_id)
+{
+ draw_depend_on_me(display, surface_id);
+ /* note that draw_depend_on_me must be called before current_remove_all.
+ otherwise "current" will hold items that other drawables may depend on, and then
+ current_remove_all will remove them from the pipe. */
+ current_remove_all(display, surface_id);
+ clear_surface_drawables_from_pipes(display, surface_id, FALSE);
+ display_channel_surface_unref(display, surface_id);
+}
+
+void display_channel_destroy_surface_wait(DisplayChannel *display, uint32_t surface_id)
+{
+ if (!validate_surface(display, surface_id))
+ return;
+ if (!display->surfaces[surface_id].context.canvas)
+ return;
+
+ draw_depend_on_me(display, surface_id);
+ /* note that draw_depend_on_me must be called before current_remove_all.
+ otherwise "current" will hold items that other drawables may depend on, and then
+ current_remove_all will remove them from the pipe. */
+ current_remove_all(display, surface_id);
+ clear_surface_drawables_from_pipes(display, surface_id, TRUE);
+}
+
+/* called upon device reset */
+/* TODO: split me*/
+void display_channel_destroy_surfaces(DisplayChannel *display)
+{
+ int i;
+
+ spice_debug(NULL);
+ //to handle better
+ for (i = 0; i < NUM_SURFACES; ++i) {
+ if (display->surfaces[i].context.canvas) {
+ display_channel_destroy_surface_wait(display, i);
+ if (display->surfaces[i].context.canvas) {
+ display_channel_surface_unref(display, i);
+ }
+ spice_assert(!display->surfaces[i].context.canvas);
+ }
+ }
+ spice_warn_if_fail(ring_is_empty(&display->streams));
+
+ if (red_channel_is_connected(RED_CHANNEL(display))) {
+ red_channel_pipes_add_type(RED_CHANNEL(display), PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE);
+ red_pipes_add_verb(RED_CHANNEL(display), SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL);
+ }
+
+ display_channel_free_glz_drawables(display);
+}
+
static void on_disconnect(RedChannelClient *rcc)
{
DisplayChannel *display;
diff --git a/server/display-channel.h b/server/display-channel.h
index 90d7f80..e74941a 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -284,6 +284,11 @@ int display_channel_wait_for_migrate_data (DisplayCha
void display_channel_flush_all_surfaces (DisplayChannel *display);
void display_channel_free_glz_drawables_to_free(DisplayChannel *display);
void display_channel_free_glz_drawables (DisplayChannel *display);
+void display_channel_destroy_surface_wait (DisplayChannel *display,
+ uint32_t surface_id);
+void display_channel_destroy_surfaces (DisplayChannel *display);
+void display_channel_destroy_surface (DisplayChannel *display,
+ uint32_t surface_id);
static inline int validate_surface(DisplayChannel *display, uint32_t surface_id)
{
@@ -415,6 +420,21 @@ static inline void region_add_clip_rects(QRegion *rgn, SpiceClipRects *data)
}
}
+static inline void draw_depend_on_me(DisplayChannel *display, uint32_t surface_id)
+{
+ RedSurface *surface;
+ RingItem *ring_item;
+
+ surface = &display->surfaces[surface_id];
+
+ while ((ring_item = ring_get_tail(&surface->depend_on_me))) {
+ Drawable *drawable;
+ DependItem *depended_item = SPICE_CONTAINEROF(ring_item, DependItem, ring_item);
+ drawable = depended_item->drawable;
+ display_channel_draw(display, &drawable->red_drawable->bbox, drawable->surface_id);
+ }
+}
+
void current_remove_drawable(DisplayChannel *display, Drawable *item);
void red_pipes_remove_drawable(Drawable *drawable);
void current_remove(DisplayChannel *display, TreeItem *item);
diff --git a/server/red_worker.c b/server/red_worker.c
index f792ea3..3709691 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -72,8 +72,6 @@
#define CMD_RING_POLL_TIMEOUT 10 //milli
#define CMD_RING_POLL_RETRIES 200
-#define DISPLAY_CLIENT_SHORT_TIMEOUT 15000000000ULL //nano
-
#define MAX_EVENT_SOURCES 20
#define INF_EVENT_WAIT ~0
@@ -334,101 +332,6 @@ void current_remove_all(DisplayChannel *display, int surface_id)
}
}
-/*
- * Return: TRUE if wait_if_used == FALSE, or otherwise, if all of the pipe items that
- * are related to the surface have been cleared (or sent) from the pipe.
- */
-static int red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface_id,
- int wait_if_used)
-{
- Ring *ring;
- PipeItem *item;
- int x;
- RedChannelClient *rcc;
-
- if (!dcc) {
- return TRUE;
- }
-
- /* removing the newest drawables that their destination is surface_id and
- no other drawable depends on them */
-
- rcc = RED_CHANNEL_CLIENT(dcc);
- ring = &rcc->pipe;
- item = (PipeItem *) ring;
- while ((item = (PipeItem *)ring_next(ring, (RingItem *)item))) {
- Drawable *drawable;
- DrawablePipeItem *dpi = NULL;
- int depend_found = FALSE;
-
- if (item->type == PIPE_ITEM_TYPE_DRAW) {
- dpi = SPICE_CONTAINEROF(item, DrawablePipeItem, dpi_pipe_item);
- drawable = dpi->drawable;
- } else if (item->type == PIPE_ITEM_TYPE_UPGRADE) {
- drawable = ((UpgradeItem *)item)->drawable;
- } else {
- continue;
- }
-
- if (drawable->surface_id == surface_id) {
- PipeItem *tmp_item = item;
- item = (PipeItem *)ring_prev(ring, (RingItem *)item);
- red_channel_client_pipe_remove_and_release(rcc, tmp_item);
- if (!item) {
- item = (PipeItem *)ring;
- }
- continue;
- }
-
- for (x = 0; x < 3; ++x) {
- if (drawable->surface_deps[x] == surface_id) {
- depend_found = TRUE;
- break;
- }
- }
-
- if (depend_found) {
- spice_debug("surface %d dependent item found %p, %p", surface_id, drawable, item);
- if (wait_if_used) {
- break;
- } else {
- return TRUE;
- }
- }
- }
-
- if (!wait_if_used) {
- return TRUE;
- }
-
- if (item) {
- return red_channel_client_wait_pipe_item_sent(RED_CHANNEL_CLIENT(dcc), item,
- DISPLAY_CLIENT_TIMEOUT);
- } else {
- /*
- * in case that the pipe didn't contain any item that is dependent on the surface, but
- * there is one during sending. Use a shorter timeout, since it is just one item
- */
- return red_channel_client_wait_outgoing_item(RED_CHANNEL_CLIENT(dcc),
- DISPLAY_CLIENT_SHORT_TIMEOUT);
- }
- return TRUE;
-}
-
-static void red_clear_surface_drawables_from_pipes(DisplayChannel *display,
- int surface_id,
- int wait_if_used)
-{
- RingItem *item, *next;
- DisplayChannelClient *dcc;
-
- FOREACH_DCC(display, item, next, dcc) {
- if (!red_clear_surface_drawables_from_pipe(dcc, surface_id, wait_if_used)) {
- red_channel_client_disconnect(RED_CHANNEL_CLIENT(dcc));
- }
- }
-}
-
static int red_display_drawable_is_in_pipe(DisplayChannelClient *dcc, Drawable *drawable)
{
DrawablePipeItem *dpi;
@@ -697,23 +600,6 @@ static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *re
return drawable;
}
-static inline int red_handle_depends_on_target_surface(DisplayChannel *display, uint32_t surface_id)
-{
- RedSurface *surface;
- RingItem *ring_item;
-
- surface = &display->surfaces[surface_id];
-
- while ((ring_item = ring_get_tail(&surface->depend_on_me))) {
- Drawable *drawable;
- DependItem *depended_item = SPICE_CONTAINEROF(ring_item, DependItem, ring_item);
- drawable = depended_item->drawable;
- display_channel_draw(display, &drawable->red_drawable->bbox, drawable->surface_id);
- }
-
- return TRUE;
-}
-
static inline void add_to_surface_dependency(DisplayChannel *display, int depend_on_surface_id,
DependItem *depend_item, Drawable *drawable)
{
@@ -812,9 +698,7 @@ static inline void red_process_draw(RedWorker *worker, RedDrawable *red_drawable
goto cleanup;
}
- if (!red_handle_depends_on_target_surface(worker->display_channel, surface_id)) {
- goto cleanup;
- }
+ draw_depend_on_me(display, surface_id);
if (!red_handle_surfaces_dependencies(worker->display_channel, drawable)) {
goto cleanup;
@@ -870,16 +754,10 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface
break;
}
set_surface_release_info(&red_surface->destroy, surface->release_info, group_id);
- red_handle_depends_on_target_surface(display, surface_id);
- /* note that red_handle_depends_on_target_surface must be called before current_remove_all.
- otherwise "current" will hold items that other drawables may depend on, and then
- current_remove_all will remove them from the pipe. */
- current_remove_all(display, surface_id);
- red_clear_surface_drawables_from_pipes(display, surface_id, FALSE);
- display_channel_surface_unref(display, surface_id);
+ display_channel_destroy_surface(display, surface_id);
break;
default:
- spice_error("unknown surface command");
+ spice_warn_if_reached();
};
exit:
red_put_surface_cmd(surface);
@@ -4119,21 +3997,6 @@ static void handle_dev_del_memslot(void *opaque, void *payload)
red_memslot_info_del_slot(&worker->mem_slots, slot_group_id, slot_id);
}
-void display_channel_destroy_surface_wait(DisplayChannel *display, int surface_id)
-{
- if (!validate_surface(display, surface_id))
- return;
- if (!display->surfaces[surface_id].context.canvas)
- return;
-
- red_handle_depends_on_target_surface(display, surface_id);
- /* note that red_handle_depends_on_target_surface must be called before current_remove_all.
- otherwise "current" will hold items that other drawables may depend on, and then
- current_remove_all will remove them from the pipe. */
- current_remove_all(display, surface_id);
- red_clear_surface_drawables_from_pipes(display, surface_id, TRUE);
-}
-
static void handle_dev_destroy_surface_wait(void *opaque, void *payload)
{
RedWorkerMessageDestroySurfaceWait *msg = payload;
@@ -4145,34 +4008,6 @@ static void handle_dev_destroy_surface_wait(void *opaque, void *payload)
display_channel_destroy_surface_wait(worker->display_channel, msg->surface_id);
}
-/* called upon device reset */
-
-/* TODO: split me*/
-void display_channel_destroy_surfaces(DisplayChannel *display)
-{
- int i;
-
- spice_debug(NULL);
- //to handle better
- for (i = 0; i < NUM_SURFACES; ++i) {
- if (display->surfaces[i].context.canvas) {
- display_channel_destroy_surface_wait(display, i);
- if (display->surfaces[i].context.canvas) {
- display_channel_surface_unref(display, i);
- }
- spice_assert(!display->surfaces[i].context.canvas);
- }
- }
- spice_warn_if_fail(ring_is_empty(&display->streams));
-
- if (red_channel_is_connected(RED_CHANNEL(display))) {
- red_channel_pipes_add_type(RED_CHANNEL(display), PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE);
- red_pipes_add_verb(RED_CHANNEL(display), SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL);
- }
-
- display_channel_free_glz_drawables(display);
-}
-
static void handle_dev_destroy_surfaces(void *opaque, void *payload)
{
RedWorker *worker = opaque;
@@ -4738,6 +4573,8 @@ static void register_callbacks(Dispatcher *dispatcher)
dispatcher_register_async_done_callback(
dispatcher,
worker_handle_dispatcher_async_done);
+
+ /* TODO: register cursor & display specific msg in respective channel files */
dispatcher_register_handler(dispatcher,
RED_WORKER_MESSAGE_DISPLAY_CONNECT,
handle_dev_display_connect,
commit 9c828e8553a4ef6e3ab291bfde7b18fe18a2cd81
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date: Fri Sep 27 17:23:02 2013 +0200
worker: move display_channel_new
Acked-by: Frediano Ziglio <fziglio at redhat.com>
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 e158d59..4190ac4 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1418,3 +1418,152 @@ void display_channel_draw(DisplayChannel *display, const SpiceRect *area, int su
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_assert(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 391e4ab..90d7f80 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 19ee4e6..f792ea3 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)
@@ -3447,12 +3390,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);
@@ -3546,37 +3496,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
@@ -3823,29 +3742,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);
@@ -4028,94 +3924,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_assert(item);
- 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;
@@ -5173,7 +4981,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;
}
More information about the Spice-commits
mailing list