[Spice-devel] [PATCH 04/18] worker: move dcc_add_drawable*
Frediano Ziglio
fziglio at redhat.com
Fri Nov 20 03:17:28 PST 2015
From: Marc-André Lureau <marcandre.lureau at gmail.com>
---
server/dcc.c | 82 +++++++++++++++++++++++++++
server/dcc.h | 17 ++++++
server/display-channel.c | 65 +++++++++++++++++----
server/display-channel.h | 19 +------
server/red_worker.c | 144 +----------------------------------------------
5 files changed, 158 insertions(+), 169 deletions(-)
diff --git a/server/dcc.c b/server/dcc.c
index 8cc2c0a..a17fa7d 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -93,6 +93,88 @@ void dcc_push_surface_image(DisplayChannelClient *dcc, int surface_id)
red_channel_client_push(RED_CHANNEL_CLIENT(dcc));
}
+static void add_drawable_surface_images(DisplayChannelClient *dcc, Drawable *drawable)
+{
+ DisplayChannel *display = DCC_TO_DC(dcc);
+ int x;
+
+ for (x = 0; x < 3; ++x) {
+ int surface_id;
+
+ surface_id = drawable->surface_deps[x];
+ if (surface_id != -1) {
+ if (dcc->surface_client_created[surface_id] == TRUE) {
+ continue;
+ }
+ dcc_create_surface(dcc, surface_id);
+ display_channel_current_flush(display, surface_id);
+ dcc_push_surface_image(dcc, surface_id);
+ }
+ }
+
+ if (dcc->surface_client_created[drawable->surface_id] == TRUE) {
+ return;
+ }
+
+ dcc_create_surface(dcc, drawable->surface_id);
+ display_channel_current_flush(display, drawable->surface_id);
+ dcc_push_surface_image(dcc, drawable->surface_id);
+}
+
+DrawablePipeItem *drawable_pipe_item_ref(DrawablePipeItem *dpi)
+{
+ dpi->refs++;
+ return dpi;
+}
+
+void drawable_pipe_item_unref(DrawablePipeItem *dpi)
+{
+ DisplayChannel *display = DCC_TO_DC(dpi->dcc);
+
+ if (--dpi->refs != 0)
+ return;
+
+ spice_return_if_fail(!ring_item_is_linked(&dpi->dpi_pipe_item.link));
+ spice_return_if_fail(!ring_item_is_linked(&dpi->base));
+ display_channel_drawable_unref(display, dpi->drawable);
+ free(dpi);
+}
+
+static DrawablePipeItem *drawable_pipe_item_new(DisplayChannelClient *dcc, Drawable *drawable)
+{
+ DrawablePipeItem *dpi;
+
+ dpi = spice_malloc0(sizeof(*dpi));
+ dpi->drawable = drawable;
+ dpi->dcc = dcc;
+ ring_item_init(&dpi->base);
+ ring_add(&drawable->pipes, &dpi->base);
+ red_channel_pipe_item_init(RED_CHANNEL_CLIENT(dcc)->channel,
+ &dpi->dpi_pipe_item, PIPE_ITEM_TYPE_DRAW);
+ dpi->refs++;
+ drawable->refs++;
+ return dpi;
+}
+
+void dcc_add_drawable(DisplayChannelClient *dcc, Drawable *drawable, bool to_tail)
+{
+ DrawablePipeItem *dpi = drawable_pipe_item_new(dcc, drawable);
+
+ add_drawable_surface_images(dcc, drawable);
+ if (to_tail)
+ red_channel_client_pipe_add_tail(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item);
+ else
+ red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item);
+}
+
+void dcc_add_drawable_after(DisplayChannelClient *dcc, Drawable *drawable, PipeItem *pos)
+{
+ DrawablePipeItem *dpi = drawable_pipe_item_new(dcc, drawable);
+
+ add_drawable_surface_images(dcc, drawable);
+ red_channel_client_pipe_add_after(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item, pos);
+}
+
static void dcc_init_stream_agents(DisplayChannelClient *dcc)
{
int i;
diff --git a/server/dcc.h b/server/dcc.h
index c62c3c9..f7c01a1 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -135,6 +135,17 @@ typedef struct ImageItem {
uint8_t data[0];
} ImageItem;
+typedef struct DrawablePipeItem {
+ RingItem base; /* link for a list of pipe items held by Drawable */
+ PipeItem dpi_pipe_item; /* link for the client's pipe itself */
+ Drawable *drawable;
+ DisplayChannelClient *dcc;
+ uint8_t refs;
+} DrawablePipeItem;
+
+void drawable_pipe_item_unref (DrawablePipeItem *dpi);
+DrawablePipeItem* drawable_pipe_item_ref (DrawablePipeItem *dpi);
+
DisplayChannelClient* dcc_new (DisplayChannel *display,
RedClient *client,
RedsStream *stream,
@@ -169,6 +180,12 @@ void dcc_palette_cache_palette (DisplayCha
uint8_t *flags);
int dcc_pixmap_cache_unlocked_add (DisplayChannelClient *dcc,
uint64_t id, uint32_t size, int lossy);
+void dcc_add_drawable (DisplayChannelClient *dcc,
+ Drawable *drawable,
+ bool to_tail);
+void dcc_add_drawable_after (DisplayChannelClient *dcc,
+ Drawable *drawable,
+ PipeItem *pos);
typedef struct compress_send_data_t {
void* comp_buf;
diff --git a/server/display-channel.c b/server/display-channel.c
index d455a0d..ecf6f7d 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -325,6 +325,50 @@ static void streams_update_visible_region(DisplayChannel *display, Drawable *dra
}
}
+static void pipes_add_drawable(DisplayChannel *display, Drawable *drawable)
+{
+ DisplayChannelClient *dcc;
+ RingItem *dcc_ring_item, *next;
+
+ spice_warn_if(!ring_is_empty(&drawable->pipes));
+ FOREACH_DCC(display, dcc_ring_item, next, dcc) {
+ dcc_add_drawable(dcc, drawable, FALSE);
+ }
+}
+
+static void pipes_add_drawable_after(DisplayChannel *display,
+ Drawable *drawable, Drawable *pos_after)
+{
+ DrawablePipeItem *dpi_pos_after;
+ RingItem *dpi_link, *dpi_next;
+ DisplayChannelClient *dcc;
+ int num_other_linked = 0;
+
+ DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next, dpi_pos_after) {
+ num_other_linked++;
+ dcc_add_drawable_after(dpi_pos_after->dcc, drawable, &dpi_pos_after->dpi_pipe_item);
+ }
+ if (num_other_linked == 0) {
+ pipes_add_drawable(display, drawable);
+ return;
+ }
+ if (num_other_linked != display->common.base.clients_num) {
+ RingItem *item, *next;
+ spice_debug("TODO: not O(n^2)");
+ FOREACH_DCC(display, item, next, dcc) {
+ int sent = 0;
+ DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next, dpi_pos_after) {
+ if (dpi_pos_after->dcc == dcc) {
+ sent = 1;
+ break;
+ }
+ }
+ if (!sent) {
+ dcc_add_drawable(dcc, drawable, FALSE);
+ }
+ }
+ }
+}
static void current_add_drawable(DisplayChannel *display,
Drawable *drawable, RingItem *pos)
@@ -366,9 +410,9 @@ static int current_add_equal(DisplayChannel *display, DrawItem *item, TreeItem *
other_drawable->refs++;
current_remove_drawable(display, other_drawable);
if (add_after) {
- red_pipes_add_drawable_after(display, drawable, other_drawable);
+ pipes_add_drawable_after(display, drawable, other_drawable);
} else {
- red_pipes_add_drawable(display, drawable);
+ pipes_add_drawable(display, drawable);
}
red_pipes_remove_drawable(other_drawable);
display_channel_drawable_unref(display, other_drawable);
@@ -396,7 +440,7 @@ static int current_add_equal(DisplayChannel *display, DrawItem *item, TreeItem *
common.base.channel_link);
dpi = SPICE_CONTAINEROF(dpi_ring_item, DrawablePipeItem, base);
while (worker_ring_item && (!dpi || dcc != dpi->dcc)) {
- dcc_add_drawable(dcc, drawable);
+ dcc_add_drawable(dcc, drawable, FALSE);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
@@ -423,7 +467,7 @@ static int current_add_equal(DisplayChannel *display, DrawItem *item, TreeItem *
current_add_drawable(display, drawable, &other->siblings_link);
red_pipes_remove_drawable(other_drawable);
current_remove_drawable(display, other_drawable);
- red_pipes_add_drawable(display, drawable);
+ pipes_add_drawable(display, drawable);
return TRUE;
}
break;
@@ -787,25 +831,26 @@ void display_channel_print_stats(DisplayChannel *display)
#endif
}
-int display_channel_add_drawable(DisplayChannel *display, Drawable *drawable)
+void display_channel_add_drawable(DisplayChannel *display, Drawable *drawable)
{
- int ret = FALSE, surface_id = drawable->surface_id;
+ int success = FALSE, surface_id = drawable->surface_id;
RedDrawable *red_drawable = drawable->red_drawable;
Ring *ring = &display->surfaces[surface_id].current;
if (has_shadow(red_drawable)) {
- ret = current_add_with_shadow(display, ring, drawable);
+ success = current_add_with_shadow(display, ring, drawable);
} else {
drawable->streamable = drawable_can_stream(display, drawable);
- ret = current_add(display, ring, drawable);
+ success = current_add(display, ring, drawable);
}
+ if (success)
+ pipes_add_drawable(display, drawable);
+
#ifdef RED_WORKER_STAT
if ((++display->add_count % 100) == 0)
display_channel_print_stats(display);
#endif
-
- return ret;
}
int display_channel_wait_for_migrate_data(DisplayChannel *display)
diff --git a/server/display-channel.h b/server/display-channel.h
index bad61d1..233c391 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -113,19 +113,6 @@ enum {
PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT,
};
-typedef struct DrawablePipeItem {
- RingItem base; /* link for a list of pipe items held by Drawable */
- PipeItem dpi_pipe_item; /* link for the client's pipe itself */
- Drawable *drawable;
- DisplayChannelClient *dcc;
- uint8_t refs;
-} DrawablePipeItem;
-
-DrawablePipeItem* drawable_pipe_item_new (DisplayChannelClient *dcc,
- Drawable *drawable);
-void drawable_pipe_item_unref (DrawablePipeItem *dpi);
-DrawablePipeItem* drawable_pipe_item_ref (DrawablePipeItem *dpi);
-
typedef struct MonitorsConfig {
int refs;
int count;
@@ -270,7 +257,7 @@ void display_channel_surface_unref (DisplayCha
uint32_t surface_id);
bool display_channel_surface_has_canvas (DisplayChannel *display,
uint32_t surface_id);
-int display_channel_add_drawable (DisplayChannel *display,
+void display_channel_add_drawable (DisplayChannel *display,
Drawable *drawable);
void display_channel_current_flush (DisplayChannel *display,
int surface_id);
@@ -394,12 +381,8 @@ static inline void region_add_clip_rects(QRegion *rgn, SpiceClipRects *data)
}
}
-void red_pipes_add_drawable(DisplayChannel *display, Drawable *drawable);
void current_remove_drawable(DisplayChannel *display, Drawable *item);
-void red_pipes_add_drawable_after(DisplayChannel *display,
- Drawable *drawable, Drawable *pos_after);
void red_pipes_remove_drawable(Drawable *drawable);
-void dcc_add_drawable(DisplayChannelClient *dcc, Drawable *drawable);
void current_remove(DisplayChannel *display, TreeItem *item);
void detach_streams_behind(DisplayChannel *display, QRegion *region, Drawable *drawable);
diff --git a/server/red_worker.c b/server/red_worker.c
index f6dfe28..b8dfbb9 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -191,44 +191,6 @@ static void red_create_surface(DisplayChannel *display, uint32_t surface_id, uin
uint32_t height, int32_t stride, uint32_t format,
void *line_0, int data_is_valid, int send_client);
-/* fixme: move to display channel */
-DrawablePipeItem *drawable_pipe_item_new(DisplayChannelClient *dcc,
- Drawable *drawable)
-{
- DrawablePipeItem *dpi;
-
- dpi = spice_malloc0(sizeof(*dpi));
- dpi->drawable = drawable;
- dpi->dcc = dcc;
- ring_item_init(&dpi->base);
- ring_add(&drawable->pipes, &dpi->base);
- red_channel_pipe_item_init(RED_CHANNEL_CLIENT(dcc)->channel,
- &dpi->dpi_pipe_item, PIPE_ITEM_TYPE_DRAW);
- dpi->refs++;
- drawable->refs++;
- return dpi;
-}
-
-DrawablePipeItem *drawable_pipe_item_ref(DrawablePipeItem *dpi)
-{
- dpi->refs++;
- return dpi;
-}
-
-void drawable_pipe_item_unref(DrawablePipeItem *dpi)
-{
- DisplayChannel *display = DCC_TO_DC(dpi->dcc);
-
- if (--dpi->refs != 0) {
- return;
- }
-
- spice_return_if_fail(!ring_item_is_linked(&dpi->dpi_pipe_item.link));
- spice_return_if_fail(!ring_item_is_linked(&dpi->base));
- display_channel_drawable_unref(display, dpi->drawable);
- free(dpi);
-}
-
QXLInstance* red_worker_get_qxl(RedWorker *worker)
{
spice_return_val_if_fail(worker != NULL, NULL);
@@ -252,35 +214,6 @@ static inline int validate_surface(DisplayChannel *display, uint32_t surface_id)
}
-static inline void red_handle_drawable_surfaces_client_synced(
- DisplayChannelClient *dcc, Drawable *drawable)
-{
- DisplayChannel *display = DCC_TO_DC(dcc);
- int x;
-
- for (x = 0; x < 3; ++x) {
- int surface_id;
-
- surface_id = drawable->surface_deps[x];
- if (surface_id != -1) {
- if (dcc->surface_client_created[surface_id] == TRUE) {
- continue;
- }
- dcc_create_surface(dcc, surface_id);
- display_channel_current_flush(display, surface_id);
- dcc_push_surface_image(dcc, surface_id);
- }
- }
-
- if (dcc->surface_client_created[drawable->surface_id] == TRUE) {
- return;
- }
-
- dcc_create_surface(dcc, drawable->surface_id);
- display_channel_current_flush(display, drawable->surface_id);
- dcc_push_surface_image(dcc, drawable->surface_id);
-}
-
static int display_is_connected(RedWorker *worker)
{
return (worker->display_channel && red_channel_is_connected(
@@ -293,76 +226,6 @@ static int cursor_is_connected(RedWorker *worker)
red_channel_is_connected(RED_CHANNEL(worker->cursor_channel));
}
-void dcc_add_drawable(DisplayChannelClient *dcc, Drawable *drawable)
-{
- DrawablePipeItem *dpi;
-
- red_handle_drawable_surfaces_client_synced(dcc, drawable);
- dpi = drawable_pipe_item_new(dcc, drawable);
- red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item);
-}
-
-void red_pipes_add_drawable(DisplayChannel *display, Drawable *drawable)
-{
- DisplayChannelClient *dcc;
- RingItem *dcc_ring_item, *next;
-
- spice_warn_if(!ring_is_empty(&drawable->pipes));
- FOREACH_DCC(display, dcc_ring_item, next, dcc) {
- dcc_add_drawable(dcc, drawable);
- }
-}
-
-static void dcc_add_drawable_to_tail(DisplayChannelClient *dcc, Drawable *drawable)
-{
- DrawablePipeItem *dpi;
-
- if (!dcc) {
- return;
- }
- red_handle_drawable_surfaces_client_synced(dcc, drawable);
- dpi = drawable_pipe_item_new(dcc, drawable);
- red_channel_client_pipe_add_tail(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item);
-}
-
-void red_pipes_add_drawable_after(DisplayChannel *display,
- Drawable *drawable, Drawable *pos_after)
-{
- DrawablePipeItem *dpi, *dpi_pos_after;
- RingItem *dpi_link, *dpi_next;
- DisplayChannelClient *dcc;
- int num_other_linked = 0;
-
- DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next, dpi_pos_after) {
- num_other_linked++;
- dcc = dpi_pos_after->dcc;
- red_handle_drawable_surfaces_client_synced(dcc, drawable);
- dpi = drawable_pipe_item_new(dcc, drawable);
- red_channel_client_pipe_add_after(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item,
- &dpi_pos_after->dpi_pipe_item);
- }
- if (num_other_linked == 0) {
- red_pipes_add_drawable(display, drawable);
- return;
- }
- if (num_other_linked != display->common.base.clients_num) {
- RingItem *item, *next;
- spice_debug("TODO: not O(n^2)");
- FOREACH_DCC(display, item, next, dcc) {
- int sent = 0;
- DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next, dpi_pos_after) {
- if (dpi_pos_after->dcc == dcc) {
- sent = 1;
- break;
- }
- }
- if (!sent) {
- dcc_add_drawable(dcc, drawable);
- }
- }
- }
-}
-
static inline PipeItem *red_pipe_get_tail(DisplayChannelClient *dcc)
{
if (!dcc) {
@@ -1226,9 +1089,8 @@ static inline void red_process_draw(RedWorker *worker, RedDrawable *red_drawable
goto cleanup;
}
- if (display_channel_add_drawable(worker->display_channel, drawable)) {
- red_pipes_add_drawable(worker->display_channel, drawable);
- }
+ display_channel_add_drawable(worker->display_channel, drawable);
+
cleanup:
display_channel_drawable_unref(display, drawable);
}
@@ -2509,7 +2371,7 @@ static void red_add_lossless_drawable_dependencies(RedChannelClient *rcc,
if (!sync_rendered) {
// pushing the pipe item back to the pipe
- dcc_add_drawable_to_tail(dcc, item);
+ dcc_add_drawable(dcc, item, TRUE);
// the surfaces areas will be sent as DRAW_COPY commands, that
// will be executed before the current drawable
for (i = 0; i < num_deps; i++) {
--
2.4.3
More information about the Spice-devel
mailing list