From: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> --- 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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel