summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2010-06-01 10:30:51 +0300
committerAlexander Larsson <alexl@redhat.com>2010-06-09 11:41:01 +0200
commit5d2ae66f5022187e0028a1d7ccf67fe48fdaa94b (patch)
tree0458ad257a08447d5edc21c6391225ac8b738717 /client
parent263646a1f7e705766f7d46017679812d4b1406b8 (diff)
downloadspice-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.cpp1
-rw-r--r--client/canvas.h23
-rw-r--r--client/shared_cache.hpp80
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;
};