mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-12 20:53:48 +00:00
server: split spice_image_cache from red_worker
This commit is contained in:
parent
1bbce9ba05
commit
ee382109a6
@ -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
|
||||
|
||||
@ -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
135
server/spice_image_cache.c
Normal 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
|
||||
}
|
||||
39
server/spice_image_cache.h
Normal file
39
server/spice_image_cache.h
Normal 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
|
||||
Loading…
Reference in New Issue
Block a user