[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