diff options
author | Marc-André Lureau <marcandre.lureau@gmail.com> | 2013-09-26 22:53:57 +0200 |
---|---|---|
committer | Frediano Ziglio <fziglio@redhat.com> | 2015-11-23 14:21:09 +0000 |
commit | 4acf97cae1ce9cfc59a8826b3f604c84241929d7 (patch) | |
tree | d8a4d8f1259912548729e7cdb8d3f5675442e1fe | |
parent | b9ea3c9145f0eb1600a75abc239135bfd3d04510 (diff) | |
download | spice-4acf97cae1ce9cfc59a8826b3f604c84241929d7.tar.gz spice-4acf97cae1ce9cfc59a8826b3f604c84241929d7.tar.xz spice-4acf97cae1ce9cfc59a8826b3f604c84241929d7.zip |
worker: move display_channel_free_some
Author: Marc-André Lureau <marcandre.lureau@gmail.com>
Acked-by: Fabiano Fidêncio <fabiano@fidencio.org>
-rw-r--r-- | server/dcc-encoders.c | 25 | ||||
-rw-r--r-- | server/dcc-encoders.h | 3 | ||||
-rw-r--r-- | server/display-channel.c | 106 | ||||
-rw-r--r-- | server/display-channel.h | 6 | ||||
-rw-r--r-- | server/red_worker.c | 134 |
5 files changed, 145 insertions, 129 deletions
diff --git a/server/dcc-encoders.c b/server/dcc-encoders.c index f5e4dc56..24064a89 100644 --- a/server/dcc-encoders.c +++ b/server/dcc-encoders.c @@ -517,6 +517,31 @@ void dcc_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable) } } +/* + * Remove from the global lz dictionary some glz_drawables that have no reference to + * Drawable (their qxl drawables are released too). + * NOTE - the caller should prevent encoding using the dictionary during the operation + */ +int dcc_free_some_independent_glz_drawables(DisplayChannelClient *dcc) +{ + RingItem *ring_link; + int n = 0; + + if (!dcc) { + return 0; + } + ring_link = ring_get_head(&dcc->glz_drawables); + while ((n < RED_RELEASE_BUNCH_SIZE) && (ring_link != NULL)) { + RedGlzDrawable *glz_drawable = SPICE_CONTAINEROF(ring_link, RedGlzDrawable, link); + ring_link = ring_next(&dcc->glz_drawables, ring_link); + if (!glz_drawable->drawable) { + dcc_free_glz_drawable(dcc, glz_drawable); + n++; + } + } + return n; +} + void dcc_free_glz_drawables_to_free(DisplayChannelClient* dcc) { RingItem *ring_link; diff --git a/server/dcc-encoders.h b/server/dcc-encoders.h index 6c19cf42..05fd29ed 100644 --- a/server/dcc-encoders.h +++ b/server/dcc-encoders.h @@ -36,13 +36,13 @@ typedef struct RedCompressBuf RedCompressBuf; typedef struct GlzDrawableInstanceItem GlzDrawableInstanceItem; typedef struct RedGlzDrawable RedGlzDrawable; - void dcc_encoders_init (DisplayChannelClient *dcc); void dcc_encoders_free (DisplayChannelClient *dcc); void dcc_free_glz_drawable_instance (DisplayChannelClient *dcc, GlzDrawableInstanceItem *item); void dcc_free_glz_drawable (DisplayChannelClient *dcc, RedGlzDrawable *drawable); +int dcc_free_some_independent_glz_drawables (DisplayChannelClient *dcc); void dcc_free_glz_drawables (DisplayChannelClient *dcc); void dcc_free_glz_drawables_to_free (DisplayChannelClient* dcc); void dcc_freeze_glz (DisplayChannelClient *dcc); @@ -157,5 +157,6 @@ struct RedGlzDrawable { DisplayChannelClient *dcc; }; +#define RED_RELEASE_BUNCH_SIZE 64 #endif /* DCC_ENCODERS_H_ */ diff --git a/server/display-channel.c b/server/display-channel.c index d455a0db..f443dd01 100644 --- a/server/display-channel.c +++ b/server/display-channel.c @@ -873,3 +873,109 @@ void display_channel_free_glz_drawables(DisplayChannel *display) dcc_free_glz_drawables(dcc); } } + +static bool free_one_drawable(DisplayChannel *display, int force_glz_free) +{ + RingItem *ring_item = ring_get_tail(&display->current_list); + Drawable *drawable; + Container *container; + + if (!ring_item) { + return FALSE; + } + + drawable = SPICE_CONTAINEROF(ring_item, Drawable, list_link); + if (force_glz_free) { + RingItem *glz_item, *next_item; + RedGlzDrawable *glz; + DRAWABLE_FOREACH_GLZ_SAFE(drawable, glz_item, next_item, glz) { + dcc_free_glz_drawable(glz->dcc, glz); + } + } + drawable_draw(display, drawable); + container = drawable->tree_item.base.container; + + current_remove_drawable(display, drawable); + container_cleanup(container); + return TRUE; +} + +void display_channel_current_flush(DisplayChannel *display, int surface_id) +{ + while (!ring_is_empty(&display->surfaces[surface_id].current_list)) { + free_one_drawable(display, FALSE); + } + current_remove_all(display, surface_id); +} + +void display_channel_free_some(DisplayChannel *display) +{ + int n = 0; + DisplayChannelClient *dcc; + RingItem *item, *next; + + spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d", display->drawable_count, + display->red_drawable_count, display->glz_drawable_count); + FOREACH_DCC(display, item, next, dcc) { + GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL; + + if (glz_dict) { + // encoding using the dictionary is prevented since the following operations might + // change the dictionary + pthread_rwlock_wrlock(&glz_dict->encode_lock); + n = dcc_free_some_independent_glz_drawables(dcc); + } + } + + while (!ring_is_empty(&display->current_list) && n++ < RED_RELEASE_BUNCH_SIZE) { + free_one_drawable(display, TRUE); + } + + FOREACH_DCC(display, item, next, dcc) { + GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL; + + if (glz_dict) { + pthread_rwlock_unlock(&glz_dict->encode_lock); + } + } +} + +static Drawable* drawable_try_new(DisplayChannel *display) +{ + Drawable *drawable; + + if (!display->free_drawables) + return NULL; + + drawable = &display->free_drawables->u.drawable; + display->free_drawables = display->free_drawables->u.next; + display->drawable_count++; + + return drawable; +} + +Drawable *display_channel_drawable_try_new(DisplayChannel *display, + int group_id, int process_commands_generation) +{ + Drawable *drawable; + + while (!(drawable = drawable_try_new(display))) { + if (!free_one_drawable(display, FALSE)) + return NULL; + } + + bzero(drawable, sizeof(Drawable)); + drawable->refs = 1; + drawable->creation_time = red_get_monotonic_time(); + ring_item_init(&drawable->list_link); + ring_item_init(&drawable->surface_list_link); + ring_item_init(&drawable->tree_item.base.siblings_link); + drawable->tree_item.base.type = TREE_ITEM_TYPE_DRAWABLE; + region_init(&drawable->tree_item.base.rgn); + ring_init(&drawable->pipes); + ring_init(&drawable->glz_ring); + drawable->process_commands_generation = process_commands_generation; + drawable->group_id = group_id; + + return drawable; +} diff --git a/server/display-channel.h b/server/display-channel.h index 03834fae..29c11517 100644 --- a/server/display-channel.h +++ b/server/display-channel.h @@ -257,11 +257,15 @@ typedef struct SurfaceDestroyItem { } SurfaceDestroyItem; +void display_channel_free_some (DisplayChannel *display); void display_channel_set_stream_video (DisplayChannel *display, int stream_video); 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); +Drawable * display_channel_drawable_try_new (DisplayChannel *display, + int group_id, + int process_commands_generation); void display_channel_drawable_unref (DisplayChannel *display, Drawable *drawable); void display_channel_surface_unref (DisplayChannel *display, uint32_t surface_id); @@ -399,5 +403,7 @@ 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); +void drawable_draw(DisplayChannel *display, Drawable *item); +void current_remove_all(DisplayChannel *display, int surface_id); #endif /* DISPLAY_CHANNEL_H_ */ diff --git a/server/red_worker.c b/server/red_worker.c index 63e7d253..2a7b4158 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -152,13 +152,11 @@ typedef struct BitmapData { static inline int validate_surface(DisplayChannel *display, uint32_t surface_id); -static void drawable_draw(DisplayChannel *display, Drawable *item); static void red_update_area(DisplayChannel *display, const SpiceRect *area, int surface_id); static void red_update_area_till(DisplayChannel *display, const SpiceRect *area, int surface_id, Drawable *last); static inline void display_begin_send_message(RedChannelClient *rcc); static void dcc_release_glz(DisplayChannelClient *dcc); -static int red_display_free_some_independent_glz_drawables(DisplayChannelClient *dcc); static void display_channel_client_release_item_before_push(DisplayChannelClient *dcc, PipeItem *item); static void display_channel_client_release_item_after_push(DisplayChannelClient *dcc, @@ -300,7 +298,6 @@ static inline int validate_surface(DisplayChannel *display, uint32_t surface_id) return 1; } - static inline void red_handle_drawable_surfaces_client_synced( DisplayChannelClient *dcc, Drawable *drawable) { @@ -473,20 +470,6 @@ static void common_release_recv_buf(RedChannelClient *rcc, uint16_t type, uint32 } -static Drawable* drawable_try_new(DisplayChannel *display) -{ - Drawable *drawable; - - if (!display->free_drawables) - return NULL; - - drawable = &display->free_drawables->u.drawable; - display->free_drawables = display->free_drawables->u.next; - display->drawable_count++; - - return drawable; -} - static void drawable_free(DisplayChannel *display, Drawable *drawable) { ((_Drawable *)drawable)->u.next = display->free_drawables; @@ -678,7 +661,7 @@ void current_remove(DisplayChannel *display, TreeItem *item) } } -static void current_remove_all(DisplayChannel *display, int surface_id) +void current_remove_all(DisplayChannel *display, int surface_id) { Ring *ring = &display->surfaces[surface_id].current; RingItem *ring_item; @@ -1048,31 +1031,6 @@ static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable) return TRUE; } -static bool free_one_drawable(DisplayChannel *display, int force_glz_free) -{ - RingItem *ring_item = ring_get_tail(&display->current_list); - Drawable *drawable; - Container *container; - - if (!ring_item) { - return FALSE; - } - drawable = SPICE_CONTAINEROF(ring_item, Drawable, list_link); - if (force_glz_free) { - RingItem *glz_item, *next_item; - RedGlzDrawable *glz; - DRAWABLE_FOREACH_GLZ_SAFE(drawable, glz_item, next_item, glz) { - dcc_free_glz_drawable(glz->dcc, glz); - } - } - drawable_draw(display, drawable); - container = drawable->tree_item.base.container; - - current_remove_drawable(display, drawable); - container_cleanup(container); - return TRUE; -} - static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *red_drawable, uint32_t group_id) { @@ -1090,29 +1048,17 @@ static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *re } } - while (!(drawable = drawable_try_new(display))) { - if (!free_one_drawable(display, FALSE)) - return NULL; + drawable = display_channel_drawable_try_new(display, group_id, worker->process_commands_generation); + if (!drawable) { + return NULL; } - bzero(drawable, sizeof(Drawable)); - drawable->refs = 1; - drawable->creation_time = red_get_monotonic_time(); - ring_item_init(&drawable->list_link); - ring_item_init(&drawable->surface_list_link); - ring_item_init(&drawable->tree_item.base.siblings_link); - drawable->tree_item.base.type = TREE_ITEM_TYPE_DRAWABLE; - region_init(&drawable->tree_item.base.rgn); drawable->tree_item.effect = effect; drawable->red_drawable = red_drawable_ref(red_drawable); - drawable->group_id = group_id; drawable->surface_id = red_drawable->surface_id; memcpy(drawable->surface_deps, red_drawable->surface_deps, sizeof(drawable->surface_deps)); - ring_init(&drawable->pipes); - ring_init(&drawable->glz_ring); - drawable->process_commands_generation = worker->process_commands_generation; return drawable; } @@ -1324,7 +1270,7 @@ static void image_surface_init(DisplayChannel *display) display->image_surfaces.ops = &image_surfaces_ops; } -static void drawable_draw(DisplayChannel *display, Drawable *drawable) +void drawable_draw(DisplayChannel *display, Drawable *drawable) { RedSurface *surface; SpiceCanvas *canvas; @@ -1792,49 +1738,6 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size, int * return n; } -#define RED_RELEASE_BUNCH_SIZE 64 - -static void red_free_some(RedWorker *worker) -{ - DisplayChannel *display = worker->display_channel; - int n = 0; - DisplayChannelClient *dcc; - RingItem *item, *next; - - spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d", display->drawable_count, - display->red_drawable_count, display->glz_drawable_count); - FOREACH_DCC(worker->display_channel, item, next, dcc) { - GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL; - - if (glz_dict) { - // encoding using the dictionary is prevented since the following operations might - // change the dictionary - pthread_rwlock_wrlock(&glz_dict->encode_lock); - n = red_display_free_some_independent_glz_drawables(dcc); - } - } - - while (!ring_is_empty(&display->current_list) && n++ < RED_RELEASE_BUNCH_SIZE) { - free_one_drawable(display, TRUE); - } - - FOREACH_DCC(worker->display_channel, item, next, dcc) { - GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL; - - if (glz_dict) { - pthread_rwlock_unlock(&glz_dict->encode_lock); - } - } -} - -void display_channel_current_flush(DisplayChannel *display, int surface_id) -{ - while (!ring_is_empty(&display->surfaces[surface_id].current_list)) { - free_one_drawable(display, FALSE); - } - current_remove_all(display, surface_id); -} - static void fill_base(SpiceMarshaller *base_marshaller, Drawable *drawable) { SpiceMsgDisplayBase base; @@ -1846,31 +1749,6 @@ static void fill_base(SpiceMarshaller *base_marshaller, Drawable *drawable) spice_marshall_DisplayBase(base_marshaller, &base); } -/* - * Remove from the global lz dictionary some glz_drawables that have no reference to - * Drawable (their qxl drawables are released too). - * NOTE - the caller should prevent encoding using the dictionary during the operation - */ -static int red_display_free_some_independent_glz_drawables(DisplayChannelClient *dcc) -{ - RingItem *ring_link; - int n = 0; - - if (!dcc) { - return 0; - } - ring_link = ring_get_head(&dcc->glz_drawables); - while ((n < RED_RELEASE_BUNCH_SIZE) && (ring_link != NULL)) { - RedGlzDrawable *glz_drawable = SPICE_CONTAINEROF(ring_link, RedGlzDrawable, link); - ring_link = ring_next(&dcc->glz_drawables, ring_link); - if (!glz_drawable->drawable) { - dcc_free_glz_drawable(dcc, glz_drawable); - n++; - } - } - return n; -} - static inline void red_display_add_image_to_pixmap_cache(RedChannelClient *rcc, SpiceImage *image, SpiceImage *io_image, int is_lossy) @@ -5828,7 +5706,7 @@ static void handle_dev_oom(void *opaque, void *payload) red_channel_push(&worker->display_channel->common.base); } if (worker->qxl->st->qif->flush_resources(worker->qxl) == 0) { - red_free_some(worker); + display_channel_free_some(worker->display_channel); worker->qxl->st->qif->flush_resources(worker->qxl); } spice_debug("OOM2 #draw=%u, #red_draw=%u, #glz_draw=%u current %u pipes %u", |