server: split spice_image_cache from red_worker

This commit is contained in:
Alon Levy 2013-08-12 15:31:56 +03:00
parent 1bbce9ba05
commit ee382109a6
4 changed files with 177 additions and 157 deletions

View File

@ -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

View File

@ -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,
@ -4300,140 +4278,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)
{

135
server/spice_image_cache.c Normal file
View File

@ -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
}

View File

@ -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