diff options
author | Yonit Halperin <yhalperi@redhat.com> | 2010-06-01 10:30:51 +0300 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2010-06-09 11:41:01 +0200 |
commit | 5d2ae66f5022187e0028a1d7ccf67fe48fdaa94b (patch) | |
tree | 0458ad257a08447d5edc21c6391225ac8b738717 /client | |
parent | 263646a1f7e705766f7d46017679812d4b1406b8 (diff) | |
download | spice-5d2ae66f5022187e0028a1d7ccf67fe48fdaa94b.tar.gz spice-5d2ae66f5022187e0028a1d7ccf67fe48fdaa94b.tar.xz spice-5d2ae66f5022187e0028a1d7ccf67fe48fdaa94b.zip |
support for lossy images in the pixmap cache and fill bits
1) add an option to determine if a bitmap can be sent lossy to the client
2) when required, replacing lossy cache items with their correspending
lossless bitmaps
Diffstat (limited to 'client')
-rw-r--r-- | client/canvas.cpp | 1 | ||||
-rw-r--r-- | client/canvas.h | 23 | ||||
-rw-r--r-- | client/shared_cache.hpp | 80 |
3 files changed, 99 insertions, 5 deletions
diff --git a/client/canvas.cpp b/client/canvas.cpp index 0a4d8e5e..4ed1e184 100644 --- a/client/canvas.cpp +++ b/client/canvas.cpp @@ -91,6 +91,7 @@ void Canvas::localalize_image(SPICE_ADDRESS* in_bitmap) case SPICE_IMAGE_TYPE_JPEG: break; case SPICE_IMAGE_TYPE_FROM_CACHE: + case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS: break; default: THROW("invalid image type %u", image->type); diff --git a/client/canvas.h b/client/canvas.h index 8d64ca3f..f0314b93 100644 --- a/client/canvas.h +++ b/client/canvas.h @@ -163,17 +163,38 @@ public: cache->add(id, surface); } + static void op_put_lossy(SpiceImageCache *c, uint64_t id, pixman_image_t *surface) + { + PixmapCache* cache = reinterpret_cast<PixmapCache*>(c); + cache->add(id, surface, TRUE); + } + + static void op_replace_lossy(SpiceImageCache *c, uint64_t id, pixman_image_t *surface) + { + PixmapCache* cache = reinterpret_cast<PixmapCache*>(c); + cache->replace(id, surface); + } + static pixman_image_t* op_get(SpiceImageCache *c, uint64_t id) { PixmapCache* cache = reinterpret_cast<PixmapCache*>(c); return cache->get(id); } + static pixman_image_t* op_get_lossless(SpiceImageCache *c, uint64_t id) + { + PixmapCache* cache = reinterpret_cast<PixmapCache*>(c); + return cache->get_lossless(id); + } + SpiceImageCacheBase() { static SpiceImageCacheOps cache_ops = { op_put, - op_get + op_get, + op_put_lossy, + op_replace_lossy, + op_get_lossless }; base.ops = &cache_ops; } diff --git a/client/shared_cache.hpp b/client/shared_cache.hpp index 88360251..a8308545 100644 --- a/client/shared_cache.hpp +++ b/client/shared_cache.hpp @@ -41,7 +41,7 @@ public: clear(); } - void add(uint64_t id, T* data) + void add(uint64_t id, T* data, bool is_lossy = FALSE) { Lock lock(_lock); Item** item = &_hash[key(id)]; @@ -53,7 +53,7 @@ public: } item = &(*item)->next; } - *item = new Item(id, data); + *item = new Item(id, data, is_lossy); _new_item_cond.notify_all(); } @@ -81,6 +81,68 @@ public: } } + T* get_lossless(uint64_t id) + { + Lock lock(_lock); + Item* item = _hash[key(id)]; + + for (;;) { + if (!item) { + if (_aborting) { + THROW("%s aborting", Treat::name()); + } + _new_item_cond.wait(lock); + item = _hash[key(id)]; + continue; + } + + if (item->id != id) { + item = item->next; + continue; + } + break; + } + + // item has been retreived. Now checking if lossless + for (;;) { + if (item->lossy) { + if (_aborting) { + THROW("%s aborting", Treat::name()); + } + _replace_data_cond.wait(lock); + continue; + } + + return Treat::get(item->data); + } + } + + void replace(uint64_t id, T* data, bool is_lossy = FALSE) + { + Lock lock(_lock); + Item* item = _hash[key(id)]; + + for (;;) { + if (!item) { + if (_aborting) { + THROW("%s aborting", Treat::name()); + } + _new_item_cond.wait(lock); + item = _hash[key(id)]; + continue; + } + + if (item->id != id) { + item = item->next; + continue; + } + + item->replace(data, is_lossy); + break; + } + _replace_data_cond.notify_all(); + } + void remove(uint64_t id) { Lock lock(_lock); @@ -125,26 +187,36 @@ private: private: class Item { public: - Item(uint64_t in_id, T* data) + Item(uint64_t in_id, T* data, bool is_lossy = FALSE) : id (in_id) , refs (1) , next (NULL) - , data (Treat::get(data)) {} + , data (Treat::get(data)) + , lossy (is_lossy) {} ~Item() { Treat::release(data); } + void replace(T* new_data, bool is_lossy = FALSE) + { + Treat::release(data); + data = Treat::get(new_data); + lossy = is_lossy; + } + uint64_t id; int refs; Item* next; T* data; + bool lossy; }; Item* _hash[HASH_SIZE]; Mutex _lock; Condition _new_item_cond; + Condition _replace_data_cond; bool _aborting; }; |