--- server/Makefile.am | 2 + server/red_worker.c | 158 +-------------------------------------------- server/spice_image_cache.c | 135 ++++++++++++++++++++++++++++++++++++++ server/spice_image_cache.h | 39 +++++++++++ 4 files changed, 177 insertions(+), 157 deletions(-) create mode 100644 server/spice_image_cache.c create mode 100644 server/spice_image_cache.h diff --git a/server/Makefile.am b/server/Makefile.am index feee2f1..815f65e 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -100,6 +100,8 @@ libspice_server_la_SOURCES = \ spice_bitmap_utils.h \ spice_bitmap_utils.c \ spice_server_utils.h \ + spice_image_cache.h \ + spice_image_cache.c \ $(NULL) if SUPPORT_TUNNEL diff --git a/server/red_worker.c b/server/red_worker.c index b0dd471..a201315 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -85,6 +85,7 @@ #include "spice_server_utils.h" #include "red_time.h" #include "spice_bitmap_utils.h" +#include "spice_image_cache.h" //#define COMPRESS_STAT //#define DUMP_BITMAP @@ -757,29 +758,6 @@ typedef struct CursorChannel { #endif } CursorChannel; -typedef struct ImageCacheItem { - RingItem lru_link; - uint64_t id; -#ifdef IMAGE_CACHE_AGE - uint32_t age; -#endif - struct ImageCacheItem *next; - pixman_image_t *image; -} ImageCacheItem; - -#define IMAGE_CACHE_HASH_SIZE 1024 - -typedef struct ImageCache { - SpiceImageCache base; - ImageCacheItem *hash_table[IMAGE_CACHE_HASH_SIZE]; - Ring lru; -#ifdef IMAGE_CACHE_AGE - uint32_t age; -#else - uint32_t num_items; -#endif -} ImageCache; - enum { TREE_ITEM_TYPE_DRAWABLE, TREE_ITEM_TYPE_CONTAINER, @@ -4310,140 +4288,6 @@ static void image_surface_init(RedWorker *worker) worker->image_surfaces.ops = &image_surfaces_ops; } -static ImageCacheItem *image_cache_find(ImageCache *cache, uint64_t id) -{ - ImageCacheItem *item = cache->hash_table[id % IMAGE_CACHE_HASH_SIZE]; - - while (item) { - if (item->id == id) { - return item; - } - item = item->next; - } - return NULL; -} - -static int image_cache_hit(ImageCache *cache, uint64_t id) -{ - ImageCacheItem *item; - if (!(item = image_cache_find(cache, id))) { - return FALSE; - } -#ifdef IMAGE_CACHE_AGE - item->age = cache->age; -#endif - ring_remove(&item->lru_link); - ring_add(&cache->lru, &item->lru_link); - return TRUE; -} - -static void image_cache_remove(ImageCache *cache, ImageCacheItem *item) -{ - ImageCacheItem **now; - - now = &cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE]; - for (;;) { - spice_assert(*now); - if (*now == item) { - *now = item->next; - break; - } - now = &(*now)->next; - } - ring_remove(&item->lru_link); - pixman_image_unref(item->image); - free(item); -#ifndef IMAGE_CACHE_AGE - cache->num_items--; -#endif -} - -#define IMAGE_CACHE_MAX_ITEMS 2 - -static void image_cache_put(SpiceImageCache *spice_cache, uint64_t id, pixman_image_t *image) -{ - ImageCache *cache = (ImageCache *)spice_cache; - ImageCacheItem *item; - -#ifndef IMAGE_CACHE_AGE - if (cache->num_items == IMAGE_CACHE_MAX_ITEMS) { - ImageCacheItem *tail = (ImageCacheItem *)ring_get_tail(&cache->lru); - spice_assert(tail); - image_cache_remove(cache, tail); - } -#endif - - item = spice_new(ImageCacheItem, 1); - item->id = id; -#ifdef IMAGE_CACHE_AGE - item->age = cache->age; -#else - cache->num_items++; -#endif - item->image = pixman_image_ref(image); - ring_item_init(&item->lru_link); - - item->next = cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE]; - cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE] = item; - - ring_add(&cache->lru, &item->lru_link); -} - -static pixman_image_t *image_cache_get(SpiceImageCache *spice_cache, uint64_t id) -{ - ImageCache *cache = (ImageCache *)spice_cache; - - ImageCacheItem *item = image_cache_find(cache, id); - if (!item) { - spice_error("not found"); - } - return pixman_image_ref(item->image); -} - -static void image_cache_init(ImageCache *cache) -{ - static SpiceImageCacheOps image_cache_ops = { - image_cache_put, - image_cache_get, - }; - - cache->base.ops = &image_cache_ops; - memset(cache->hash_table, 0, sizeof(cache->hash_table)); - ring_init(&cache->lru); -#ifdef IMAGE_CACHE_AGE - cache->age = 0; -#else - cache->num_items = 0; -#endif -} - -static void image_cache_reset(ImageCache *cache) -{ - ImageCacheItem *item; - - while ((item = (ImageCacheItem *)ring_get_head(&cache->lru))) { - image_cache_remove(cache, item); - } -#ifdef IMAGE_CACHE_AGE - cache->age = 0; -#endif -} - -#define IMAGE_CACHE_DEPTH 4 - -static void image_cache_aging(ImageCache *cache) -{ -#ifdef IMAGE_CACHE_AGE - ImageCacheItem *item; - - cache->age++; - while ((item = (ImageCacheItem *)ring_get_tail(&cache->lru)) && - cache->age - item->age > IMAGE_CACHE_DEPTH) { - image_cache_remove(cache, item); - } -#endif -} - static void localize_bitmap(RedWorker *worker, SpiceImage **image_ptr, SpiceImage *image_store, Drawable *drawable) { diff --git a/server/spice_image_cache.c b/server/spice_image_cache.c new file mode 100644 index 0000000..291094c --- /dev/null +++ b/server/spice_image_cache.c @@ -0,0 +1,135 @@ +#include "spice_image_cache.h" + +static ImageCacheItem *image_cache_find(ImageCache *cache, uint64_t id) +{ + ImageCacheItem *item = cache->hash_table[id % IMAGE_CACHE_HASH_SIZE]; + + while (item) { + if (item->id == id) { + return item; + } + item = item->next; + } + return NULL; +} + +int image_cache_hit(ImageCache *cache, uint64_t id) +{ + ImageCacheItem *item; + if (!(item = image_cache_find(cache, id))) { + return FALSE; + } +#ifdef IMAGE_CACHE_AGE + item->age = cache->age; +#endif + ring_remove(&item->lru_link); + ring_add(&cache->lru, &item->lru_link); + return TRUE; +} + +static void image_cache_remove(ImageCache *cache, ImageCacheItem *item) +{ + ImageCacheItem **now; + + now = &cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE]; + for (;;) { + spice_assert(*now); + if (*now == item) { + *now = item->next; + break; + } + now = &(*now)->next; + } + ring_remove(&item->lru_link); + pixman_image_unref(item->image); + free(item); +#ifndef IMAGE_CACHE_AGE + cache->num_items--; +#endif +} + +#define IMAGE_CACHE_MAX_ITEMS 2 + +static void image_cache_put(SpiceImageCache *spice_cache, uint64_t id, pixman_image_t *image) +{ + ImageCache *cache = (ImageCache *)spice_cache; + ImageCacheItem *item; + +#ifndef IMAGE_CACHE_AGE + if (cache->num_items == IMAGE_CACHE_MAX_ITEMS) { + ImageCacheItem *tail = (ImageCacheItem *)ring_get_tail(&cache->lru); + spice_assert(tail); + image_cache_remove(cache, tail); + } +#endif + + item = spice_new(ImageCacheItem, 1); + item->id = id; +#ifdef IMAGE_CACHE_AGE + item->age = cache->age; +#else + cache->num_items++; +#endif + item->image = pixman_image_ref(image); + ring_item_init(&item->lru_link); + + item->next = cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE]; + cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE] = item; + + ring_add(&cache->lru, &item->lru_link); +} + +static pixman_image_t *image_cache_get(SpiceImageCache *spice_cache, uint64_t id) +{ + ImageCache *cache = (ImageCache *)spice_cache; + + ImageCacheItem *item = image_cache_find(cache, id); + if (!item) { + spice_error("not found"); + } + return pixman_image_ref(item->image); +} + +void image_cache_init(ImageCache *cache) +{ + static SpiceImageCacheOps image_cache_ops = { + image_cache_put, + image_cache_get, + }; + + cache->base.ops = &image_cache_ops; + memset(cache->hash_table, 0, sizeof(cache->hash_table)); + ring_init(&cache->lru); +#ifdef IMAGE_CACHE_AGE + cache->age = 0; +#else + cache->num_items = 0; +#endif +} + +void image_cache_reset(ImageCache *cache) +{ + ImageCacheItem *item; + + while ((item = (ImageCacheItem *)ring_get_head(&cache->lru))) { + image_cache_remove(cache, item); + } +#ifdef IMAGE_CACHE_AGE + cache->age = 0; +#endif +} + +#define IMAGE_CACHE_DEPTH 4 + +void image_cache_aging(ImageCache *cache) +{ +#ifdef IMAGE_CACHE_AGE + ImageCacheItem *item; + + cache->age++; + while ((item = (ImageCacheItem *)ring_get_tail(&cache->lru)) && + cache->age - item->age > IMAGE_CACHE_DEPTH) { + image_cache_remove(cache, item); + } +#endif +} diff --git a/server/spice_image_cache.h b/server/spice_image_cache.h new file mode 100644 index 0000000..f11cebc --- /dev/null +++ b/server/spice_image_cache.h @@ -0,0 +1,39 @@ +#ifndef H_SPICE_IMAGE_CACHE +#define H_SPICE_IMAGE_CACHE + +#include <inttypes.h> + +#include "common/pixman_utils.h" +#include "common/canvas_base.h" + +#include "common/ring.h" + +typedef struct ImageCacheItem { + RingItem lru_link; + uint64_t id; +#ifdef IMAGE_CACHE_AGE + uint32_t age; +#endif + struct ImageCacheItem *next; + pixman_image_t *image; +} ImageCacheItem; + +#define IMAGE_CACHE_HASH_SIZE 1024 + +typedef struct ImageCache { + SpiceImageCache base; + ImageCacheItem *hash_table[IMAGE_CACHE_HASH_SIZE]; + Ring lru; +#ifdef IMAGE_CACHE_AGE + uint32_t age; +#else + uint32_t num_items; +#endif +} ImageCache; + +int image_cache_hit(ImageCache *cache, uint64_t id); +void image_cache_init(ImageCache *cache); +void image_cache_reset(ImageCache *cache); +void image_cache_aging(ImageCache *cache); + +#endif -- 1.8.3.1 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel