[Spice-devel] [PATCH 09/10] worker: move drawable to display

Frediano Ziglio fziglio at redhat.com
Fri Nov 6 03:02:05 PST 2015


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

---
 server/display-channel.h |  24 ++++++++--
 server/red_worker.c      | 117 ++++++++++++++++++++++-------------------------
 2 files changed, 74 insertions(+), 67 deletions(-)

diff --git a/server/display-channel.h b/server/display-channel.h
index 1871cb0..f981d27 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -273,6 +273,15 @@ void                       monitors_config_unref                     (MonitorsCo
 #define NUM_TRACE_ITEMS (1 << TRACE_ITEMS_SHIFT)
 #define ITEMS_TRACE_MASK (NUM_TRACE_ITEMS - 1)
 
+#define NUM_DRAWABLES 1000
+typedef struct _Drawable _Drawable;
+struct _Drawable {
+    union {
+        Drawable drawable;
+        _Drawable *next;
+    } u;
+};
+
 struct DisplayChannel {
     CommonChannel common; // Must be the first thing
 
@@ -281,16 +290,17 @@ struct DisplayChannel {
     uint32_t num_renderers;
     uint32_t renderers[RED_RENDERER_LAST];
     uint32_t renderer;
-
-    Ring current_list; // of TreeItem
-    uint32_t current_size;
-
     int enable_jpeg;
     int jpeg_quality;
     int enable_zlib_glz_wrap;
     int zlib_level;
 
-    RedCompressBuf *free_compress_bufs;
+    Ring current_list; // of TreeItem
+    uint32_t current_size;
+
+    uint32_t drawable_count;
+    _Drawable drawables[NUM_DRAWABLES];
+    _Drawable *free_drawables;
 
     int stream_video;
     uint32_t stream_count;
@@ -302,6 +312,7 @@ struct DisplayChannel {
     uint64_t streams_size_total;
 
     ImageCache image_cache;
+    RedCompressBuf *free_compress_bufs;
 
 #ifdef RED_STATISTICS
     uint64_t *cache_hits_counter;
@@ -344,5 +355,8 @@ void                       display_channel_attach_stream             (DisplayCha
 int                        display_channel_get_streams_timeout       (DisplayChannel *display);
 void                       display_channel_compress_stats_print      (const DisplayChannel *display);
 void                       display_channel_compress_stats_reset      (DisplayChannel *display);
+void                       display_channel_drawable_unref            (DisplayChannel *display, Drawable *drawable);
+
+
 
 #endif /* DISPLAY_CHANNEL_H_ */
diff --git a/server/red_worker.c b/server/red_worker.c
index c51f160..20b72a3 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -300,14 +300,6 @@ struct RedGlzDrawable {
 pthread_mutex_t glz_dictionary_list_lock = PTHREAD_MUTEX_INITIALIZER;
 Ring glz_dictionary_list = {&glz_dictionary_list, &glz_dictionary_list};
 
-typedef struct _Drawable _Drawable;
-struct _Drawable {
-    union {
-        Drawable drawable;
-        _Drawable *next;
-    } u;
-};
-
 typedef struct DrawContext {
     SpiceCanvas *canvas;
     int canvas_draws_on_surface;
@@ -332,7 +324,6 @@ typedef struct RedSurface {
     QXLReleaseInfoExt create, destroy;
 } RedSurface;
 
-#define NUM_DRAWABLES 1000
 #define NUM_CURSORS 100
 
 typedef struct RedWorker {
@@ -355,7 +346,6 @@ typedef struct RedWorker {
     uint32_t n_surfaces;
     SpiceImageSurfaces image_surfaces;
 
-    uint32_t drawable_count;
     uint32_t red_drawable_count;
     uint32_t glz_drawable_count;
     uint32_t transparent_count;
@@ -365,9 +355,6 @@ typedef struct RedWorker {
 
     uint32_t bits_unique;
 
-    _Drawable drawables[NUM_DRAWABLES];
-    _Drawable *free_drawables;
-
     RedMemSlotInfo mem_slots;
 
     SpiceImageCompression image_compression;
@@ -441,7 +428,6 @@ static void red_draw_drawable(RedWorker *worker, Drawable *item);
 static void red_update_area(RedWorker *worker, const SpiceRect *area, int surface_id);
 static void red_update_area_till(RedWorker *worker, const SpiceRect *area, int surface_id,
                                  Drawable *last);
-static void red_worker_drawable_unref(RedWorker *worker, Drawable *drawable);
 static inline void display_channel_stream_maintenance(DisplayChannel *display, Drawable *candidate, Drawable *sect);
 static inline void display_begin_send_message(RedChannelClient *rcc);
 static void red_release_glz(DisplayChannelClient *dcc);
@@ -640,7 +626,7 @@ DrawablePipeItem *drawable_pipe_item_ref(DrawablePipeItem *dpi)
 
 void drawable_pipe_item_unref(DrawablePipeItem *dpi)
 {
-    RedWorker *worker = DCC_TO_WORKER(dpi->dcc);
+    DisplayChannel *display = DCC_TO_DC(dpi->dcc);
 
     if (--dpi->refs != 0) {
         return;
@@ -648,7 +634,7 @@ void drawable_pipe_item_unref(DrawablePipeItem *dpi)
 
     spice_warn_if_fail(!ring_item_is_linked(&dpi->dpi_pipe_item.link));
     spice_warn_if_fail(!ring_item_is_linked(&dpi->base));
-    red_worker_drawable_unref(worker, dpi->drawable);
+    display_channel_drawable_unref(display, dpi->drawable);
     free(dpi);
 }
 
@@ -874,12 +860,12 @@ static void release_image_item(ImageItem *item)
     }
 }
 
-static void release_upgrade_item(RedWorker* worker, UpgradeItem *item)
+static void upgrade_item_unref(DisplayChannel *display, UpgradeItem *item)
 {
     if (--item->refs != 0)
         return;
 
-    red_worker_drawable_unref(worker, item->drawable);
+    display_channel_drawable_unref(display, item->drawable);
     free(item->rects);
     free(item);
 }
@@ -917,30 +903,33 @@ static void red_reset_palette_cache(DisplayChannelClient *dcc)
     red_palette_cache_reset(dcc, CLIENT_PALETTE_CACHE_SIZE);
 }
 
-static inline Drawable *alloc_drawable(RedWorker *worker)
+static Drawable* drawable_try_new(DisplayChannel *display)
 {
     Drawable *drawable;
-    if (!worker->free_drawables) {
+
+    if (!display->free_drawables)
         return NULL;
-    }
-    drawable = &worker->free_drawables->u.drawable;
-    worker->free_drawables = worker->free_drawables->u.next;
+
+    drawable = &display->free_drawables->u.drawable;
+    display->free_drawables = display->free_drawables->u.next;
+    display->drawable_count++;
+
     return drawable;
 }
 
-static inline void free_drawable(RedWorker *worker, Drawable *item)
+static void drawable_free(DisplayChannel *display, Drawable *drawable)
 {
-    ((_Drawable *)item)->u.next = worker->free_drawables;
-    worker->free_drawables = (_Drawable *)item;
+    ((_Drawable *)drawable)->u.next = display->free_drawables;
+    display->free_drawables = (_Drawable *)drawable;
 }
 
-static void drawables_init(RedWorker *worker)
+static void drawables_init(DisplayChannel *display)
 {
     int i;
 
-    worker->free_drawables = NULL;
+    display->free_drawables = NULL;
     for (i = 0; i < NUM_DRAWABLES; i++) {
-        free_drawable(worker, &worker->drawables[i].u.drawable);
+        drawable_free(display, &display->drawables[i].u.drawable);
     }
 }
 
@@ -1035,7 +1024,7 @@ static void remove_depended_item(DependItem *item)
     ring_remove(&item->ring_item);
 }
 
-static inline void red_dec_surfaces_drawable_dependencies(RedWorker *worker, Drawable *drawable)
+static void drawable_unref_surfaces_dest(DisplayChannel *display, Drawable *drawable)
 {
     int x;
     int surface_id;
@@ -1045,11 +1034,11 @@ static inline void red_dec_surfaces_drawable_dependencies(RedWorker *worker, Dra
         if (surface_id == -1) {
             continue;
         }
-        red_surface_unref(worker, surface_id);
+        red_surface_unref(COMMON_CHANNEL(display)->worker, surface_id);
     }
 }
 
-static void remove_drawable_dependencies(RedWorker *worker, Drawable *drawable)
+static void drawable_remove_dependencies(DisplayChannel *display, Drawable *drawable)
 {
     int x;
     int surface_id;
@@ -1065,7 +1054,7 @@ static void remove_drawable_dependencies(RedWorker *worker, Drawable *drawable)
 static void detach_stream(DisplayChannel *display, Stream *stream,
                           int detach_sized);
 
-static void red_worker_drawable_unref(RedWorker *worker, Drawable *drawable)
+void display_channel_drawable_unref(DisplayChannel *display, Drawable *drawable)
 {
     RingItem *item, *next;
 
@@ -1076,21 +1065,21 @@ static void red_worker_drawable_unref(RedWorker *worker, Drawable *drawable)
     spice_warn_if_fail(ring_is_empty(&drawable->pipes));
 
     if (drawable->stream) {
-        detach_stream(worker->display_channel, drawable->stream, TRUE);
+        detach_stream(display, drawable->stream, TRUE);
     }
     region_destroy(&drawable->tree_item.base.rgn);
 
-    remove_drawable_dependencies(worker, drawable);
-    red_dec_surfaces_drawable_dependencies(worker, drawable);
-    red_surface_unref(worker, drawable->surface_id);
+    drawable_remove_dependencies(display, drawable);
+    drawable_unref_surfaces_dest(display, drawable);
+    red_surface_unref(COMMON_CHANNEL(display)->worker, drawable->surface_id);
 
     RING_FOREACH_SAFE(item, next, &drawable->glz_ring) {
         SPICE_CONTAINEROF(item, RedGlzDrawable, drawable_link)->drawable = NULL;
         ring_remove(item);
     }
-    put_red_drawable(worker, drawable->red_drawable, drawable->group_id);
-    free_drawable(worker, drawable);
-    worker->drawable_count--;
+    put_red_drawable(COMMON_CHANNEL(display)->worker, drawable->red_drawable, drawable->group_id);
+    drawable_free(display, drawable);
+    display->drawable_count--;
 }
 
 static inline void remove_shadow(RedWorker *worker, DrawItem *item)
@@ -1185,7 +1174,7 @@ static inline void current_remove_drawable(RedWorker *worker, Drawable *item)
     ring_remove(&item->tree_item.base.siblings_link);
     ring_remove(&item->list_link);
     ring_remove(&item->surface_list_link);
-    red_worker_drawable_unref(worker, item);
+    display_channel_drawable_unref(display, item);
     display->current_size--;
 }
 
@@ -2347,6 +2336,7 @@ static inline int is_drawable_independent_from_surfaces(Drawable *drawable)
 
 static inline int red_current_add_equal(RedWorker *worker, DrawItem *item, TreeItem *other)
 {
+    DisplayChannel *display  = worker->display_channel;
     DrawItem *other_draw_item;
     Drawable *drawable;
     Drawable *other_drawable;
@@ -2376,7 +2366,7 @@ static inline int red_current_add_equal(RedWorker *worker, DrawItem *item, TreeI
             red_pipes_add_drawable(worker, drawable);
         }
         red_pipes_remove_drawable(other_drawable);
-        red_worker_drawable_unref(worker, other_drawable);
+        display_channel_drawable_unref(display, other_drawable);
         return TRUE;
     }
 
@@ -2419,7 +2409,7 @@ static inline int red_current_add_equal(RedWorker *worker, DrawItem *item, TreeI
             /* not sending other_drawable where possible */
             red_pipes_remove_drawable(other_drawable);
 
-            red_worker_drawable_unref(worker, other_drawable);
+            display_channel_drawable_unref(display, other_drawable);
             return TRUE;
         }
         break;
@@ -2894,6 +2884,7 @@ static bool free_one_drawable(RedWorker *worker, int force_glz_free)
 static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *red_drawable,
                               uint32_t group_id)
 {
+    DisplayChannel *display = worker->display_channel;
     Drawable *drawable;
     int x;
 
@@ -2908,12 +2899,12 @@ static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *re
         }
     }
 
-    while (!(drawable = alloc_drawable(worker))) {
-        if (!free_one_drawable(worker, FALSE))
+    while (!(drawable = drawable_try_new(display))) {
+        if (!free_one_drawable(COMMON_CHANNEL(display)->worker, FALSE))
             return NULL;
     }
-    worker->drawable_count++;
-    memset(drawable, 0, sizeof(Drawable));
+
+    bzero(drawable, sizeof(Drawable));
     drawable->refs = 1;
     drawable->creation_time = red_get_monotonic_time();
     ring_item_init(&drawable->list_link);
@@ -3010,6 +3001,7 @@ static inline void red_inc_surfaces_drawable_dependencies(RedWorker *worker, Dra
 static inline void red_process_draw(RedWorker *worker, RedDrawable *red_drawable,
                                     uint32_t group_id)
 {
+    DisplayChannel *display = worker->display_channel;
     int surface_id;
     Drawable *drawable = get_drawable(worker, red_drawable->effect, red_drawable, group_id);
 
@@ -3063,7 +3055,7 @@ static inline void red_process_draw(RedWorker *worker, RedDrawable *red_drawable
         red_pipes_add_drawable(worker, drawable);
     }
 cleanup:
-    red_worker_drawable_unref(worker, drawable);
+    display_channel_drawable_unref(display, drawable);
 }
 
 static inline void red_create_surface(RedWorker *worker, uint32_t surface_id,uint32_t width,
@@ -3392,13 +3384,14 @@ static void red_update_area_till(RedWorker *worker, const SpiceRect *area, int s
            that red_update_area is called for, Otherwise, 'now' would have already been rendered.
            See the call for red_handle_depends_on_target_surface in red_process_draw */
         red_draw_drawable(worker, now);
-        red_worker_drawable_unref(worker, now);
+        display_channel_drawable_unref(display, now);
     } while (now != surface_last);
     validate_area(worker, area, surface_id);
 }
 
 static void red_update_area(RedWorker *worker, const SpiceRect *area, int surface_id)
 {
+    DisplayChannel *display = worker->display_channel;
     RedSurface *surface;
     Ring *ring;
     RingItem *ring_item;
@@ -3445,7 +3438,7 @@ static void red_update_area(RedWorker *worker, const SpiceRect *area, int surfac
         current_remove_drawable(worker, now);
         container_cleanup(worker, container);
         red_draw_drawable(worker, now);
-        red_worker_drawable_unref(worker, now);
+        display_channel_drawable_unref(display, now);
     } while (now != last);
     validate_area(worker, area, surface_id);
 }
@@ -3630,7 +3623,7 @@ static void red_free_some(RedWorker *worker)
     DisplayChannelClient *dcc;
     RingItem *item, *next;
 
-    spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d", worker->drawable_count,
+    spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d", display->drawable_count,
                 worker->red_drawable_count, worker->glz_drawable_count);
     FOREACH_DCC(worker->display_channel, item, next, dcc) {
         GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
@@ -7597,7 +7590,7 @@ void red_show_tree(RedWorker *worker)
 
 static void display_channel_client_on_disconnect(RedChannelClient *rcc)
 {
-    DisplayChannel *display_channel;
+    DisplayChannel *display;
     DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
     CommonChannel *common;
     RedWorker *worker;
@@ -7608,9 +7601,9 @@ static void display_channel_client_on_disconnect(RedChannelClient *rcc)
     spice_info(NULL);
     common = SPICE_CONTAINEROF(rcc->channel, CommonChannel, base);
     worker = common->worker;
-    display_channel = (DisplayChannel *)rcc->channel;
-    spice_assert(display_channel == worker->display_channel);
-    display_channel_compress_stats_print(display_channel);
+    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;
     red_release_glz(dcc);
@@ -7622,10 +7615,10 @@ static void display_channel_client_on_disconnect(RedChannelClient *rcc)
 
     // this was the last channel client
     if (!red_channel_is_connected(rcc->channel)) {
-        red_display_destroy_compress_bufs(display_channel);
+        red_display_destroy_compress_bufs(display);
     }
     spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d",
-                worker->drawable_count, worker->red_drawable_count,
+                display->drawable_count, worker->red_drawable_count,
                 worker->glz_drawable_count);
 }
 
@@ -8676,7 +8669,7 @@ static void display_channel_client_release_item_after_push(DisplayChannelClient
         display_stream_clip_unref(display, (StreamClipItem *)item);
         break;
     case PIPE_ITEM_TYPE_UPGRADE:
-        release_upgrade_item(DCC_TO_WORKER(dcc), (UpgradeItem *)item);
+        upgrade_item_unref(display, (UpgradeItem *)item);
         break;
     case PIPE_ITEM_TYPE_IMAGE:
         release_image_item((ImageItem *)item);
@@ -8724,7 +8717,7 @@ static void display_channel_client_release_item_before_push(DisplayChannelClient
         break;
     }
     case PIPE_ITEM_TYPE_UPGRADE:
-        release_upgrade_item(DCC_TO_WORKER(dcc), (UpgradeItem *)item);
+        upgrade_item_unref(display, (UpgradeItem *)item);
         break;
     case PIPE_ITEM_TYPE_IMAGE:
         release_image_item((ImageItem *)item);
@@ -8836,6 +8829,7 @@ static void display_channel_create(RedWorker *worker, int migrate)
     init_streams(display_channel);
     image_cache_init(&display_channel->image_cache);
     ring_init(&display_channel->current_list);
+    drawables_init(display_channel);
 }
 
 static void guest_set_client_capabilities(RedWorker *worker)
@@ -9421,7 +9415,7 @@ void handle_dev_oom(void *opaque, void *payload)
     spice_assert(worker->running);
     // streams? but without streams also leak
     spice_debug("OOM1 #draw=%u, #red_draw=%u, #glz_draw=%u current %u pipes %u",
-                worker->drawable_count,
+                display->drawable_count,
                 worker->red_drawable_count,
                 worker->glz_drawable_count,
                 display->current_size,
@@ -9435,7 +9429,7 @@ void handle_dev_oom(void *opaque, void *payload)
         worker->qxl->st->qif->flush_resources(worker->qxl);
     }
     spice_debug("OOM2 #draw=%u, #red_draw=%u, #glz_draw=%u current %u pipes %u",
-                worker->drawable_count,
+                display->drawable_count,
                 worker->red_drawable_count,
                 worker->glz_drawable_count,
                 display->current_size,
@@ -9968,7 +9962,6 @@ RedWorker* red_worker_new(QXLInstance *qxl, RedDispatcher *red_dispatcher)
     worker->zlib_glz_state = zlib_glz_state;
     worker->driver_cap_monitors_config = 0;
     image_surface_init(worker);
-    drawables_init(worker);
     stat_init(&worker->add_stat, add_stat_name);
     stat_init(&worker->exclude_stat, exclude_stat_name);
     stat_init(&worker->__exclude_stat, __exclude_stat_name);
-- 
2.4.3



More information about the Spice-devel mailing list