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 | |
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
-rw-r--r-- | client/canvas.cpp | 1 | ||||
-rw-r--r-- | client/canvas.h | 23 | ||||
-rw-r--r-- | client/shared_cache.hpp | 80 | ||||
-rw-r--r-- | common/canvas_base.c | 56 | ||||
-rw-r--r-- | common/canvas_base.h | 10 | ||||
-rw-r--r-- | server/red_client_shared_cache.h | 24 | ||||
-rw-r--r-- | server/red_worker.c | 86 |
7 files changed, 241 insertions, 39 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; }; diff --git a/common/canvas_base.c b/common/canvas_base.c index 8180f09d..aac472c8 100644 --- a/common/canvas_base.c +++ b/common/canvas_base.c @@ -567,7 +567,7 @@ static void dump_jpeg(uint8_t* data, int data_size) if (!f) { return; } - + fwrite(data, 1, data_size, f); fclose(f); } @@ -1044,12 +1044,19 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE * to happen which breaks if we don't. */ if (!real_get && !(descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME) && +#ifdef SW_CANVAS_CACHE + !(descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME) && +#endif (descriptor->type != SPICE_IMAGE_TYPE_GLZ_RGB)) { return NULL; } saved_want_original = want_original; - if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME) { + if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME +#ifdef SW_CANVAS_CACHE + || descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME +#endif + ) { want_original = TRUE; } @@ -1092,7 +1099,11 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE case SPICE_IMAGE_TYPE_FROM_CACHE: surface = canvas->bits_cache->ops->get(canvas->bits_cache, descriptor->id); break; - +#ifdef SW_CANVAS_CACHE + case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS: + surface = canvas->bits_cache->ops->get_lossless(canvas->bits_cache, descriptor->id); + break; +#endif case SPICE_IMAGE_TYPE_BITMAP: { SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor; access_test(canvas, descriptor, sizeof(SpiceBitmapImage)); @@ -1107,6 +1118,9 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE if (descriptor->flags & SPICE_IMAGE_FLAGS_HIGH_BITS_SET && descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE && +#ifdef SW_CANVAS_CACHE + descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS && +#endif surface_format == PIXMAN_x8r8g8b8) { spice_pixman_fill_rect_rop(surface, 0, 0, @@ -1116,13 +1130,39 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE } if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME && - descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE) { +#ifdef SW_CANVAS_CACHE + descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS && +#endif + descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE ) { +#ifdef SW_CANVAS_CACHE + if (descriptor->type != SPICE_IMAGE_TYPE_JPEG) { + canvas->bits_cache->ops->put(canvas->bits_cache, descriptor->id, surface); + } else { + canvas->bits_cache->ops->put_lossy(canvas->bits_cache, descriptor->id, surface); + } +#else canvas->bits_cache->ops->put(canvas->bits_cache, descriptor->id, surface); +#endif +#ifdef DEBUG_DUMP_SURFACE + dump_surface(surface, 1); +#endif +#ifdef SW_CANVAS_CACHE + } else if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME) { + if (descriptor->type == SPICE_IMAGE_TYPE_JPEG) { + CANVAS_ERROR("invalid cache replace request: the image is lossy"); + } + canvas->bits_cache->ops->replace_lossy(canvas->bits_cache, descriptor->id, surface); #ifdef DEBUG_DUMP_SURFACE dump_surface(surface, 1); #endif - } else if (descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE) { +#endif #ifdef DEBUG_DUMP_SURFACE + } else if (descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE +#ifdef SW_CANVAS_CACHE + && descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS +#endif + ) { + dump_surface(surface, 0); #endif } @@ -1438,6 +1478,12 @@ static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int is_invers = 0; break; #endif +#ifdef SW_CANVAS_CACHE + case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS: + surface = canvas->bits_cache->ops->get_lossless(canvas->bits_cache, descriptor->id); + is_invers = 0; + break; +#endif default: CANVAS_ERROR("invalid image type"); } diff --git a/common/canvas_base.h b/common/canvas_base.h index 4eaafbbd..1bbe4653 100644 --- a/common/canvas_base.h +++ b/common/canvas_base.h @@ -41,6 +41,16 @@ typedef struct { pixman_image_t *surface); pixman_image_t *(*get)(SpiceImageCache *cache, uint64_t id); +#ifdef SW_CANVAS_CACHE + void (*put_lossy)(SpiceImageCache *cache, + uint64_t id, + pixman_image_t *surface); + void (*replace_lossy)(SpiceImageCache *cache, + uint64_t id, + pixman_image_t *surface); + pixman_image_t *(*get_lossless)(SpiceImageCache *cache, + uint64_t id); +#endif } SpiceImageCacheOps; struct _SpiceImageCache { diff --git a/server/red_client_shared_cache.h b/server/red_client_shared_cache.h index 4d1989dd..716b8122 100644 --- a/server/red_client_shared_cache.h +++ b/server/red_client_shared_cache.h @@ -35,7 +35,7 @@ #endif -static int FUNC_NAME(hit)(CACHE *cache, uint64_t id, CHANNEL *channel) +static int FUNC_NAME(hit)(CACHE *cache, uint64_t id, int *lossy, CHANNEL *channel) { NewCacheItem *item; uint64_t serial; @@ -51,6 +51,7 @@ static int FUNC_NAME(hit)(CACHE *cache, uint64_t id, CHANNEL *channel) ASSERT(channel->base.id < MAX_CACHE_CLIENTS) item->sync[channel->base.id] = serial; cache->sync[channel->base.id] = serial; + *lossy = item->lossy; break; } item = item->next; @@ -60,7 +61,25 @@ static int FUNC_NAME(hit)(CACHE *cache, uint64_t id, CHANNEL *channel) return !!item; } -static int FUNC_NAME(add)(CACHE *cache, uint64_t id, uint32_t size, CHANNEL *channel) +static int FUNC_NAME(set_lossy)(CACHE *cache, uint64_t id, int lossy) +{ + NewCacheItem *item; + pthread_mutex_lock(&cache->lock); + + item = cache->hash_table[CACHE_HASH_KEY(id)]; + + while (item) { + if (item->id == id) { + item->lossy = lossy; + break; + } + item = item->next; + } + pthread_mutex_unlock(&cache->lock); + return !!item; +} + +static int FUNC_NAME(add)(CACHE *cache, uint64_t id, uint32_t size, int lossy, CHANNEL *channel) { NewCacheItem *item; uint64_t serial; @@ -119,6 +138,7 @@ static int FUNC_NAME(add)(CACHE *cache, uint64_t id, uint32_t size, CHANNEL *cha ring_add(&cache->lru, &item->lru_link); item->id = id; item->size = size; + item->lossy = lossy; memset(item->sync, 0, sizeof(item->sync)); item->sync[channel->base.id] = serial; cache->sync[channel->base.id] = serial; diff --git a/server/red_worker.c b/server/red_worker.c index aac1d27c..aa3b2a52 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -268,6 +268,7 @@ struct NewCacheItem { uint64_t id; uint64_t sync[MAX_CACHE_CLIENTS]; size_t size; + int lossy; }; typedef struct CacheItem CacheItem; @@ -5969,6 +5970,7 @@ typedef struct compress_send_data_t { uint32_t comp_buf_size; SPICE_ADDRESS *plt_ptr; uint8_t *flags_ptr; + int is_lossy; } compress_send_data_t; @@ -6034,6 +6036,7 @@ static inline int red_glz_compress_image(DisplayChannel *display_channel, o_comp_data->comp_buf_size = size; o_comp_data->plt_ptr = NULL; o_comp_data->flags_ptr = NULL; + o_comp_data->is_lossy = FALSE; stat_compress_add(&display_channel->glz_stat, start_time, src->stride * src->y, o_comp_data->comp_buf_size); @@ -6121,6 +6124,8 @@ static inline int red_lz_compress_image(DisplayChannel *display_channel, o_comp_data->plt_ptr = &(dest->lz_plt.palette); o_comp_data->flags_ptr = &(dest->lz_plt.flags); } + + o_comp_data->is_lossy = FALSE; stat_compress_add(&display_channel->lz_stat, start_time, src->stride * src->y, o_comp_data->comp_buf_size); return TRUE; @@ -6263,6 +6268,7 @@ static int red_jpeg_compress_image(DisplayChannel *display_channel, RedImage *de o_comp_data->comp_buf_size = size; o_comp_data->plt_ptr = NULL; o_comp_data->flags_ptr = NULL; + o_comp_data->is_lossy = TRUE; stat_compress_add(&display_channel->jpeg_stat, start_time, src->stride * src->y, o_comp_data->comp_buf_size); return TRUE; @@ -6409,6 +6415,7 @@ static inline int red_quic_compress_image(DisplayChannel *display_channel, RedIm o_comp_data->comp_buf_size = size << 2; o_comp_data->plt_ptr = NULL; o_comp_data->flags_ptr = NULL; + o_comp_data->is_lossy = FALSE; stat_compress_add(&display_channel->quic_stat, start_time, src->stride * src->y, o_comp_data->comp_buf_size); @@ -6419,6 +6426,7 @@ static inline int red_quic_compress_image(DisplayChannel *display_channel, RedIm #define MIN_DIMENSION_TO_QUIC 3 static inline int red_compress_image(DisplayChannel *display_channel, RedImage *dest, SpiceBitmap *src, Drawable *drawable, + int can_lossy, compress_send_data_t* o_comp_data) { spice_image_compression_t image_compression = @@ -6472,7 +6480,7 @@ static inline int red_compress_image(DisplayChannel *display_channel, red_printf("QUIC compress"); #endif // if bitmaps is picture-like, compress it using jpeg - if (display_channel->base.worker->enable_jpeg && + if (can_lossy && display_channel->base.worker->enable_jpeg && ((image_compression == SPICE_IMAGE_COMPRESS_AUTO_LZ) || (image_compression == SPICE_IMAGE_COMPRESS_AUTO_GLZ))) { if (src->format != SPICE_BITMAP_FMT_RGBA) { @@ -6526,15 +6534,18 @@ static inline int red_compress_image(DisplayChannel *display_channel, } static inline void red_display_add_image_to_pixmap_cache(DisplayChannel *display_channel, - QXLImage *qxl_image, RedImage *io_image) + QXLImage *qxl_image, RedImage *io_image, + int is_lossy) { if ((qxl_image->descriptor.flags & QXL_IMAGE_CACHE)) { ASSERT(qxl_image->descriptor.width * qxl_image->descriptor.height > 0); - if (pixmap_cache_add(display_channel->pixmap_cache, qxl_image->descriptor.id, - qxl_image->descriptor.width * qxl_image->descriptor.height, - display_channel)) { - io_image->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_ME; - stat_inc_counter(display_channel->add_to_cache_counter, 1); + if (!(io_image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME)) { + if (pixmap_cache_add(display_channel->pixmap_cache, qxl_image->descriptor.id, + qxl_image->descriptor.width * qxl_image->descriptor.height, is_lossy, + display_channel)) { + io_image->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_ME; + stat_inc_counter(display_channel->add_to_cache_counter, 1); + } } } @@ -6545,7 +6556,8 @@ static inline void red_display_add_image_to_pixmap_cache(DisplayChannel *display /* if the number of times fill_bits can be called per one qxl_drawable increases - MAX_LZ_DRAWABLE_INSTANCES must be increased as well */ -static void fill_bits(DisplayChannel *display_channel, QXLPHYSICAL *in_bitmap, Drawable *drawable) +static void fill_bits(DisplayChannel *display_channel, QXLPHYSICAL *in_bitmap, + Drawable *drawable, int can_lossy) { RedChannel *channel = &display_channel->base; RedWorker *worker = channel->worker; @@ -6577,12 +6589,26 @@ static void fill_bits(DisplayChannel *display_channel, QXLPHYSICAL *in_bitmap, D memslot_id = get_memslot_id(&worker->mem_slots, *in_bitmap); *in_bitmap = channel->send_data.header.size; if ((qxl_image->descriptor.flags & QXL_IMAGE_CACHE)) { + int lossy_cache_item; if (pixmap_cache_hit(display_channel->pixmap_cache, image->descriptor.id, - display_channel)) { - image->descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE; - add_buf(channel, BUF_TYPE_RAW, image, sizeof(SpiceImageDescriptor), 0, 0); - stat_inc_counter(display_channel->cache_hits_counter, 1); - return; + &lossy_cache_item, display_channel)) { + if (can_lossy || !lossy_cache_item) { + if (!worker->enable_jpeg || lossy_cache_item) { + image->descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE; + } else { + // making sure, in multiple monitor scenario, that lossy items that + // should have been replaced with lossless data by one display channel, + // will be retrieved as lossless by another display channel. + image->descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS; + } + add_buf(channel, BUF_TYPE_RAW, image, sizeof(SpiceImageDescriptor), 0, 0); + stat_inc_counter(display_channel->cache_hits_counter, 1); + return; + } else { + pixmap_cache_set_lossy(display_channel->pixmap_cache, qxl_image->descriptor.id, + FALSE); + image->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME; + } } } @@ -6612,12 +6638,12 @@ static void fill_bits(DisplayChannel *display_channel, QXLPHYSICAL *in_bitmap, D in order to prevent starvation in the client between pixmap_cache and global dictionary (in cases of multiple monitors) */ if (!red_compress_image(display_channel, image, &qxl_image->bitmap, - drawable, &comp_send_data)) { + drawable, can_lossy, &comp_send_data)) { uint32_t y; uint32_t stride; SPICE_ADDRESS image_data; - red_display_add_image_to_pixmap_cache(display_channel, qxl_image, image); + red_display_add_image_to_pixmap_cache(display_channel, qxl_image, image, FALSE); image->bitmap = qxl_image->bitmap; y = image->bitmap.y; @@ -6638,7 +6664,8 @@ static void fill_bits(DisplayChannel *display_channel, QXLPHYSICAL *in_bitmap, D add_buf(channel, BUF_TYPE_CHUNK, data, y * stride, memslot_id, drawable->group_id); } } else { - red_display_add_image_to_pixmap_cache(display_channel, qxl_image, image); + red_display_add_image_to_pixmap_cache(display_channel, qxl_image, image, + comp_send_data.is_lossy); add_buf((RedChannel *)display_channel, BUF_TYPE_RAW, image, comp_send_data.raw_size, 0, 0); @@ -6652,7 +6679,7 @@ static void fill_bits(DisplayChannel *display_channel, QXLPHYSICAL *in_bitmap, D } break; case SPICE_IMAGE_TYPE_QUIC: - red_display_add_image_to_pixmap_cache(display_channel, qxl_image, image); + red_display_add_image_to_pixmap_cache(display_channel, qxl_image, image, FALSE); image->quic = qxl_image->quic; add_buf(channel, BUF_TYPE_RAW, image, sizeof(SpiceQUICImage), 0, 0); add_buf(channel, BUF_TYPE_CHUNK, qxl_image->quic.data, qxl_image->quic.data_size, @@ -6666,7 +6693,7 @@ static void fill_bits(DisplayChannel *display_channel, QXLPHYSICAL *in_bitmap, D static void fill_brush(DisplayChannel *display_channel, SpiceBrush *brush, Drawable *drawable) { if (brush->type == SPICE_BRUSH_TYPE_PATTERN) { - fill_bits(display_channel, &brush->u.pattern.pat, drawable); + fill_bits(display_channel, &brush->u.pattern.pat, drawable, FALSE); } } @@ -6677,10 +6704,10 @@ static void fill_mask(DisplayChannel *display_channel, SpiceQMask *mask, Drawabl spice_image_compression_t save_img_comp = display_channel->base.worker->image_compression; display_channel->base.worker->image_compression = SPICE_IMAGE_COMPRESS_OFF; - fill_bits(display_channel, &mask->bitmap, drawable); + fill_bits(display_channel, &mask->bitmap, drawable, FALSE); display_channel->base.worker->image_compression = save_img_comp; } else { - fill_bits(display_channel, &mask->bitmap, drawable); + fill_bits(display_channel, &mask->bitmap, drawable, FALSE); } } } @@ -6781,7 +6808,8 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp fill_base(display_channel, &display_channel->send_data.u.opaque.base, item, sizeof(SpiceMsgDisplayDrawOpaque), item->surface_id); display_channel->send_data.u.opaque.data = drawable->u.opaque; - fill_bits(display_channel, &display_channel->send_data.u.opaque.data.src_bitmap, item); + fill_bits(display_channel, &display_channel->send_data.u.opaque.data.src_bitmap, + item, FALSE); fill_brush(display_channel, &display_channel->send_data.u.opaque.data.brush, item); fill_mask(display_channel, &display_channel->send_data.u.opaque.data.mask, item); break; @@ -6790,7 +6818,7 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp fill_base(display_channel, &display_channel->send_data.u.copy.base, item, sizeof(SpiceMsgDisplayDrawCopy), item->surface_id); display_channel->send_data.u.copy.data = drawable->u.copy; - fill_bits(display_channel, &display_channel->send_data.u.copy.data.src_bitmap, item); + fill_bits(display_channel, &display_channel->send_data.u.copy.data.src_bitmap, item, FALSE); fill_mask(display_channel, &display_channel->send_data.u.copy.data.mask, item); break; case QXL_DRAW_TRANSPARENT: @@ -6798,14 +6826,16 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp fill_base(display_channel, &display_channel->send_data.u.transparent.base, item, sizeof(SpiceMsgDisplayDrawTransparent), item->surface_id); display_channel->send_data.u.transparent.data = drawable->u.transparent; - fill_bits(display_channel, &display_channel->send_data.u.transparent.data.src_bitmap, item); + fill_bits(display_channel, &display_channel->send_data.u.transparent.data.src_bitmap, + item, FALSE); break; case QXL_DRAW_ALPHA_BLEND: channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND; fill_base(display_channel, &display_channel->send_data.u.alpha_blend.base, item, sizeof(SpiceMsgDisplayDrawAlphaBlend), item->surface_id); display_channel->send_data.u.alpha_blend.data = drawable->u.alpha_blend; - fill_bits(display_channel, &display_channel->send_data.u.alpha_blend.data.src_bitmap, item); + fill_bits(display_channel, &display_channel->send_data.u.alpha_blend.data.src_bitmap, + item, FALSE); break; case QXL_COPY_BITS: channel->send_data.header.type = SPICE_MSG_DISPLAY_COPY_BITS; @@ -6818,7 +6848,8 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp fill_base(display_channel, &display_channel->send_data.u.blend.base, item, sizeof(SpiceMsgDisplayDrawBlend), item->surface_id); display_channel->send_data.u.blend.data = drawable->u.blend; - fill_bits(display_channel, &display_channel->send_data.u.blend.data.src_bitmap, item); + fill_bits(display_channel, &display_channel->send_data.u.blend.data.src_bitmap, + item, FALSE); fill_mask(display_channel, &display_channel->send_data.u.blend.data.mask, item); break; case QXL_DRAW_BLACKNESS: @@ -6847,7 +6878,8 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp fill_base(display_channel, &display_channel->send_data.u.rop3.base, item, sizeof(SpiceMsgDisplayDrawRop3), item->surface_id); display_channel->send_data.u.rop3.data = drawable->u.rop3; - fill_bits(display_channel, &display_channel->send_data.u.rop3.data.src_bitmap, item); + fill_bits(display_channel, &display_channel->send_data.u.rop3.data.src_bitmap, + item, FALSE); fill_brush(display_channel, &display_channel->send_data.u.rop3.data.brush, item); fill_mask(display_channel, &display_channel->send_data.u.rop3.data.mask, item); break; @@ -7638,7 +7670,7 @@ static void red_display_send_upgrade(DisplayChannel *display_channel, UpgradeIte add_buf(channel, BUF_TYPE_RAW, &item->n_rects, sizeof(uint32_t), 0, 0); add_buf(channel, BUF_TYPE_RAW, item->rects, sizeof(SpiceRect) * item->n_rects, 0, 0); copy->data = qxl_drawable->u.copy; - fill_bits(display_channel, ©->data.src_bitmap, item->drawable); + fill_bits(display_channel, ©->data.src_bitmap, item->drawable, FALSE); display_begin_send_massage(display_channel, &item->base); } |