diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2010-07-01 17:55:33 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2010-07-07 23:58:33 +0200 |
commit | 5ac88aa79fa6445f96e5419d8bf4fce81da63b90 (patch) | |
tree | ae702a8569fda96e8bfe27c6b2655d90bcef7ce4 | |
parent | 26c1a0767f3fdcd0211b6b4c91a63ac9bc7abc6f (diff) |
Properly parse QXLImage to the new-world SpiceImage
SpiceImage now replaces RedImage and has all image types in it.
All image data are now chunked (and as such not copied when demarshalling).
-rw-r--r-- | common/canvas_base.c | 267 | ||||
-rw-r--r-- | common/canvas_base.h | 11 | ||||
-rw-r--r-- | common/gl_canvas.c | 6 | ||||
-rw-r--r-- | common/gl_canvas.h | 3 | ||||
-rw-r--r-- | common/sw_canvas.c | 18 | ||||
-rw-r--r-- | common/sw_canvas.h | 6 | ||||
-rw-r--r-- | python_modules/demarshal.py | 4 | ||||
-rw-r--r-- | python_modules/ptypes.py | 31 | ||||
-rw-r--r-- | python_modules/spice_parser.py | 2 | ||||
-rw-r--r-- | server/red_parse_qxl.c | 278 | ||||
-rw-r--r-- | server/red_parse_qxl.h | 1 | ||||
-rw-r--r-- | server/red_worker.c | 1244 | ||||
-rw-r--r-- | spice.proto | 81 | ||||
-rw-r--r-- | spice1.proto | 69 |
14 files changed, 813 insertions, 1208 deletions
diff --git a/common/canvas_base.c b/common/canvas_base.c index a0429a6..a1378a0 100644 --- a/common/canvas_base.c +++ b/common/canvas_base.c @@ -69,18 +69,6 @@ (((descriptor)->type == SPICE_IMAGE_TYPE_JPEG) || \ ((descriptor)->type == SPICE_IMAGE_TYPE_JPEG_ALPHA)) -#ifdef WIN32 -typedef struct __declspec (align(1)) LZImage { -#else -typedef struct __attribute__ ((__packed__)) LZImage { -#endif - SpiceImageDescriptor descriptor; - union { - SpiceLZRGBData lz_rgb; - SpiceLZPLTData lz_plt; - }; -} LZImage; - static inline int fix_to_int(SPICE_FIXED28_4 fixed) { int val, rem; @@ -157,11 +145,9 @@ typedef struct QuicData { QuicUsrContext usr; QuicContext *quic; jmp_buf jmp_env; -#ifndef SW_CANVAS_NO_CHUNKS - SPICE_ADDRESS next; - SpiceVirtMapping *virt_mapping; -#endif char message_buf[512]; + SpiceChunks *chunks; + int current_chunk; } QuicData; typedef struct CanvasBase { @@ -196,32 +182,6 @@ typedef struct CanvasBase { spice_destroy_fn_t usr_data_destroy; } CanvasBase; - -#ifndef SW_CANVAS_NO_CHUNKS - -#ifdef __GNUC__ -#define ATTR_PACKED __attribute__ ((__packed__)) -#else -#pragma pack(push) -#pragma pack(1) -#define ATTR_PACKED -#endif - -typedef struct ATTR_PACKED DataChunk { - uint32_t size; - SPICE_ADDRESS prev; - SPICE_ADDRESS next; - uint8_t data[0]; -} DataChunk; - -#undef ATTR_PACKED - -#ifndef __GNUC__ -#pragma pack(pop) -#endif - -#endif - typedef enum { ROP_INPUT_SRC, ROP_INPUT_BRUSH, @@ -434,7 +394,7 @@ static pixman_format_code_t canvas_get_target_format(CanvasBase *canvas, return format; } -static pixman_image_t *canvas_get_quic(CanvasBase *canvas, SpiceQUICImage *image, +static pixman_image_t *canvas_get_quic(CanvasBase *canvas, SpiceImage *image, int invers, int want_original) { pixman_image_t *surface = NULL; @@ -445,30 +405,21 @@ static pixman_image_t *canvas_get_quic(CanvasBase *canvas, SpiceQUICImage *image int stride; int width; int height; -#ifndef SW_CANVAS_NO_CHUNKS - DataChunk **tmp; - DataChunk *chunk; -#endif if (setjmp(quic_data->jmp_env)) { pixman_image_unref(surface); CANVAS_ERROR("quic error, %s", quic_data->message_buf); } -#ifdef SW_CANVAS_NO_CHUNKS - if (quic_decode_begin(quic_data->quic, (uint32_t *)image->quic.data, - image->quic.data_size >> 2, &type, &width, &height) == QUIC_ERROR) { - CANVAS_ERROR("quic decode begin failed"); - } -#else - tmp = (DataChunk **)image->quic.data; - chunk = *tmp; - quic_data->next = chunk->next; - if (quic_decode_begin(quic_data->quic, (uint32_t *)chunk->data, chunk->size >> 2, + quic_data->chunks = image->u.quic.data; + quic_data->current_chunk = 0; + + if (quic_decode_begin(quic_data->quic, + (uint32_t *)image->u.quic.data->chunk[0].data, + image->u.quic.data->chunk[0].len >> 2, &type, &width, &height) == QUIC_ERROR) { CANVAS_ERROR("quic decode begin failed"); } -#endif switch (type) { case QUIC_IMAGE_TYPE_RGBA: @@ -564,7 +515,7 @@ static void dump_jpeg(uint8_t* data, int data_size) } #endif -static pixman_image_t *canvas_get_jpeg(CanvasBase *canvas, SpiceJPEGImage *image, int invers) +static pixman_image_t *canvas_get_jpeg(CanvasBase *canvas, SpiceImage *image, int invers) { pixman_image_t *surface = NULL; int stride; @@ -572,7 +523,8 @@ static pixman_image_t *canvas_get_jpeg(CanvasBase *canvas, SpiceJPEGImage *image int height; uint8_t *dest; - canvas->jpeg->ops->begin_decode(canvas->jpeg, image->jpeg.data, image->jpeg.data_size, + ASSERT(image->u.jpeg.data->num_chunks == 1); /* TODO: Handle chunks */ + canvas->jpeg->ops->begin_decode(canvas->jpeg, image->u.jpeg.data->chunk[0].data, image->u.jpeg.data->chunk[0].len, &width, &height); ASSERT((uint32_t)width == image->descriptor.width); ASSERT((uint32_t)height == image->descriptor.height); @@ -606,13 +558,13 @@ static pixman_image_t *canvas_get_jpeg(CanvasBase *canvas, SpiceJPEGImage *image } } #ifdef DUMP_JPEG - dump_jpeg(image->jpeg.data, image->jpeg.data_size); + dump_jpeg(image->u.jpeg.data, image->u.jpeg.data_size); #endif return surface; } static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas, - SpiceJPEGAlphaImage *image, int invers) + SpiceImage *image, int invers) { pixman_image_t *surface = NULL; int stride; @@ -627,13 +579,15 @@ static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas, int alpha_size; int lz_alpha_width, lz_alpha_height, n_comp_pixels, lz_alpha_top_down; - canvas->jpeg->ops->begin_decode(canvas->jpeg, image->jpeg_alpha.data, - image->jpeg_alpha.jpeg_size, + ASSERT(image->u.jpeg_alpha.data->num_chunks == 1); + canvas->jpeg->ops->begin_decode(canvas->jpeg, + image->u.jpeg_alpha.data->chunk[0].data, + image->u.jpeg_alpha.data->chunk[0].len, &width, &height); ASSERT((uint32_t)width == image->descriptor.width); ASSERT((uint32_t)height == image->descriptor.height); - if (image->jpeg_alpha.flags & SPICE_JPEG_ALPHA_FLAGS_TOP_DOWN) { + if (image->u.jpeg_alpha.flags & SPICE_JPEG_ALPHA_FLAGS_TOP_DOWN) { alpha_top_down = TRUE; } @@ -642,7 +596,7 @@ static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas, #endif surface = alloc_lz_image_surface(&lz_data->decode_data, PIXMAN_a8r8g8b8, width, height, width*height, alpha_top_down); - + if (surface == NULL) { CANVAS_ERROR("create surface failed"); } @@ -651,9 +605,9 @@ static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas, stride = pixman_image_get_stride(surface); canvas->jpeg->ops->decode(canvas->jpeg, dest, stride, SPICE_BITMAP_FMT_32BIT); - - comp_alpha_buf = image->jpeg_alpha.data + image->jpeg_alpha.jpeg_size; - alpha_size = image->jpeg_alpha.data_size - image->jpeg_alpha.jpeg_size; + + comp_alpha_buf = image->u.jpeg_alpha.data->chunk[0].data + image->u.jpeg_alpha.jpeg_size; + alpha_size = image->u.jpeg_alpha.data_size - image->u.jpeg_alpha.jpeg_size; lz_decode_begin(lz_data->lz, comp_alpha_buf, alpha_size, &lz_alpha_type, &lz_alpha_width, &lz_alpha_height, &n_comp_pixels, @@ -685,7 +639,7 @@ static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas, } } #ifdef DUMP_JPEG - dump_jpeg(image->jpeg_alpha.data, image->jpeg_alpha.jpeg_size); + dump_jpeg(image->u.jpeg_alpha.data, image->u.jpeg_alpha.jpeg_size); #endif return surface; } @@ -698,7 +652,9 @@ static pixman_image_t *canvas_bitmap_to_surface(CanvasBase *canvas, SpiceBitmap* pixman_image_t *image; pixman_format_code_t format; - src = (uint8_t *)SPICE_GET_ADDRESS(bitmap->data); + spice_chunks_linearize(bitmap->data); + + src = bitmap->data->chunk[0].data; src_stride = bitmap->stride; if (want_original) { @@ -730,27 +686,24 @@ static pixman_image_t *canvas_bitmap_to_surface(CanvasBase *canvas, SpiceBitmap* #ifdef SW_CANVAS_CACHE -static inline SpicePalette *canvas_get_palette(CanvasBase *canvas, SPICE_ADDRESS base_palette, uint8_t flags) +static inline SpicePalette *canvas_get_palette(CanvasBase *canvas, SpicePalette *base_palette, uint64_t palette_id, uint8_t flags) { SpicePalette *palette; - if (!base_palette) { - return NULL; - } if (flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE) { - palette = canvas->palette_cache->ops->get(canvas->palette_cache, base_palette); - } else if (flags & SPICE_BITMAP_FLAGS_PAL_CACHE_ME) { - palette = (SpicePalette *)SPICE_GET_ADDRESS(base_palette); - canvas->palette_cache->ops->put(canvas->palette_cache, palette); + palette = canvas->palette_cache->ops->get(canvas->palette_cache, palette_id); } else { - palette = (SpicePalette *)SPICE_GET_ADDRESS(base_palette); + palette = base_palette; + if (palette != NULL && flags & SPICE_BITMAP_FLAGS_PAL_CACHE_ME) { + canvas->palette_cache->ops->put(canvas->palette_cache, palette); + } } return palette; } -static inline SpicePalette *canvas_get_localized_palette(CanvasBase *canvas, SPICE_ADDRESS base_palette, uint8_t flags, int *free_palette) +static inline SpicePalette *canvas_get_localized_palette(CanvasBase *canvas, SpicePalette *base_palette, uint64_t palette_id, uint8_t flags, int *free_palette) { - SpicePalette *palette = canvas_get_palette(canvas, base_palette, flags); + SpicePalette *palette = canvas_get_palette(canvas, base_palette, palette_id, flags); SpicePalette *copy; uint32_t *now, *end; size_t size; @@ -784,7 +737,7 @@ static inline SpicePalette *canvas_get_localized_palette(CanvasBase *canvas, SPI return copy; } -static pixman_image_t *canvas_get_lz(CanvasBase *canvas, LZImage *image, int invers, +static pixman_image_t *canvas_get_lz(CanvasBase *canvas, SpiceImage *image, int invers, int want_original) { LzData *lz_data = &canvas->lz_data; @@ -811,13 +764,15 @@ static pixman_image_t *canvas_get_lz(CanvasBase *canvas, LZImage *image, int inv free_palette = FALSE; if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB) { - comp_buf = image->lz_rgb.data; - comp_size = image->lz_rgb.data_size; + ASSERT(image->u.lz_rgb.data->num_chunks == 1); /* TODO: Handle chunks */ + comp_buf = image->u.lz_rgb.data->chunk[0].data; + comp_size = image->u.lz_rgb.data->chunk[0].len; palette = NULL; } else if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) { - comp_buf = image->lz_plt.data; - comp_size = image->lz_plt.data_size; - palette = canvas_get_localized_palette(canvas, image->lz_plt.palette, image->lz_plt.flags, &free_palette); + ASSERT(image->u.lz_plt.data->num_chunks == 1); /* TODO: Handle chunks */ + comp_buf = image->u.lz_plt.data->chunk[0].data; + comp_size = image->u.lz_plt.data->chunk[0].len; + palette = canvas_get_localized_palette(canvas, image->u.lz_plt.palette, image->u.lz_plt.palette_id, image->u.lz_plt.flags, &free_palette); } else { CANVAS_ERROR("unexpected image type"); } @@ -918,7 +873,7 @@ static pixman_image_t *canvas_get_glz_rgb_common(CanvasBase *canvas, uint8_t *da // don't handle plts since bitmaps with plt can be decoded globally to RGB32 (because // same byte sequence can be transformed to different RGB pixels by different plts) -static pixman_image_t *canvas_get_glz(CanvasBase *canvas, LZImage *image, +static pixman_image_t *canvas_get_glz(CanvasBase *canvas, SpiceImage *image, int want_original) { ASSERT(image->descriptor.type == SPICE_IMAGE_TYPE_GLZ_RGB); @@ -926,10 +881,11 @@ static pixman_image_t *canvas_get_glz(CanvasBase *canvas, LZImage *image, canvas->glz_data.decode_data.dc = canvas->dc; #endif - return canvas_get_glz_rgb_common(canvas, image->lz_rgb.data, want_original); + ASSERT(image->u.lz_rgb.data->num_chunks == 1); /* TODO: Handle chunks */ + return canvas_get_glz_rgb_common(canvas, image->u.lz_rgb.data->chunk[0].data, want_original); } -static pixman_image_t *canvas_get_zlib_glz_rgb(CanvasBase *canvas, SpiceZlibGlzRGBImage *image, +static pixman_image_t *canvas_get_zlib_glz_rgb(CanvasBase *canvas, SpiceImage *image, int want_original) { uint8_t *glz_data; @@ -939,9 +895,11 @@ static pixman_image_t *canvas_get_zlib_glz_rgb(CanvasBase *canvas, SpiceZlibGlzR CANVAS_ERROR("zlib not supported"); } - glz_data = (uint8_t*)spice_malloc(image->zlib_glz.glz_data_size); - canvas->zlib->ops->decode(canvas->zlib, image->zlib_glz.data, image->zlib_glz.data_size, - glz_data, image->zlib_glz.glz_data_size); + ASSERT(image->u.zlib_glz.data->num_chunks == 1); /* TODO: Handle chunks */ + glz_data = (uint8_t*)spice_malloc(image->u.zlib_glz.glz_data_size); + canvas->zlib->ops->decode(canvas->zlib, image->u.zlib_glz.data->chunk[0].data, + image->u.zlib_glz.data->chunk[0].len, + glz_data, image->u.zlib_glz.glz_data_size); surface = canvas_get_glz_rgb_common(canvas, glz_data, want_original); free(glz_data); return surface; @@ -993,7 +951,7 @@ static pixman_image_t *canvas_get_bits(CanvasBase *canvas, SpiceBitmap *bitmap, pixman_image_t* surface; SpicePalette *palette; - palette = canvas_get_palette(canvas, bitmap->palette, bitmap->flags); + palette = canvas_get_palette(canvas, bitmap->palette, bitmap->palette_id, bitmap->flags); #ifdef DEBUG_DUMP_BITMAP if (palette) { dump_bitmap(bitmap, palette); @@ -1079,26 +1037,20 @@ static void dump_surface(pixman_image_t *surface, int cache) #endif -static SpiceCanvas *canvas_get_surface_internal(CanvasBase *canvas, SPICE_ADDRESS addr) +static SpiceCanvas *canvas_get_surface_internal(CanvasBase *canvas, SpiceImage *image) { - SpiceImageDescriptor *descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr); - - if (descriptor->type == SPICE_IMAGE_TYPE_SURFACE) { - SpiceSurfaceImage *surface = (SpiceSurfaceImage *)descriptor; - return canvas->surfaces->ops->get(canvas->surfaces, surface->surface.surface_id); + if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) { + SpiceSurface *surface = &image->u.surface; + return canvas->surfaces->ops->get(canvas->surfaces, surface->surface_id); } return NULL; } -static SpiceCanvas *canvas_get_surface_mask_internal(CanvasBase *canvas, SPICE_ADDRESS addr) +static SpiceCanvas *canvas_get_surface_mask_internal(CanvasBase *canvas, SpiceImage *image) { - SpiceImageDescriptor *descriptor; - - descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr); - - if (descriptor->type == SPICE_IMAGE_TYPE_SURFACE) { - SpiceSurfaceImage *surface = (SpiceSurfaceImage *)descriptor; - return canvas->surfaces->ops->get(canvas->surfaces, surface->surface.surface_id); + if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) { + SpiceSurface *surface = &image->u.surface; + return canvas->surfaces->ops->get(canvas->surfaces, surface->surface_id); } return NULL; } @@ -1115,10 +1067,10 @@ static SpiceCanvas *canvas_get_surface_mask_internal(CanvasBase *canvas, SPICE_A * you have to be able to handle any image format. This is useful to avoid * e.g. losing alpha when blending a argb32 image on a rgb16 surface. */ -static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRESS addr, +static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SpiceImage *image, int want_original, int real_get) { - SpiceImageDescriptor *descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr); + SpiceImageDescriptor *descriptor = &image->descriptor; pixman_image_t *surface, *converted; pixman_format_code_t wanted_format, surface_format; int saved_want_original; @@ -1150,40 +1102,33 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE switch (descriptor->type) { case SPICE_IMAGE_TYPE_QUIC: { - SpiceQUICImage *image = (SpiceQUICImage *)descriptor; surface = canvas_get_quic(canvas, image, 0, want_original); break; } -#ifdef SW_CANVAS_NO_CHUNKS +#if defined(SW_CANVAS_CACHE) case SPICE_IMAGE_TYPE_LZ_PLT: { - LZImage *image = (LZImage *)descriptor; surface = canvas_get_lz(canvas, image, 0, want_original); break; } case SPICE_IMAGE_TYPE_LZ_RGB: { - LZImage *image = (LZImage *)descriptor; surface = canvas_get_lz(canvas, image, 0, want_original); break; } #endif case SPICE_IMAGE_TYPE_JPEG: { - SpiceJPEGImage *image = (SpiceJPEGImage *)descriptor; surface = canvas_get_jpeg(canvas, image, 0); break; } case SPICE_IMAGE_TYPE_JPEG_ALPHA: { - SpiceJPEGAlphaImage *image = (SpiceJPEGAlphaImage *)descriptor; surface = canvas_get_jpeg_alpha(canvas, image, 0); break; } #if defined(SW_CANVAS_CACHE) case SPICE_IMAGE_TYPE_GLZ_RGB: { - LZImage *image = (LZImage *)descriptor; surface = canvas_get_glz(canvas, image, want_original); break; } case SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB: { - SpiceZlibGlzRGBImage *image = (SpiceZlibGlzRGBImage *)descriptor; surface = canvas_get_zlib_glz_rgb(canvas, image, want_original); break; } @@ -1197,8 +1142,7 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE break; #endif case SPICE_IMAGE_TYPE_BITMAP: { - SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor; - surface = canvas_get_bits(canvas, &bitmap->bitmap, want_original); + surface = canvas_get_bits(canvas, &image->u.bitmap, want_original); break; } default: @@ -1298,10 +1242,10 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE #else -static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRESS addr, +static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SpiceImage *image, int want_original, int real_get) { - SpiceImageDescriptor *descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr); + SpiceImageDescriptor *descriptor = &image->descriptor; pixman_format_code_t format; /* When touching, never load image. */ @@ -1311,12 +1255,10 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE switch (descriptor->type) { case SPICE_IMAGE_TYPE_QUIC: { - SpiceQUICImage *image = (SpiceQUICImage *)descriptor; return canvas_get_quic(canvas, image, 0); } case SPICE_IMAGE_TYPE_BITMAP: { - SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor; - return canvas_get_bits(canvas, &bitmap->bitmap, want_original, &format); + return canvas_get_bits(canvas, &image->u.bitmap, want_original, &format); } default: CANVAS_ERROR("invalid image type"); @@ -1325,25 +1267,25 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE #endif -static SpiceCanvas *canvas_get_surface_mask(CanvasBase *canvas, SPICE_ADDRESS addr) +static SpiceCanvas *canvas_get_surface_mask(CanvasBase *canvas, SpiceImage *image) { - return canvas_get_surface_mask_internal(canvas, addr); + return canvas_get_surface_mask_internal(canvas, image); } -static SpiceCanvas *canvas_get_surface(CanvasBase *canvas, SPICE_ADDRESS addr) +static SpiceCanvas *canvas_get_surface(CanvasBase *canvas, SpiceImage *image) { - return canvas_get_surface_internal(canvas, addr); + return canvas_get_surface_internal(canvas, image); } -static pixman_image_t *canvas_get_image(CanvasBase *canvas, SPICE_ADDRESS addr, +static pixman_image_t *canvas_get_image(CanvasBase *canvas, SpiceImage *image, int want_original) { - return canvas_get_image_internal(canvas, addr, want_original, TRUE); + return canvas_get_image_internal(canvas, image, want_original, TRUE); } -static void canvas_touch_image(CanvasBase *canvas, SPICE_ADDRESS addr) +static void canvas_touch_image(CanvasBase *canvas, SpiceImage *image) { - canvas_get_image_internal(canvas, addr, TRUE, FALSE); + canvas_get_image_internal(canvas, image, TRUE, FALSE); } static pixman_image_t* canvas_get_image_from_self(SpiceCanvas *canvas, @@ -1407,7 +1349,8 @@ static pixman_image_t *canvas_get_bitmap_mask(CanvasBase *canvas, SpiceBitmap* b CANVAS_ERROR("create surface failed"); } - src_line = (uint8_t *)SPICE_GET_ADDRESS(bitmap->data); + spice_chunks_linearize(bitmap->data); + src_line = bitmap->data->chunk[0].data; src_stride = bitmap->stride; end_line = src_line + (bitmap->y * src_stride); line_size = SPICE_ALIGN(bitmap->x, 8) >> 3; @@ -1530,7 +1473,7 @@ static inline pixman_image_t *canvas_A1_invers(pixman_image_t *src_surf) static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int *needs_invert_out) { - SpiceImageDescriptor *descriptor; + SpiceImage *image; pixman_image_t *surface; int need_invers; int is_invers; @@ -1540,31 +1483,30 @@ static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int *needs_invert_out = 0; } - descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(mask->bitmap); + image = mask->bitmap; need_invers = mask->flags & SPICE_MASK_FLAGS_INVERS; #ifdef SW_CANVAS_CACHE - cache_me = descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME; + cache_me = image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME; #else cache_me = 0; #endif - switch (descriptor->type) { + switch (image->descriptor.type) { case SPICE_IMAGE_TYPE_BITMAP: { - SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor; is_invers = need_invers && !cache_me; - surface = canvas_get_bitmap_mask(canvas, &bitmap->bitmap, is_invers); + surface = canvas_get_bitmap_mask(canvas, &image->u.bitmap, is_invers); break; } #if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE) case SPICE_IMAGE_TYPE_FROM_CACHE: - surface = canvas->bits_cache->ops->get(canvas->bits_cache, descriptor->id); + surface = canvas->bits_cache->ops->get(canvas->bits_cache, image->descriptor.id); 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); + surface = canvas->bits_cache->ops->get_lossless(canvas->bits_cache, image->descriptor.id); is_invers = 0; break; #endif @@ -1574,7 +1516,7 @@ static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int #if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE) if (cache_me) { - canvas->bits_cache->ops->put(canvas->bits_cache, descriptor->id, surface); + canvas->bits_cache->ops->put(canvas->bits_cache, image->descriptor.id, surface); } if (need_invers && !is_invers) { // surface is in cache @@ -1847,13 +1789,6 @@ static void quic_usr_free(QuicUsrContext *usr, void *ptr) free(ptr); } -#ifdef SW_CANVAS_NO_CHUNKS - -static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed) -{ - return 0; -} - static void lz_usr_warn(LzUsrContext *usr, const char *fmt, ...) { LzData *usr_data = (LzData *)usr; @@ -1896,29 +1831,19 @@ static int lz_usr_more_lines(LzUsrContext *usr, uint8_t **lines) return 0; } -#else - static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed) { QuicData *quic_data = (QuicData *)usr; - DataChunk *chunk; - uint32_t size; - if (!quic_data->next) { + if (quic_data->current_chunk == quic_data->chunks->num_chunks -1) { return 0; } - chunk = (DataChunk *)quic_data->virt_mapping->ops->get_virt(quic_data->virt_mapping, quic_data->next, - sizeof(DataChunk)); - size = chunk->size; - quic_data->virt_mapping->ops->validate_virt(quic_data->virt_mapping, (unsigned long)chunk->data, - quic_data->next, size); + quic_data->current_chunk++; - quic_data->next = chunk->next; - *io_ptr = (uint32_t *)chunk->data; - return size >> 2; + *io_ptr = (uint32_t *)quic_data->chunks->chunk[quic_data->current_chunk].data; + return quic_data->chunks->chunk[quic_data->current_chunk].len >> 2; } -#endif static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines) { @@ -1928,9 +1853,7 @@ static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines) static void canvas_base_destroy(CanvasBase *canvas) { quic_destroy(canvas->quic_data.quic); -#ifdef SW_CANVAS_NO_CHUNKS lz_destroy(canvas->lz_data.lz); -#endif #ifdef GDI_CANVAS DeleteDC(canvas->dc); #endif @@ -3398,9 +3321,6 @@ static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops, , SpiceGlzDecoder *glz_decoder , SpiceJpegDecoder *jpeg_decoder , SpiceZlibDecoder *zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , SpiceVirtMapping *virt_mapping -#endif ) { canvas->parent.ops = ops; @@ -3411,13 +3331,10 @@ static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops, canvas->quic_data.usr.free = quic_usr_free; canvas->quic_data.usr.more_space = quic_usr_more_space; canvas->quic_data.usr.more_lines = quic_usr_more_lines; -#ifndef SW_CANVAS_NO_CHUNKS - canvas->quic_data.virt_mapping = virt_mapping; -#endif if (!(canvas->quic_data.quic = quic_create(&canvas->quic_data.usr))) { return 0; } -#ifdef SW_CANVAS_NO_CHUNKS + canvas->lz_data.usr.error = lz_usr_error; canvas->lz_data.usr.warn = lz_usr_warn; canvas->lz_data.usr.info = lz_usr_warn; @@ -3428,7 +3345,7 @@ static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops, if (!(canvas->lz_data.lz = lz_create(&canvas->lz_data.usr))) { return 0; } -#endif + canvas->surfaces = surfaces; canvas->glz_data.decoder = glz_decoder; canvas->jpeg = jpeg_decoder; diff --git a/common/canvas_base.h b/common/canvas_base.h index 9dfbe85..36199a7 100644 --- a/common/canvas_base.h +++ b/common/canvas_base.h @@ -33,7 +33,6 @@ typedef struct _SpicePaletteCache SpicePaletteCache; typedef struct _SpiceGlzDecoder SpiceGlzDecoder; typedef struct _SpiceJpegDecoder SpiceJpegDecoder; typedef struct _SpiceZlibDecoder SpiceZlibDecoder; -typedef struct _SpiceVirtMapping SpiceVirtMapping; typedef struct _SpiceCanvas SpiceCanvas; typedef struct { @@ -121,16 +120,6 @@ struct _SpiceZlibDecoder { }; typedef struct { - void *(*get_virt)(SpiceVirtMapping *mapping, unsigned long addr, uint32_t add_size); - void (*validate_virt)(SpiceVirtMapping *mapping, unsigned long virt, - unsigned long from_addr, uint32_t add_size); -} SpiceVirtMappingOps; - -struct _SpiceVirtMapping { - SpiceVirtMappingOps *ops; -}; - -typedef struct { void (*draw_fill)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill); void (*draw_copy)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy); void (*draw_opaque)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque); diff --git a/common/gl_canvas.c b/common/gl_canvas.c index f0e10dd..a5c8511 100644 --- a/common/gl_canvas.c +++ b/common/gl_canvas.c @@ -806,9 +806,6 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format , SpiceGlzDecoder *glz_decoder , SpiceJpegDecoder *jpeg_decoder , SpiceZlibDecoder *zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , SpiceVirtMapping *virt_mapping -#endif ) { GLCanvas *canvas; @@ -835,9 +832,6 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format , glz_decoder , jpeg_decoder , zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , virt_mapping -#endif ); if (!init_ok) { goto error_2; diff --git a/common/gl_canvas.h b/common/gl_canvas.h index d3f707a..dfb59bb 100644 --- a/common/gl_canvas.h +++ b/common/gl_canvas.h @@ -32,9 +32,6 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format , SpiceGlzDecoder *glz_decoder , SpiceJpegDecoder *jpeg_decoder , SpiceZlibDecoder *zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , SpiceVirtMapping *virt_mapping -#endif ); void gl_canvas_set_textures_lost(SpiceCanvas *canvas, int textures_lost); void gl_canvas_init(); diff --git a/common/sw_canvas.c b/common/sw_canvas.c index 56865c3..78cc1e4 100644 --- a/common/sw_canvas.c +++ b/common/sw_canvas.c @@ -1173,9 +1173,6 @@ static SpiceCanvas *canvas_create_common(pixman_image_t *image, , SpiceGlzDecoder *glz_decoder , SpiceJpegDecoder *jpeg_decoder , SpiceZlibDecoder *zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , SpiceVirtMapping *virt_mapping -#endif ) { SwCanvas *canvas; @@ -1202,9 +1199,6 @@ static SpiceCanvas *canvas_create_common(pixman_image_t *image, , glz_decoder , jpeg_decoder , zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , virt_mapping -#endif ); canvas->private_data = NULL; canvas->private_data_size = 0; @@ -1225,9 +1219,6 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format , SpiceGlzDecoder *glz_decoder , SpiceJpegDecoder *jpeg_decoder , SpiceZlibDecoder *zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , SpiceVirtMapping *virt_mapping -#endif ) { pixman_image_t *image; @@ -1246,9 +1237,6 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format , glz_decoder , jpeg_decoder , zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , virt_mapping -#endif ); } @@ -1264,9 +1252,6 @@ SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, , SpiceGlzDecoder *glz_decoder , SpiceJpegDecoder *jpeg_decoder , SpiceZlibDecoder *zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , SpiceVirtMapping *virt_mapping -#endif ) { pixman_image_t *image; @@ -1285,9 +1270,6 @@ SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, , glz_decoder , jpeg_decoder , zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , virt_mapping -#endif ); } diff --git a/common/sw_canvas.h b/common/sw_canvas.h index 05e4071..d4573bb 100644 --- a/common/sw_canvas.h +++ b/common/sw_canvas.h @@ -37,9 +37,6 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format , SpiceGlzDecoder *glz_decoder , SpiceJpegDecoder *jpeg_decoder , SpiceZlibDecoder *zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , SpiceVirtMapping *virt_mapping -#endif ); SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, uint8_t *data, size_t stride @@ -53,9 +50,6 @@ SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, uint , SpiceGlzDecoder *glz_decoder , SpiceJpegDecoder *jpeg_decoder , SpiceZlibDecoder *zlib_decoder -#ifndef SW_CANVAS_NO_CHUNKS - , SpiceVirtMapping *virt_mapping -#endif ); diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 323fc70..1ae1911 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -93,7 +93,7 @@ def write_read_primitive(writer, start, container, name, scope): writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size")) writer.error_check("pos + %s > message_end" % m.member_type.get_fixed_nw_size()) - var = "%s__value" % (name) + var = "%s__value" % (name.replace(".", "_")) if not scope.variable_defined(var): scope.variable_def(m.member_type.c_type(), var) writer.assign(var, "read_%s(pos)" % (m.member_type.primitive_type())) @@ -112,7 +112,7 @@ def write_read_primitive_item(writer, item, scope): assert(item.type.is_primitive()) writer.assign("pos", item.get_position()) writer.error_check("pos + %s > message_end" % item.type.get_fixed_nw_size()) - var = "%s__value" % (item.subprefix) + var = "%s__value" % (item.subprefix.replace(".", "_")) scope.variable_def(item.type.c_type(), var) writer.assign(var, "read_%s(pos)" % (item.type.primitive_type())) return var diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py index 68cf3df..715544f 100644 --- a/python_modules/ptypes.py +++ b/python_modules/ptypes.py @@ -811,14 +811,31 @@ class ContainerType(Type): return str(fixed) def lookup_member(self, name): + dot = name.find('.') + rest = None + if dot >= 0: + rest = name[dot+1:] + name = name[:dot] + + member = None if self.members_by_name.has_key(name): - return self.members_by_name[name] - for m in self.members: - if m.is_switch(): - member = m.lookup_case_member(name) - if member: - return member - raise Exception, "No member called %s found" % name + member = self.members_by_name[name] + else: + for m in self.members: + if m.is_switch(): + member = m.lookup_case_member(name) + if member != None: + break + if member != None: + break + + if member == None: + raise Exception, "No member called %s found" % name + + if rest != None: + return member.member_type.lookup_member(rest) + + return member class StructType(ContainerType): def __init__(self, name, members, attribute_list): diff --git a/python_modules/spice_parser.py b/python_modules/spice_parser.py index 61ef458..ac2da8d 100644 --- a/python_modules/spice_parser.py +++ b/python_modules/spice_parser.py @@ -95,7 +95,7 @@ def SPICE_BNF(): switchCase = Group(Group(OneOrMore(default_.setParseAction(replaceWith(None)) + colon | case_.suppress() + identifier + colon)) + variableDef) \ .setParseAction(lambda toks: ptypes.SwitchCase(toks[0][0], toks[0][1])) - switchBody = Group(switch_ + lparen + identifier + rparen + lbrace + Group(OneOrMore(switchCase)) + rbrace + identifier + attributes - semi) \ + switchBody = Group(switch_ + lparen + delimitedList(identifier,delim='.', combine=True) + rparen + lbrace + Group(OneOrMore(switchCase)) + rbrace + identifier + attributes - semi) \ .setParseAction(lambda toks: ptypes.Switch(toks[0][1], toks[0][2], toks[0][3], toks[0][4])) messageBody = structBody = Group(lbrace + ZeroOrMore(variableDef | switchBody) + rbrace) structSpec = Group(struct_ + identifier + structBody + attributes).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3])) diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c index 56f17dc..ee099a0 100644 --- a/server/red_parse_qxl.c +++ b/server/red_parse_qxl.c @@ -17,6 +17,7 @@ */ #include <stdbool.h> +#include <inttypes.h> #include "red_common.h" #include "red_memslots.h" #include "red_parse_qxl.h" @@ -99,7 +100,6 @@ static size_t red_get_data_chunks_ptr(RedMemSlotInfo *slots, int group_id, return data_size; } -#if 0 static size_t red_get_data_chunks(RedMemSlotInfo *slots, int group_id, RedDataChunk *red, SPICE_ADDRESS addr) { @@ -109,7 +109,6 @@ static size_t red_get_data_chunks(RedMemSlotInfo *slots, int group_id, qxl = (QXLDataChunk*)get_virt(slots, addr, sizeof(*qxl), group_id); return red_get_data_chunks_ptr(slots, group_id, memslot_id, red, qxl); } -#endif static void red_put_data_chunks(RedDataChunk *red) { @@ -255,6 +254,151 @@ static SpiceClipRects *red_get_clip_rects(RedMemSlotInfo *slots, int group_id, return red; } +static SpiceChunks *red_get_image_data_flat(RedMemSlotInfo *slots, int group_id, + SPICE_ADDRESS addr, size_t size) +{ + SpiceChunks *data; + + data = spice_chunks_new(1); + data->data_size = size; + data->chunk[0].data = (void*)get_virt(slots, addr, size, group_id); + data->chunk[0].len = size; + return data; +} + +static SpiceChunks *red_get_image_data_chunked(RedMemSlotInfo *slots, int group_id, + RedDataChunk *head) +{ + SpiceChunks *data; + RedDataChunk *chunk; + int i; + + for (i = 0, chunk = head; chunk != NULL; chunk = chunk->next_chunk) { + i++; + } + + data = spice_chunks_new(i); + data->data_size = 0; + for (i = 0, chunk = head; + chunk != NULL && i < data->num_chunks; + chunk = chunk->next_chunk, i++) { + data->chunk[i].data = chunk->data; + data->chunk[i].len = chunk->data_size; + data->data_size += chunk->data_size; + } + ASSERT(i == data->num_chunks); + return data; +} + +static SpiceImage *red_get_image(RedMemSlotInfo *slots, int group_id, + SPICE_ADDRESS addr) +{ + RedDataChunk chunks; + QXLImage *qxl; + SpiceImage *red; + size_t bitmap_size, size; + uint8_t qxl_flags; + + if (addr == 0) { + return NULL; + } + + qxl = (QXLImage *)get_virt(slots, addr, sizeof(*qxl), group_id); + red = spice_new0(SpiceImage, 1); + red->descriptor.id = qxl->descriptor.id; + red->descriptor.type = qxl->descriptor.type; + red->descriptor.flags = 0; + if (qxl->descriptor.flags & QXL_IMAGE_HIGH_BITS_SET) { + red->descriptor.flags |= SPICE_IMAGE_FLAGS_HIGH_BITS_SET; + } + if (qxl->descriptor.flags & QXL_IMAGE_CACHE) { + red->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_ME; + } + red->descriptor.width = qxl->descriptor.width; + red->descriptor.height = qxl->descriptor.height; + + switch (red->descriptor.type) { + case SPICE_IMAGE_TYPE_BITMAP: + red->u.bitmap.format = qxl->bitmap.format; + qxl_flags = qxl->bitmap.flags; + if (qxl_flags & QXL_BITMAP_TOP_DOWN) { + red->u.bitmap.flags = SPICE_BITMAP_FLAGS_TOP_DOWN; + } + red->u.bitmap.x = qxl->bitmap.x; + red->u.bitmap.y = qxl->bitmap.y; + red->u.bitmap.stride = qxl->bitmap.stride; + if (qxl->bitmap.palette) { + QXLPalette *qp; + SpicePalette *rp; + int i, num_ents; + qp = (QXLPalette *)get_virt(slots, qxl->bitmap.palette, + sizeof(*qp), group_id); + num_ents = qp->num_ents; + validate_virt(slots, (intptr_t)qp->ents, + get_memslot_id(slots, qxl->bitmap.palette), + num_ents * sizeof(qp->ents[0]), group_id); + rp = spice_malloc_n_m(num_ents, sizeof(rp->ents[0]), sizeof(*rp)); + rp->unique = qp->unique; + rp->num_ents = num_ents; + for (i = 0; i < num_ents; i++) { + rp->ents[i] = qp->ents[i]; + } + red->u.bitmap.palette = rp; + red->u.bitmap.palette_id = rp->unique; + } + bitmap_size = red->u.bitmap.y * abs(red->u.bitmap.stride); + if (qxl_flags & QXL_BITMAP_DIRECT) { + red->u.bitmap.data = red_get_image_data_flat(slots, group_id, + qxl->bitmap.data, + bitmap_size); + } else { + size = red_get_data_chunks(slots, group_id, + &chunks, qxl->bitmap.data); + ASSERT(size == bitmap_size); + red->u.bitmap.data = red_get_image_data_chunked(slots, group_id, + &chunks); + red_put_data_chunks(&chunks); + } + if (qxl_flags & QXL_BITMAP_UNSTABLE) { + red->u.bitmap.data->flags |= SPICE_CHUNKS_FLAGS_UNSTABLE; + } + break; + case SPICE_IMAGE_TYPE_SURFACE: + red->u.surface.surface_id = qxl->surface_image.surface_id; + break; + case SPICE_IMAGE_TYPE_QUIC: + red->u.quic.data_size = qxl->quic.data_size; + size = red_get_data_chunks_ptr(slots, group_id, + get_memslot_id(slots, addr), + &chunks, (QXLDataChunk *)qxl->quic.data); + ASSERT(size == red->u.quic.data_size); + red->u.quic.data = red_get_image_data_chunked(slots, group_id, + &chunks); + red_put_data_chunks(&chunks); + break; + default: + red_error("%s: unknown type %d", __FUNCTION__, red->descriptor.type); + abort(); + } + return red; +} + +void red_put_image(SpiceImage *red) +{ + if (red == NULL) + return; + + switch (red->descriptor.type) { + case SPICE_IMAGE_TYPE_BITMAP: + if (red->u.bitmap.palette) { + free(red->u.bitmap.palette); + } + spice_chunks_destroy(red->u.bitmap.data); + break; + } + free(red); +} + static void red_get_brush_ptr(RedMemSlotInfo *slots, int group_id, SpiceBrush *red, QXLBrush *qxl) { @@ -264,18 +408,32 @@ static void red_get_brush_ptr(RedMemSlotInfo *slots, int group_id, red->u.color = qxl->u.color; break; case SPICE_BRUSH_TYPE_PATTERN: - red->u.pattern.pat = qxl->u.pattern.pat; + red->u.pattern.pat = red_get_image(slots, group_id, qxl->u.pattern.pat); red_get_point_ptr(&red->u.pattern.pos, &qxl->u.pattern.pos); break; } } +static void red_put_brush(SpiceBrush *red) +{ + switch (red->type) { + case SPICE_BRUSH_TYPE_PATTERN: + red_put_image(red->u.pattern.pat); + break; + } +} + static void red_get_qmask_ptr(RedMemSlotInfo *slots, int group_id, SpiceQMask *red, QXLQMask *qxl) { red->flags = qxl->flags; red_get_point_ptr(&red->pos, &qxl->pos); - red->bitmap = qxl->bitmap; + red->bitmap = red_get_image(slots, group_id, qxl->bitmap); +} + +static void red_put_qmask(SpiceQMask *red) +{ + red_put_image(red->bitmap); } static void red_get_fill_ptr(RedMemSlotInfo *slots, int group_id, @@ -286,10 +444,16 @@ static void red_get_fill_ptr(RedMemSlotInfo *slots, int group_id, red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); } +static void red_put_fill(SpiceFill *red) +{ + red_put_brush(&red->brush); + red_put_qmask(&red->mask); +} + static void red_get_opaque_ptr(RedMemSlotInfo *slots, int group_id, SpiceOpaque *red, QXLOpaque *qxl) { - red->src_bitmap = qxl->src_bitmap; + red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap); red_get_rect_ptr(&red->src_area, &qxl->src_area); red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush); red->rop_descriptor = qxl->rop_descriptor; @@ -297,41 +461,65 @@ static void red_get_opaque_ptr(RedMemSlotInfo *slots, int group_id, red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); } +static void red_put_opaque(SpiceOpaque *red) +{ + red_put_image(red->src_bitmap); + red_put_brush(&red->brush); + red_put_qmask(&red->mask); +} + static void red_get_copy_ptr(RedMemSlotInfo *slots, int group_id, SpiceCopy *red, QXLCopy *qxl) { - red->src_bitmap = qxl->src_bitmap; + red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap); red_get_rect_ptr(&red->src_area, &qxl->src_area); red->rop_descriptor = qxl->rop_descriptor; red->scale_mode = qxl->scale_mode; red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); } +static void red_put_copy(SpiceCopy *red) +{ + red_put_image(red->src_bitmap); + red_put_qmask(&red->mask); +} + static void red_get_blend_ptr(RedMemSlotInfo *slots, int group_id, SpiceBlend *red, QXLBlend *qxl) { - red->src_bitmap = qxl->src_bitmap; + red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap); red_get_rect_ptr(&red->src_area, &qxl->src_area); red->rop_descriptor = qxl->rop_descriptor; red->scale_mode = qxl->scale_mode; red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); } +static void red_put_blend(SpiceBlend *red) +{ + red_put_image(red->src_bitmap); + red_put_qmask(&red->mask); +} + static void red_get_transparent_ptr(RedMemSlotInfo *slots, int group_id, SpiceTransparent *red, QXLTransparent *qxl) { - red->src_bitmap = qxl->src_bitmap; + red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap); red_get_rect_ptr(&red->src_area, &qxl->src_area); red->src_color = qxl->src_color; red->true_color = qxl->true_color; } +static void red_put_transparent(SpiceTransparent *red) +{ + red_put_image(red->src_bitmap); +} + static void red_get_alpha_blend_ptr(RedMemSlotInfo *slots, int group_id, SpiceAlphaBlnd *red, QXLAlphaBlnd *qxl) { red->alpha_flags = qxl->alpha_flags; red->alpha = qxl->alpha; - red->src_bitmap = qxl->src_bitmap; + red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap); red_get_rect_ptr(&red->src_area, &qxl->src_area); } @@ -339,14 +527,19 @@ static void red_get_alpha_blend_ptr_compat(RedMemSlotInfo *slots, int group_id, SpiceAlphaBlnd *red, QXLCompatAlphaBlnd *qxl) { red->alpha = qxl->alpha; - red->src_bitmap = qxl->src_bitmap; + red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap); red_get_rect_ptr(&red->src_area, &qxl->src_area); } +static void red_put_alpha_blend(SpiceAlphaBlnd *red) +{ + red_put_image(red->src_bitmap); +} + static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id, SpiceRop3 *red, QXLRop3 *qxl) { - red->src_bitmap = qxl->src_bitmap; + red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap); red_get_rect_ptr(&red->src_area, &qxl->src_area); red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush); red->rop3 = qxl->rop3; @@ -354,6 +547,13 @@ static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id, red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); } +static void red_put_rop3(SpiceRop3 *red) +{ + red_put_image(red->src_bitmap); + red_put_brush(&red->brush); + red_put_qmask(&red->mask); +} + static void red_get_stroke_ptr(RedMemSlotInfo *slots, int group_id, SpiceStroke *red, QXLStroke *qxl) { @@ -371,8 +571,9 @@ static void red_get_stroke_ptr(RedMemSlotInfo *slots, int group_id, red->back_mode = qxl->back_mode; } -static void red_put_stroke_ptr(SpiceStroke *red) +static void red_put_stroke(SpiceStroke *red) { + red_put_brush(&red->brush); free(red->path); } @@ -465,6 +666,8 @@ static void red_get_text_ptr(RedMemSlotInfo *slots, int group_id, static void red_put_text_ptr(SpiceText *red) { free(red->str); + red_put_brush(&red->fore_brush); + red_put_brush(&red->back_brush); } static void red_get_whiteness_ptr(RedMemSlotInfo *slots, int group_id, @@ -473,18 +676,33 @@ static void red_get_whiteness_ptr(RedMemSlotInfo *slots, int group_id, red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); } +static void red_put_whiteness(SpiceWhiteness *red) +{ + red_put_qmask(&red->mask); +} + static void red_get_blackness_ptr(RedMemSlotInfo *slots, int group_id, SpiceBlackness *red, QXLBlackness *qxl) { red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); } +static void red_put_blackness(SpiceWhiteness *red) +{ + red_put_qmask(&red->mask); +} + static void red_get_invers_ptr(RedMemSlotInfo *slots, int group_id, SpiceInvers *red, QXLInvers *qxl) { red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); } +static void red_put_invers(SpiceWhiteness *red) +{ + red_put_qmask(&red->mask); +} + static void red_get_clip_ptr(RedMemSlotInfo *slots, int group_id, SpiceClip *red, QXLClip *qxl) { @@ -573,7 +791,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id, red_get_whiteness_ptr(slots, group_id, &red->u.whiteness, &qxl->u.whiteness); break; default: - red_error("unknown type"); + red_error("%s: unknown type %d", __FUNCTION__, red->type); break; }; } @@ -637,7 +855,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id, red_get_whiteness_ptr(slots, group_id, &red->u.whiteness, &qxl->u.whiteness); break; default: - red_error("unknown type"); + red_error("%s: unknown type %d", __FUNCTION__, red->type); break; }; } @@ -646,12 +864,42 @@ void red_put_drawable(RedDrawable *red) { red_put_clip(&red->clip); switch (red->type) { + case QXL_DRAW_ALPHA_BLEND: + red_put_alpha_blend(&red->u.alpha_blend); + break; + case QXL_DRAW_BLACKNESS: + red_put_blackness(&red->u.blackness); + break; + case QXL_DRAW_BLEND: + red_put_blend(&red->u.blend); + break; + case QXL_DRAW_COPY: + red_put_copy(&red->u.copy); + break; + case QXL_DRAW_FILL: + red_put_fill(&red->u.fill); + break; + case QXL_DRAW_OPAQUE: + red_put_opaque(&red->u.opaque); + break; + case QXL_DRAW_INVERS: + red_put_invers(&red->u.invers); + break; + case QXL_DRAW_ROP3: + red_put_rop3(&red->u.rop3); + break; case QXL_DRAW_STROKE: - red_put_stroke_ptr(&red->u.stroke); + red_put_stroke(&red->u.stroke); break; case QXL_DRAW_TEXT: red_put_text_ptr(&red->u.text); break; + case QXL_DRAW_TRANSPARENT: + red_put_transparent(&red->u.transparent); + break; + case QXL_DRAW_WHITENESS: + red_put_whiteness(&red->u.whiteness); + break; } } diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h index 079cf06..7c4fa0c 100644 --- a/server/red_parse_qxl.h +++ b/server/red_parse_qxl.h @@ -118,6 +118,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id, void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id, RedDrawable *red, SPICE_ADDRESS addr); void red_put_drawable(RedDrawable *red); +void red_put_image(SpiceImage *red); void red_get_update_cmd(RedMemSlotInfo *slots, int group_id, RedUpdateCmd *red, SPICE_ADDRESS addr); diff --git a/server/red_worker.c b/server/red_worker.c index 255a46e..abe4e7b 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -326,7 +326,6 @@ typedef struct LocalCursor { SpiceCursor red_cursor; } LocalCursor; -#define MAX_BITMAPS 4 #define MAX_PIPE_SIZE 50 #define RECIVE_BUF_SIZE 1024 @@ -465,20 +464,6 @@ static const int BITMAP_FMT_IS_PLT[] = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0}; static const int BITMAP_FMT_IS_RGB[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1}; static const int BITMAP_FMP_BYTES_PER_PIXEL[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 4}; -typedef struct __attribute__ ((__packed__)) RedImage { - SpiceImageDescriptor descriptor; - union { // variable length - SpiceBitmap bitmap; - SpiceQUICData quic; - SpiceLZRGBData lz_rgb; - SpiceLZPLTData lz_plt; - SpiceSurface surface; - SpiceJPEGData jpeg; - SpiceZlibGlzRGBData zlib_glz; - SpiceJPEGAlphaData jpeg_alpha; - }; -} RedImage; - pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; Ring pixmap_cache_list = {&pixmap_cache_list, &pixmap_cache_list}; @@ -552,25 +537,12 @@ typedef struct { jmp_buf jmp_env; union { struct { - SPICE_ADDRESS next; - uint32_t stride; - uint32_t group_id; - - void *enc_get_virt_opaque; - enc_get_virt_fn_t enc_get_virt; - void *enc_validate_virt_opaque; - enc_validate_virt_fn_t enc_validate_virt; + SpiceChunks *chunks; + int next; + int stride; + int reverse; } lines_data; struct { - uint8_t* next; - int src_stride; - uint32_t dest_stride; - int lines; - int max_lines_bunch; - int input_bufs_pos; - RedCompressBuf *input_bufs[2]; - } unstable_lines_data; - struct { RedCompressBuf* next; int size_left; } compressed_data; // for encoding data that was already compressed by another method @@ -625,7 +597,7 @@ struct RedGlzDrawable { Drawable *drawable; uint32_t group_id; int32_t surface_id; - uint8_t *self_bitmap; + SpiceImage *self_bitmap; GlzDrawableInstanceItem instances_pool[MAX_GLZ_DRAWABLE_INSTANCES]; Ring instances; uint8_t instances_count; @@ -719,11 +691,6 @@ typedef struct CursorChannel { #endif } CursorChannel; -typedef struct __attribute__ ((__packed__)) LocalImage { - QXLImage qxl_image; - uint8_t buf[sizeof(QXLDataChunk *)]; // quic data area -} LocalImage; - typedef struct ImageCacheItem { RingItem lru_link; uint64_t id; @@ -819,7 +786,7 @@ struct Drawable { #endif BitmapGradualType copy_bitmap_graduality; uint32_t group_id; - uint8_t *self_bitmap; + SpiceImage *self_bitmap; DependItem depend_items[3]; uint8_t *backed_surface_data; @@ -947,9 +914,6 @@ typedef struct RedWorker { uint32_t preload_group_id; - uint32_t local_images_pos; - LocalImage local_images[MAX_BITMAPS]; - ImageCache image_cache; spice_image_compression_t image_compression; @@ -992,8 +956,6 @@ typedef struct RedWorker { uint64_t *wakeup_counter; uint64_t *command_counter; #endif - SpiceVirtMapping preload_group_virt_mapping; - } RedWorker; typedef enum { @@ -1145,22 +1107,6 @@ static inline void validate_surface(RedWorker *worker, uint32_t surface_id) PANIC_ON(!worker->surfaces[surface_id].context.canvas); } -static void *op_get_virt_preload_group(SpiceVirtMapping *mapping, unsigned long addr, uint32_t add_size) -{ - RedWorker *worker = SPICE_CONTAINEROF(mapping, RedWorker, preload_group_virt_mapping); - return (void *)get_virt(&worker->mem_slots, addr, add_size, - worker->preload_group_id); -} - -static void op_validate_virt_preload_group(SpiceVirtMapping *mapping, unsigned long virt, - unsigned long from_addr, uint32_t add_size) -{ - RedWorker *worker = SPICE_CONTAINEROF(mapping, RedWorker, preload_group_virt_mapping); - int slot_id = get_memslot_id(&worker->mem_slots, from_addr); - validate_virt(&worker->mem_slots, virt, slot_id, add_size, - worker->preload_group_id); -} - char *draw_type_to_str(uint8_t type) { switch (type) { @@ -1603,13 +1549,13 @@ static inline void set_surface_release_info(RedWorker *worker, uint32_t surface_ } static inline void free_red_drawable(RedWorker *worker, RedDrawable *drawable, uint32_t group_id, - uint8_t *self_bitmap, int surface_id) + SpiceImage *self_bitmap, int surface_id) { QXLReleaseInfoExt release_info_ext; red_destroy_surface(worker, surface_id); if (self_bitmap) { - free(self_bitmap); + red_put_image(self_bitmap); } release_info_ext.group_id = group_id; release_info_ext.info = drawable->release_info; @@ -2768,9 +2714,8 @@ static void red_create_stream(RedWorker *worker, Drawable *drawable) #endif stream->refs = 1; stream->bit_rate = get_bit_rate(stream_width, stream_height); - QXLImage *qxl_image = (QXLImage *)get_virt(&worker->mem_slots, drawable->red_drawable->u.copy.src_bitmap, - sizeof(QXLImage), drawable->group_id); - stream->top_down = !!(qxl_image->bitmap.flags & SPICE_BITMAP_FLAGS_TOP_DOWN); + SpiceBitmap *bitmap = &drawable->red_drawable->u.copy.src_bitmap->u.bitmap; + stream->top_down = !!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN); drawable->stream = stream; if (worker->display_channel) { @@ -2855,9 +2800,8 @@ static inline int __red_is_next_stream_frame(RedWorker *worker, } if (stream) { - QXLImage *qxl_image = (QXLImage *)get_virt(&worker->mem_slots, red_drawable->u.copy.src_bitmap, - sizeof(QXLImage), candidate->group_id); - if (stream->top_down != !!(qxl_image->bitmap.flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { + SpiceBitmap *bitmap = &red_drawable->u.copy.src_bitmap->u.bitmap; + if (stream->top_down != !!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { return FALSE; } } @@ -2882,7 +2826,7 @@ static inline int red_is_next_stream_frame(RedWorker *worker, const Drawable *ca static inline int red_is_next_stream_frame(RedWorker *worker, Drawable *candidate, Drawable *prev) { - QXLImage *qxl_image; + SpiceImage *image; RedDrawable *red_drawable; RedDrawable *prev_red_drawable; @@ -2891,33 +2835,32 @@ static inline int red_is_next_stream_frame(RedWorker *worker, Drawable *candidat return FALSE; } - qxl_drawable = candidate->red_drawable; - prev_qxl_drawable = prev->red_drawable; - if (qxl_drawable->type != QXL_DRAW_COPY || prev_qxl_drawable->type != QXL_DRAW_COPY) { + red_drawable = candidate->red_drawable; + prev_red_drawable = prev->red_drawable; + if (red_drawable->type != QXL_DRAW_COPY || prev_red_drawable->type != QXL_DRAW_COPY) { return FALSE; } - if (!rect_is_equal(&qxl_drawable->bbox, &prev_qxl_drawable->bbox)) { + if (!rect_is_equal(&red_drawable->bbox, &prev_red_drawable->bbox)) { return FALSE; } - if (!rect_is_same_size(&qxl_drawable->u.copy.src_area, &prev_qxl_drawable->u.copy.src_area)) { + if (!rect_is_same_size(&red_drawable->u.copy.src_area, &prev_red_drawable->u.copy.src_area)) { return FALSE; } - if (qxl_drawable->u.copy.rop_decriptor != SPICE_ROPD_OP_PUT || - prev_qxl_drawable->u.copy.rop_decriptor != SPICE_ROPD_OP_PUT) { + if (red_drawable->u.copy.rop_descriptor != SPICE_ROPD_OP_PUT || + prev_red_drawable->u.copy.rop_descriptor != SPICE_ROPD_OP_PUT) { return FALSE; } - qxl_image = (QXLImage *)get_virt(&worker->mem_slots, qxl_drawable->u.copy.src_bitmap, sizeof(QXLImage), - candidate->group_id); + image = red_drawable->u.copy.src_bitmap; - if (qxl_image->descriptor.type != SPICE_IMAGE_TYPE_BITMAP) { + if (image->descriptor.type != SPICE_IMAGE_TYPE_BITMAP) { return FALSE; } - if (prev->stream && prev->stream->top_down != !!(qxl_image->bitmap.flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { + if (prev->stream && prev->stream->top_down != !!(image->u.bitmap.flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { return FALSE; } @@ -2976,7 +2919,7 @@ static inline void pre_stream_item_swap(RedWorker *worker, Stream *stream) static inline void red_update_copy_graduality(RedWorker* worker, Drawable *drawable) { - QXLImage *qxl_image; + SpiceBitmap *bitmap; ASSERT(drawable->red_drawable->type == QXL_DRAW_COPY); if (worker->streaming_video != STREAM_VIDEO_FILTER) { @@ -2988,14 +2931,13 @@ static inline void red_update_copy_graduality(RedWorker* worker, Drawable *drawa return; // already set } - qxl_image = (QXLImage *)get_virt(&worker->mem_slots, drawable->red_drawable->u.copy.src_bitmap, - sizeof(QXLImage), drawable->group_id); + bitmap = &drawable->red_drawable->u.copy.src_bitmap->u.bitmap; - if (!BITMAP_FMT_IS_RGB[qxl_image->bitmap.format] || _stride_is_extra(&qxl_image->bitmap) || - (qxl_image->bitmap.flags & QXL_BITMAP_UNSTABLE)) { + if (!BITMAP_FMT_IS_RGB[bitmap->format] || _stride_is_extra(bitmap) || + (bitmap->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE)) { drawable->copy_bitmap_graduality = BITMAP_GRADUAL_NOT_AVAIL; } else { - drawable->copy_bitmap_graduality = _get_bitmap_graduality_level(worker, &qxl_image->bitmap, drawable->group_id); + drawable->copy_bitmap_graduality = _get_bitmap_graduality_level(worker, bitmap, drawable->group_id); } } @@ -3048,7 +2990,7 @@ static inline void red_stream_maintenance(RedWorker *worker, Drawable *candidate } #else if ((worker->streaming_video == STREAM_VIDEO_OFF) || - !red_is_next_stream_frame(worker, candidate, prev) { + !red_is_next_stream_frame(worker, candidate, prev)) { return; } #endif @@ -3507,7 +3449,7 @@ static inline int has_shadow(RedDrawable *drawable) static inline void red_update_streamable(RedWorker *worker, Drawable *drawable, RedDrawable *red_drawable) { - QXLImage *qxl_image; + SpiceImage *image; if (worker->streaming_video == STREAM_VIDEO_OFF) { return; @@ -3519,9 +3461,8 @@ static inline void red_update_streamable(RedWorker *worker, Drawable *drawable, return; } - qxl_image = (QXLImage *)get_virt(&worker->mem_slots, red_drawable->u.copy.src_bitmap, sizeof(QXLImage), - drawable->group_id); - if (qxl_image->descriptor.type != SPICE_IMAGE_TYPE_BITMAP) { + image = red_drawable->u.copy.src_bitmap; + if (image->descriptor.type != SPICE_IMAGE_TYPE_BITMAP) { return; } @@ -3648,7 +3589,7 @@ static int rgb32_data_has_alpha(int width, int height, size_t stride, static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable) { - QXLImage *image; + SpiceImage *image; int32_t width; int32_t height; uint8_t *dest; @@ -3670,21 +3611,21 @@ static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable) height = drawable->red_drawable->bbox.bottom - drawable->red_drawable->bbox.top; dest_stride = SPICE_ALIGN(width * bpp, 4); - image = spice_malloc_n_m(height, dest_stride, sizeof(QXLImage)); - dest = (uint8_t *)(image + 1); - + image = spice_new0(SpiceImage, 1); image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP; image->descriptor.flags = 0; QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_RED, ++worker->bits_unique); - image->bitmap.flags = QXL_BITMAP_DIRECT | (surface->context.top_down ? - QXL_BITMAP_TOP_DOWN : 0); - image->bitmap.format = surface_format_to_image_type(surface->context.format); - image->bitmap.stride = dest_stride; - image->descriptor.width = image->bitmap.x = width; - image->descriptor.height = image->bitmap.y = height; - image->bitmap.data = (QXLPHYSICAL)dest; - image->bitmap.palette = 0; + image->u.bitmap.flags = surface->context.top_down ? SPICE_BITMAP_FLAGS_TOP_DOWN : 0; + image->u.bitmap.format = surface_format_to_image_type(surface->context.format); + image->u.bitmap.stride = dest_stride; + image->descriptor.width = image->u.bitmap.x = width; + image->descriptor.height = image->u.bitmap.y = height; + image->u.bitmap.palette = NULL; + + dest = (uint8_t *)spice_malloc_n(height, dest_stride); + image->u.bitmap.data = spice_chunks_new_linear(dest, height * dest_stride); + image->u.bitmap.data->flags |= SPICE_CHUNKS_FLAGS_FREE; red_get_area(worker, drawable->surface_id, &drawable->red_drawable->self_bitmap_area, dest, dest_stride, TRUE); @@ -3692,16 +3633,16 @@ static inline int red_handle_self_bitmap(RedWorker *worker, Drawable *drawable) /* For 32bit non-primary surfaces we need to keep any non-zero high bytes as the surface may be used as source to an alpha_blend */ if (!is_primary_surface(worker, drawable->surface_id) && - image->bitmap.format == SPICE_BITMAP_FMT_32BIT && + image->u.bitmap.format == SPICE_BITMAP_FMT_32BIT && rgb32_data_has_alpha(width, height, dest_stride, dest, &all_set)) { if (all_set) { image->descriptor.flags |= SPICE_IMAGE_FLAGS_HIGH_BITS_SET; } else { - image->bitmap.format = SPICE_BITMAP_FMT_RGBA; + image->u.bitmap.format = SPICE_BITMAP_FMT_RGBA; } } - drawable->self_bitmap = (uint8_t *)image; + drawable->self_bitmap = image; return TRUE; } @@ -3947,12 +3888,6 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface free(surface); } -static LocalImage *alloc_local_image(RedWorker *worker) -{ - ASSERT(worker->local_images_pos < MAX_BITMAPS); - return &worker->local_images[worker->local_images_pos++]; -} - static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces, uint32_t surface_id) { @@ -4107,156 +4042,52 @@ static void image_cache_eaging(ImageCache *cache) #endif } -static void localize_bitmap(RedWorker *worker, QXLPHYSICAL *in_bitmap, uint32_t group_id) +static void localize_bitmap(RedWorker *worker, SpiceImage **image_ptr, SpiceImage *image_store) { - QXLImage *image; - QXLImage *local_image; - - ASSERT(in_bitmap && *in_bitmap); - image = (QXLImage *)get_virt(&worker->mem_slots, *in_bitmap, sizeof(QXLImage), group_id); - local_image = (QXLImage *)alloc_local_image(worker); - *local_image = *image; - *in_bitmap = (QXLPHYSICAL)local_image; - local_image->descriptor.flags = 0; + SpiceImage *image = *image_ptr; - if (image_cache_hit(&worker->image_cache, local_image->descriptor.id)) { - local_image->descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE; + if (image_cache_hit(&worker->image_cache, image->descriptor.id)) { + image_store->descriptor = image->descriptor; + image_store->descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE; + image_store->descriptor.flags = 0; + *image_ptr = image_store; return; } - if (image->descriptor.flags & QXL_IMAGE_HIGH_BITS_SET) { - local_image->descriptor.flags |= SPICE_IMAGE_FLAGS_HIGH_BITS_SET; - } - - switch (local_image->descriptor.type) { + switch (image->descriptor.type) { case SPICE_IMAGE_TYPE_QUIC: { - QXLDataChunk **chanks_head; + image_store->descriptor = image->descriptor; + image_store->u.quic = image->u.quic; + *image_ptr = image_store; #ifdef IMAGE_CACHE_AGE - local_image->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_ME; + image_store->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_ME; #else - if (local_image->descriptor.width * local_image->descriptor.height >= 640 * 480) { - local_image->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_ME; + if (image_store->descriptor.width * image->descriptor.height >= 640 * 480) { + image_store->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_ME; } #endif - chanks_head = (QXLDataChunk **)local_image->quic.data; - *chanks_head = (QXLDataChunk *)image->quic.data; break; } case SPICE_IMAGE_TYPE_BITMAP: - if (image->bitmap.flags & QXL_BITMAP_DIRECT) { - local_image->bitmap.data = (QXLPHYSICAL)get_virt(&worker->mem_slots, image->bitmap.data, - image->bitmap.stride * image->bitmap.y, - group_id); - } else { - QXLPHYSICAL src_data; - int size = image->bitmap.y * image->bitmap.stride; - uint8_t *data = spice_malloc_n(image->bitmap.y, image->bitmap.stride); - local_image->bitmap.data = (QXLPHYSICAL)data; - src_data = image->bitmap.data; - - while (size) { - QXLDataChunk *chunk; - uint32_t data_size; - int cp_size; - - ASSERT(src_data); - chunk = (QXLDataChunk *)get_virt(&worker->mem_slots, src_data, sizeof(QXLDataChunk), group_id); - data_size = chunk->data_size; - validate_virt(&worker->mem_slots, (unsigned long)chunk->data, get_memslot_id(&worker->mem_slots, src_data), - data_size, group_id); - cp_size = MIN(data_size, size); - memcpy(data, chunk->data, cp_size); - data += cp_size; - size -= cp_size; - src_data = chunk->next_chunk; - } - } - - if (local_image->bitmap.palette) { - uint16_t num_ents; - uint32_t *ents; - SpicePalette *tmp_palette; - SpicePalette *shadow_palette; - - int slot_id = get_memslot_id(&worker->mem_slots, local_image->bitmap.palette); - tmp_palette = (SpicePalette *)get_virt(&worker->mem_slots, local_image->bitmap.palette, - sizeof(SpicePalette), group_id); - - num_ents = tmp_palette->num_ents; - ents = tmp_palette->ents; - - validate_virt(&worker->mem_slots, (unsigned long)ents, slot_id, (num_ents * sizeof(uint32_t)), - group_id); - - shadow_palette = (SpicePalette *)spice_malloc_n_m(num_ents, sizeof(uint32_t),sizeof(SpicePalette) + sizeof(QXLPHYSICAL)); - - memcpy(shadow_palette->ents, ents, num_ents * sizeof(uint32_t)); - shadow_palette->num_ents = num_ents; - shadow_palette->unique = tmp_palette->unique; - - local_image->bitmap.palette = (SPICE_ADDRESS)shadow_palette; - } - break; - case SPICE_IMAGE_TYPE_SURFACE: { - break; - } - default: - red_error("invalid image type"); - } -} - -static void unlocalize_bitmap(QXLPHYSICAL *bitmap) -{ - QXLImage *image; - - ASSERT(bitmap && *bitmap); - image = (QXLImage *)*bitmap; - *bitmap = 0; - - switch (image->descriptor.type) { - case SPICE_IMAGE_TYPE_BITMAP: - if (!(image->bitmap.flags & QXL_BITMAP_DIRECT)) { - free((void *)image->bitmap.data); - } - if (image->bitmap.palette) { - free((void *)image->bitmap.palette); - } - break; - case SPICE_IMAGE_TYPE_QUIC: - case SPICE_IMAGE_TYPE_FROM_CACHE: - *bitmap = 0; case SPICE_IMAGE_TYPE_SURFACE: + /* nothing */ break; default: - red_error("invalid image type %u", image->descriptor.type); - } -} - -static void localize_brush(RedWorker *worker, SpiceBrush *brush, uint32_t group_id) -{ - if (brush->type == SPICE_BRUSH_TYPE_PATTERN) { - localize_bitmap(worker, &brush->u.pattern.pat, group_id); + red_error("invalid image type"); } } -static void unlocalize_brush(SpiceBrush *brush) +static void localize_brush(RedWorker *worker, SpiceBrush *brush, SpiceImage *image_store) { if (brush->type == SPICE_BRUSH_TYPE_PATTERN) { - unlocalize_bitmap(&brush->u.pattern.pat); + localize_bitmap(worker, &brush->u.pattern.pat, image_store); } } -static void localize_mask(RedWorker *worker, SpiceQMask *mask, uint32_t group_id) +static void localize_mask(RedWorker *worker, SpiceQMask *mask, SpiceImage *image_store) { if (mask->bitmap) { - localize_bitmap(worker, &mask->bitmap, group_id); - } -} - -static void unlocalize_mask(SpiceQMask *mask) -{ - if (mask->bitmap) { - unlocalize_bitmap(&mask->bitmap); + localize_bitmap(worker, &mask->bitmap, image_store); } } @@ -4292,7 +4123,6 @@ static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable) surface = &worker->surfaces[drawable->surface_id]; canvas = surface->context.canvas; - worker->local_images_pos = 0; image_cache_eaging(&worker->image_cache); worker->preload_group_id = drawable->group_id; @@ -4302,48 +4132,45 @@ static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable) switch (drawable->red_drawable->type) { case QXL_DRAW_FILL: { SpiceFill fill = drawable->red_drawable->u.fill; - localize_brush(worker, &fill.brush, drawable->group_id); - localize_mask(worker, &fill.mask, drawable->group_id); + SpiceImage img1, img2; + localize_brush(worker, &fill.brush, &img1); + localize_mask(worker, &fill.mask, &img2); canvas->ops->draw_fill(canvas, &drawable->red_drawable->bbox, - &clip, &fill); unlocalize_mask(&fill.mask); - unlocalize_brush(&fill.brush); + &clip, &fill); break; } case QXL_DRAW_OPAQUE: { SpiceOpaque opaque = drawable->red_drawable->u.opaque; - localize_brush(worker, &opaque.brush, drawable->group_id); - localize_bitmap(worker, &opaque.src_bitmap, drawable->group_id); - localize_mask(worker, &opaque.mask, drawable->group_id); + SpiceImage img1, img2, img3; + localize_brush(worker, &opaque.brush, &img1); + localize_bitmap(worker, &opaque.src_bitmap, &img2); + localize_mask(worker, &opaque.mask, &img3); canvas->ops->draw_opaque(canvas, &drawable->red_drawable->bbox, &clip, &opaque); - unlocalize_mask(&opaque.mask); - unlocalize_bitmap(&opaque.src_bitmap); - unlocalize_brush(&opaque.brush); break; } case QXL_DRAW_COPY: { SpiceCopy copy = drawable->red_drawable->u.copy; - localize_bitmap(worker, ©.src_bitmap, drawable->group_id); - localize_mask(worker, ©.mask, drawable->group_id); + SpiceImage img1, img2; + localize_bitmap(worker, ©.src_bitmap, &img1); + localize_mask(worker, ©.mask, &img2); canvas->ops->draw_copy(canvas, &drawable->red_drawable->bbox, &clip, ©); - unlocalize_mask(©.mask); - unlocalize_bitmap(©.src_bitmap); break; } case QXL_DRAW_TRANSPARENT: { SpiceTransparent transparent = drawable->red_drawable->u.transparent; - localize_bitmap(worker, &transparent.src_bitmap, drawable->group_id); + SpiceImage img1; + localize_bitmap(worker, &transparent.src_bitmap, &img1); canvas->ops->draw_transparent(canvas, &drawable->red_drawable->bbox, &clip, &transparent); - unlocalize_bitmap(&transparent.src_bitmap); break; } case QXL_DRAW_ALPHA_BLEND: { SpiceAlphaBlnd alpha_blend = drawable->red_drawable->u.alpha_blend; - localize_bitmap(worker, &alpha_blend.src_bitmap, drawable->group_id); + SpiceImage img1; + localize_bitmap(worker, &alpha_blend.src_bitmap, &img1); canvas->ops->draw_alpha_blend(canvas, &drawable->red_drawable->bbox, &clip, &alpha_blend); - unlocalize_bitmap(&alpha_blend.src_bitmap); break; } case QXL_COPY_BITS: { @@ -4353,67 +4180,64 @@ static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable) } case QXL_DRAW_BLEND: { SpiceBlend blend = drawable->red_drawable->u.blend; - localize_bitmap(worker, &blend.src_bitmap, drawable->group_id); - localize_mask(worker, &blend.mask, drawable->group_id); + SpiceImage img1, img2; + localize_bitmap(worker, &blend.src_bitmap, &img1); + localize_mask(worker, &blend.mask, &img2); canvas->ops->draw_blend(canvas, &drawable->red_drawable->bbox, &clip, &blend); - unlocalize_mask(&blend.mask); - unlocalize_bitmap(&blend.src_bitmap); break; } case QXL_DRAW_BLACKNESS: { SpiceBlackness blackness = drawable->red_drawable->u.blackness; - localize_mask(worker, &blackness.mask, drawable->group_id); + SpiceImage img1; + localize_mask(worker, &blackness.mask, &img1); canvas->ops->draw_blackness(canvas, &drawable->red_drawable->bbox, &clip, &blackness); - unlocalize_mask(&blackness.mask); break; } case QXL_DRAW_WHITENESS: { SpiceWhiteness whiteness = drawable->red_drawable->u.whiteness; - localize_mask(worker, &whiteness.mask, drawable->group_id); + SpiceImage img1; + localize_mask(worker, &whiteness.mask, &img1); canvas->ops->draw_whiteness(canvas, &drawable->red_drawable->bbox, &clip, &whiteness); - unlocalize_mask(&whiteness.mask); break; } case QXL_DRAW_INVERS: { SpiceInvers invers = drawable->red_drawable->u.invers; - localize_mask(worker, &invers.mask, drawable->group_id); + SpiceImage img1; + localize_mask(worker, &invers.mask, &img1); canvas->ops->draw_invers(canvas, &drawable->red_drawable->bbox, &clip, &invers); - unlocalize_mask(&invers.mask); break; } case QXL_DRAW_ROP3: { SpiceRop3 rop3 = drawable->red_drawable->u.rop3; - localize_brush(worker, &rop3.brush, drawable->group_id); - localize_bitmap(worker, &rop3.src_bitmap, drawable->group_id); - localize_mask(worker, &rop3.mask, drawable->group_id); + SpiceImage img1, img2, img3; + localize_brush(worker, &rop3.brush, &img1); + localize_bitmap(worker, &rop3.src_bitmap, &img2); + localize_mask(worker, &rop3.mask, &img3); canvas->ops->draw_rop3(canvas, &drawable->red_drawable->bbox, - &clip, &rop3); unlocalize_mask(&rop3.mask); - unlocalize_bitmap(&rop3.src_bitmap); - unlocalize_brush(&rop3.brush); + &clip, &rop3); break; } case QXL_DRAW_STROKE: { SpiceStroke stroke = drawable->red_drawable->u.stroke; - localize_brush(worker, &stroke.brush, drawable->group_id); + SpiceImage img1; + localize_brush(worker, &stroke.brush, &img1); localize_attr(worker, &stroke.attr, drawable->group_id); canvas->ops->draw_stroke(canvas, &drawable->red_drawable->bbox, &clip, &stroke); unlocalize_attr(&stroke.attr); - unlocalize_brush(&stroke.brush); break; } case QXL_DRAW_TEXT: { SpiceText text = drawable->red_drawable->u.text; - localize_brush(worker, &text.fore_brush, drawable->group_id); - localize_brush(worker, &text.back_brush, drawable->group_id); + SpiceImage img1, img2; + localize_brush(worker, &text.fore_brush, &img1); + localize_brush(worker, &text.back_brush, &img2); canvas->ops->draw_text(canvas, &drawable->red_drawable->bbox, &clip, &text); - unlocalize_brush(&text.back_brush); - unlocalize_brush(&text.fore_brush); break; } default: @@ -5077,6 +4901,7 @@ static void marshaller_add_compressed(RedWorker *worker, SpiceMarshaller *m, } while (max); } + static void marshaller_add_chunk(RedWorker *worker, SpiceMarshaller *m, QXLDataChunk *chunk, size_t size, int memslot_id, uint32_t group_id) { @@ -5139,31 +4964,22 @@ static void fill_base(DisplayChannel *display_channel, Drawable *drawable) spice_marshall_DisplayBase(channel->send_data.marshaller, &base); } -/* io_palette is relative address of the palette*/ -static inline void fill_palette(DisplayChannel *display_channel, SPICE_ADDRESS *io_palette, uint8_t *flags, - uint32_t group_id, SpicePalette **palette_out) +static inline void fill_palette(DisplayChannel *display_channel, + SpicePalette *palette, + uint8_t *flags) { - RedChannel *channel = &display_channel->base; - RedWorker *worker = channel->worker; - SpicePalette *palette; - - *palette_out = NULL; - if (!(*io_palette)) { + if (palette == NULL) { return; } - - palette = (SpicePalette *)get_virt(&worker->mem_slots, *io_palette, sizeof(SpicePalette), group_id); if (palette->unique) { if (red_palette_cache_find(display_channel, palette->unique)) { *flags |= SPICE_BITMAP_FLAGS_PAL_FROM_CACHE; - *io_palette = palette->unique; return; } if (red_palette_cache_add(display_channel, palette->unique, 1)) { *flags |= SPICE_BITMAP_FLAGS_PAL_CACHE_ME; } } - *palette_out = palette; } static inline RedCompressBuf *red_display_alloc_compress_buf(DisplayChannel *display_channel) @@ -5562,31 +5378,32 @@ static int zlib_usr_more_space(ZlibEncoderUsrContext *usr, uint8_t **io_ptr) static inline int encoder_usr_more_lines(EncoderData *enc_data, uint8_t **lines) { - uint32_t data_size; - uint8_t *data; + struct SpiceChunk *chunk; - if (!enc_data->u.lines_data.next) { - return 0; + if (enc_data->u.lines_data.reverse) { + if (!(enc_data->u.lines_data.next >= 0)) { + return 0; + } + } else { + if (!(enc_data->u.lines_data.next < enc_data->u.lines_data.chunks->num_chunks)) { + return 0; + } } - QXLDataChunk *chunk = (QXLDataChunk *)enc_data->u.lines_data.enc_get_virt( - enc_data->u.lines_data.enc_get_virt_opaque, enc_data->u.lines_data.next, - sizeof(QXLDataChunk), enc_data->u.lines_data.group_id); - - data_size = chunk->data_size; - data = chunk->data; - - if (data_size % enc_data->u.lines_data.stride) { + chunk = &enc_data->u.lines_data.chunks->chunk[enc_data->u.lines_data.next]; + if (chunk->len % enc_data->u.lines_data.stride) { return 0; } - enc_data->u.lines_data.enc_validate_virt(enc_data->u.lines_data.enc_validate_virt_opaque, - (unsigned long)data, enc_data->u.lines_data.next, - data_size, enc_data->u.lines_data.group_id); + if (enc_data->u.lines_data.reverse) { + enc_data->u.lines_data.next--; + *lines = chunk->data + chunk->len - enc_data->u.lines_data.stride; + } else { + enc_data->u.lines_data.next++; + *lines = chunk->data; + } - enc_data->u.lines_data.next = chunk->next_chunk; - *lines = data; - return data_size / enc_data->u.lines_data.stride; + return chunk->len / enc_data->u.lines_data.stride; } static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines) @@ -5613,105 +5430,6 @@ static int jpeg_usr_more_lines(JpegEncoderUsrContext *usr, uint8_t **lines) return encoder_usr_more_lines(usr_data, lines); } -static int encoder_usr_more_lines_reverse(EncoderData *enc_data, uint8_t **lines) -{ - uint8_t *data; - uint32_t data_size; - - if (!enc_data->u.lines_data.next) { - return 0; - } - - QXLDataChunk *chunk = (QXLDataChunk *)enc_data->u.lines_data.enc_get_virt( - enc_data->u.lines_data.enc_get_virt_opaque, - enc_data->u.lines_data.next, - sizeof(QXLDataChunk), enc_data->u.lines_data.group_id); - - data_size = chunk->data_size; - data = chunk->data; - - if (data_size % enc_data->u.lines_data.stride) { - return 0; - } - - enc_data->u.lines_data.enc_validate_virt(enc_data->u.lines_data.enc_validate_virt_opaque, - (unsigned long)data, - enc_data->u.lines_data.next, data_size, - enc_data->u.lines_data.group_id); - - enc_data->u.lines_data.next = chunk->prev_chunk; - *lines = data + data_size - enc_data->u.lines_data.stride; - return data_size / enc_data->u.lines_data.stride; -} - -static int quic_usr_more_lines_reverse(QuicUsrContext *usr, uint8_t **lines) -{ - EncoderData *usr_data = &(((QuicData *)usr)->data); - return encoder_usr_more_lines_reverse(usr_data, lines); - -} - -static int jpeg_usr_more_lines_reverse(JpegEncoderUsrContext *usr, uint8_t **lines) -{ - EncoderData *usr_data = &(((JpegData *)usr)->data); - return encoder_usr_more_lines_reverse(usr_data, lines); -} - -static int encoder_usr_more_lines_unstable(EncoderData *enc_data, uint8_t **out_lines) -{ - if (!enc_data->u.unstable_lines_data.lines) { - return 0; - } - uint8_t *src = enc_data->u.unstable_lines_data.next; - int lines = MIN(enc_data->u.unstable_lines_data.lines, - enc_data->u.unstable_lines_data.max_lines_bunch); - enc_data->u.unstable_lines_data.lines -= lines; - uint8_t *end = src + lines * enc_data->u.unstable_lines_data.src_stride; - enc_data->u.unstable_lines_data.next = end; - - uint8_t *out = (uint8_t *)enc_data->u.unstable_lines_data.input_bufs[ - enc_data->u.unstable_lines_data.input_bufs_pos++ & 1]->buf; - uint8_t *dest = out; - for (; src != end; src += enc_data->u.unstable_lines_data.src_stride, - dest += enc_data->u.unstable_lines_data.dest_stride) { - memcpy(dest, src, enc_data->u.unstable_lines_data.dest_stride); - } - *out_lines = out; - return lines; -} - -static int quic_usr_more_lines_unstable(QuicUsrContext *usr, uint8_t **lines) -{ - EncoderData *usr_data = &(((QuicData *)usr)->data); - return encoder_usr_more_lines_unstable(usr_data, lines); -} - -static int jpeg_usr_more_lines_unstable(JpegEncoderUsrContext *usr, uint8_t **lines) -{ - EncoderData *usr_data = &(((JpegData *)usr)->data); - return encoder_usr_more_lines_unstable(usr_data, lines); -} - -static int quic_usr_no_more_lines(QuicUsrContext *usr, uint8_t **lines) -{ - return 0; -} - -static int lz_usr_no_more_lines(LzUsrContext *usr, uint8_t **lines) -{ - return 0; -} - -static int glz_usr_no_more_lines(GlzEncoderUsrContext *usr, uint8_t **lines) -{ - return 0; -} - -static int jpeg_usr_no_more_lines(JpegEncoderUsrContext *usr, uint8_t **lines) -{ - return 0; -} - static int zlib_usr_more_input(ZlibEncoderUsrContext *usr, uint8_t** input) { EncoderData *usr_data = &(((ZlibData *)usr)->data); @@ -5869,81 +5587,34 @@ static BitmapGradualType _get_bitmap_graduality_level(RedWorker *worker, SpiceBi { double score = 0.0; int num_samples = 0; - - if ((bitmap->flags & QXL_BITMAP_DIRECT)) { - uint32_t x; - uint32_t y; - + int num_lines; + double chunk_score = 0.0; + int chunk_num_samples = 0; + uint32_t x, i; + SpiceChunk *chunk; + + chunk = bitmap->data->chunk; + for (i = 0; i < bitmap->data->num_chunks; i++) { + num_lines = chunk[i].len / bitmap->stride; x = bitmap->x; - y = bitmap->y; switch (bitmap->format) { - case SPICE_BITMAP_FMT_16BIT: { - uint8_t *lines = (uint8_t*)get_virt(&worker->mem_slots, bitmap->data, x * y * - sizeof(rgb16_pixel_t), group_id); - compute_lines_gradual_score_rgb16((rgb16_pixel_t*)lines, x, y, &score, &num_samples); + case SPICE_BITMAP_FMT_16BIT: + compute_lines_gradual_score_rgb16((rgb16_pixel_t *)chunk[i].data, x, num_lines, + &chunk_score, &chunk_num_samples); + case SPICE_BITMAP_FMT_24BIT: + compute_lines_gradual_score_rgb24((rgb24_pixel_t *)chunk[i].data, x, num_lines, + &chunk_score, &chunk_num_samples); break; - } - case SPICE_BITMAP_FMT_24BIT: { - uint8_t *lines = (uint8_t*)get_virt(&worker->mem_slots, bitmap->data, x * y * - sizeof(rgb24_pixel_t), group_id); - compute_lines_gradual_score_rgb24((rgb24_pixel_t*)lines, x, y, &score, &num_samples); - break; - } case SPICE_BITMAP_FMT_32BIT: - case SPICE_BITMAP_FMT_RGBA: { - uint8_t *lines = (uint8_t*)get_virt(&worker->mem_slots, bitmap->data, x * y * - sizeof(rgb32_pixel_t), group_id); - compute_lines_gradual_score_rgb32((rgb32_pixel_t*)lines, x, y, &score, &num_samples); + case SPICE_BITMAP_FMT_RGBA: + compute_lines_gradual_score_rgb32((rgb32_pixel_t *)chunk[i].data, x, num_lines, + &chunk_score, &chunk_num_samples); break; - } default: red_error("invalid bitmap format (not RGB) %u", bitmap->format); } - } else { - QXLDataChunk *chunk = NULL; - int num_lines; - double chunk_score = 0.0; - int chunk_num_samples = 0; - uint32_t x; - SPICE_ADDRESS relative_address = bitmap->data; - - while (relative_address) { - chunk = (QXLDataChunk *)get_virt(&worker->mem_slots, relative_address, sizeof(QXLDataChunk), - group_id); - num_lines = chunk->data_size / bitmap->stride; - x = bitmap->x; - switch (bitmap->format) { - case SPICE_BITMAP_FMT_16BIT: - validate_virt(&worker->mem_slots, (unsigned long)chunk->data, - get_memslot_id(&worker->mem_slots, relative_address), - sizeof(rgb16_pixel_t) * x * num_lines, group_id); - compute_lines_gradual_score_rgb16((rgb16_pixel_t*)chunk->data, x, num_lines, - &chunk_score, &chunk_num_samples); - break; - case SPICE_BITMAP_FMT_24BIT: - validate_virt(&worker->mem_slots, (unsigned long)chunk->data, - get_memslot_id(&worker->mem_slots, relative_address), - sizeof(rgb24_pixel_t) * x * num_lines, group_id); - compute_lines_gradual_score_rgb24((rgb24_pixel_t*)chunk->data, x, num_lines, - &chunk_score, &chunk_num_samples); - break; - case SPICE_BITMAP_FMT_32BIT: - case SPICE_BITMAP_FMT_RGBA: - validate_virt(&worker->mem_slots, (unsigned long)chunk->data, - get_memslot_id(&worker->mem_slots, relative_address), - sizeof(rgb32_pixel_t) * x * num_lines, group_id); - compute_lines_gradual_score_rgb32((rgb32_pixel_t*)chunk->data, x, num_lines, - &chunk_score, &chunk_num_samples); - break; - default: - red_error("invalid bitmap format (not RGB) %u", bitmap->format); - } - - score += chunk_score; - num_samples += chunk_num_samples; - - relative_address = chunk->next_chunk; - } + score += chunk_score; + num_samples += chunk_num_samples; } ASSERT(num_samples); @@ -6013,7 +5684,7 @@ typedef struct compress_send_data_t { static inline int red_glz_compress_image(DisplayChannel *display_channel, - RedImage *dest, SpiceBitmap *src, Drawable *drawable, + SpiceImage *dest, SpiceBitmap *src, Drawable *drawable, compress_send_data_t* o_comp_data) { RedWorker *worker = (RedWorker *)display_channel->base.worker; @@ -6027,7 +5698,6 @@ static inline int red_glz_compress_image(DisplayChannel *display_channel, RedGlzDrawable *glz_drawable; GlzDrawableInstanceItem *glz_drawable_instance; uint8_t *lines; - unsigned int num_lines; int glz_size; int zlib_size; @@ -6044,25 +5714,14 @@ static inline int red_glz_compress_image(DisplayChannel *display_channel, glz_drawable = red_display_get_glz_drawable(display_channel, drawable); glz_drawable_instance = red_display_add_glz_drawable_instance(glz_drawable); - if ((src->flags & QXL_BITMAP_DIRECT)) { - glz_data->usr.more_lines = glz_usr_no_more_lines; - lines = (uint8_t*)get_virt(&worker->mem_slots, src->data, src->stride * src->y, drawable->group_id); - num_lines = src->y; - } else { - glz_data->data.u.lines_data.enc_get_virt = cb_get_virt; - glz_data->data.u.lines_data.enc_get_virt_opaque = &worker->mem_slots; - glz_data->data.u.lines_data.enc_validate_virt = cb_validate_virt; - glz_data->data.u.lines_data.enc_validate_virt_opaque = &worker->mem_slots; - glz_data->data.u.lines_data.stride = src->stride; - glz_data->data.u.lines_data.next = src->data; - glz_data->data.u.lines_data.group_id = drawable->group_id; - glz_data->usr.more_lines = glz_usr_more_lines; - lines = NULL; - num_lines = 0; - } + glz_data->data.u.lines_data.chunks = src->data; + glz_data->data.u.lines_data.stride = src->stride; + glz_data->data.u.lines_data.next = 0; + glz_data->data.u.lines_data.reverse = 0; + glz_data->usr.more_lines = glz_usr_more_lines; glz_size = glz_encode(display_channel->glz, type, src->x, src->y, - (src->flags & QXL_BITMAP_TOP_DOWN), lines, num_lines, + (src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN), lines, 0, src->stride, (uint8_t*)glz_data->data.bufs_head->buf, sizeof(glz_data->data.bufs_head->buf), glz_drawable_instance, @@ -6107,8 +5766,8 @@ static inline int red_glz_compress_image(DisplayChannel *display_channel, } dest->descriptor.type = SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB; - dest->zlib_glz.glz_data_size = glz_size; - dest->zlib_glz.data_size = zlib_size; + dest->u.zlib_glz.glz_data_size = glz_size; + dest->u.zlib_glz.data_size = zlib_size; o_comp_data->comp_buf = zlib_data->data.bufs_head; o_comp_data->comp_buf_size = zlib_size; @@ -6117,7 +5776,7 @@ static inline int red_glz_compress_image(DisplayChannel *display_channel, return TRUE; glz: dest->descriptor.type = SPICE_IMAGE_TYPE_GLZ_RGB; - dest->lz_rgb.data_size = glz_size; + dest->u.lz_rgb.data_size = glz_size; o_comp_data->comp_buf = glz_data->data.bufs_head; o_comp_data->comp_buf_size = glz_size; @@ -6126,7 +5785,7 @@ glz: } static inline int red_lz_compress_image(DisplayChannel *display_channel, - RedImage *dest, SpiceBitmap *src, + SpiceImage *dest, SpiceBitmap *src, compress_send_data_t* o_comp_data, uint32_t group_id) { RedWorker *worker = display_channel->base.worker; @@ -6158,27 +5817,16 @@ static inline int red_lz_compress_image(DisplayChannel *display_channel, return FALSE; } - if ((src->flags & QXL_BITMAP_DIRECT)) { - lz_data->usr.more_lines = lz_usr_no_more_lines; - size = lz_encode(lz, type, src->x, src->y, (src->flags & QXL_BITMAP_TOP_DOWN), - (uint8_t*)get_virt(&worker->mem_slots, src->data, src->stride * src->y, group_id), - src->y, src->stride, (uint8_t*)lz_data->data.bufs_head->buf, - sizeof(lz_data->data.bufs_head->buf)); - } else { - lz_data->data.u.lines_data.enc_get_virt = cb_get_virt; - lz_data->data.u.lines_data.enc_get_virt_opaque = &worker->mem_slots; - lz_data->data.u.lines_data.enc_validate_virt = cb_validate_virt; - lz_data->data.u.lines_data.enc_validate_virt_opaque = &worker->mem_slots; - lz_data->data.u.lines_data.stride = src->stride; - lz_data->data.u.lines_data.next = src->data; - lz_data->data.u.lines_data.group_id = group_id; - lz_data->usr.more_lines = lz_usr_more_lines; + lz_data->data.u.lines_data.chunks = src->data; + lz_data->data.u.lines_data.stride = src->stride; + lz_data->data.u.lines_data.next = 0; + lz_data->data.u.lines_data.reverse = 0; + lz_data->usr.more_lines = lz_usr_more_lines; - size = lz_encode(lz, type, src->x, src->y, (src->flags & QXL_BITMAP_TOP_DOWN), - NULL, 0, src->stride, - (uint8_t*)lz_data->data.bufs_head->buf, - sizeof(lz_data->data.bufs_head->buf)); - } + size = lz_encode(lz, type, src->x, src->y, (src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN), + NULL, 0, src->stride, + (uint8_t*)lz_data->data.bufs_head->buf, + sizeof(lz_data->data.bufs_head->buf)); // the compressed buffer is bigger than the original data if (size > (src->y * src->stride)) { @@ -6187,21 +5835,22 @@ static inline int red_lz_compress_image(DisplayChannel *display_channel, if (BITMAP_FMT_IS_RGB[src->format]) { dest->descriptor.type = SPICE_IMAGE_TYPE_LZ_RGB; - dest->lz_rgb.data_size = size; + dest->u.lz_rgb.data_size = size; o_comp_data->comp_buf = lz_data->data.bufs_head; o_comp_data->comp_buf_size = size; } else { dest->descriptor.type = SPICE_IMAGE_TYPE_LZ_PLT; - dest->lz_plt.data_size = size; - dest->lz_plt.flags = src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN; - dest->lz_plt.palette = src->palette; + dest->u.lz_plt.data_size = size; + dest->u.lz_plt.flags = src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN; + dest->u.lz_plt.palette = src->palette; + dest->u.lz_plt.palette_id = src->palette->unique; o_comp_data->comp_buf = lz_data->data.bufs_head; o_comp_data->comp_buf_size = size; - fill_palette(display_channel, &(dest->lz_plt.palette), &(dest->lz_plt.flags), - group_id, &o_comp_data->lzplt_palette); + fill_palette(display_channel, dest->u.lz_plt.palette, &(dest->u.lz_plt.flags)); + o_comp_data->lzplt_palette = dest->u.lz_plt.palette; } stat_compress_add(&display_channel->lz_stat, start_time, src->stride * src->y, @@ -6209,7 +5858,7 @@ static inline int red_lz_compress_image(DisplayChannel *display_channel, return TRUE; } -static int red_jpeg_compress_image(DisplayChannel *display_channel, RedImage *dest, +static int red_jpeg_compress_image(DisplayChannel *display_channel, SpiceImage *dest, SpiceBitmap *src, compress_send_data_t* o_comp_data, uint32_t group_id) { @@ -6224,6 +5873,7 @@ static int red_jpeg_compress_image(DisplayChannel *display_channel, RedImage *de int alpha_lz_size = 0; int comp_head_filled; int comp_head_left; + int stride; uint8_t *lz_out_start_byte; #ifdef COMPRESS_STAT @@ -6267,83 +5917,26 @@ static int red_jpeg_compress_image(DisplayChannel *display_channel, RedImage *de return FALSE; } - if ((src->flags & QXL_BITMAP_DIRECT)) { - int stride; - uint8_t *data; + if (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE) { + spice_chunks_linearize(src->data); + } - if (!(src->flags & QXL_BITMAP_TOP_DOWN)) { - data = (uint8_t*)get_virt(&worker->mem_slots, src->data, src->stride * src->y, group_id) + - src->stride * (src->y - 1); - stride = -src->stride; - } else { - data = (uint8_t*)get_virt(&worker->mem_slots, src->data, src->stride * src->y, group_id); - stride = src->stride; - } - - if ((src->flags & QXL_BITMAP_UNSTABLE)) { - ASSERT(!has_alpha); - jpeg_data->data.u.unstable_lines_data.next = data; - jpeg_data->data.u.unstable_lines_data.src_stride = stride; - jpeg_data->data.u.unstable_lines_data.dest_stride = src->stride; - jpeg_data->data.u.unstable_lines_data.lines = src->y; - jpeg_data->data.u.unstable_lines_data.input_bufs_pos = 0; - if (!(jpeg_data->data.u.unstable_lines_data.input_bufs[0] = - red_display_alloc_compress_buf(display_channel)) || - !(jpeg_data->data.u.unstable_lines_data.input_bufs[1] = - red_display_alloc_compress_buf(display_channel))) { - return FALSE; - } - jpeg_data->data.u.unstable_lines_data.max_lines_bunch = - sizeof(jpeg_data->data.u.unstable_lines_data.input_bufs[0]->buf) / - jpeg_data->data.u.unstable_lines_data.dest_stride; - jpeg_data->usr.more_lines = jpeg_usr_more_lines_unstable; - jpeg_size = jpeg_encode(jpeg, display_channel->jpeg_quality, jpeg_in_type, - src->x, src->y, NULL, 0, src->stride, - (uint8_t*)jpeg_data->data.bufs_head->buf, - sizeof(jpeg_data->data.bufs_head->buf)); - } else { - jpeg_data->usr.more_lines = jpeg_usr_no_more_lines; - jpeg_size = jpeg_encode(jpeg, display_channel->jpeg_quality, jpeg_in_type, - src->x, src->y, data, src->y, stride, - (uint8_t*)jpeg_data->data.bufs_head->buf, - sizeof(jpeg_data->data.bufs_head->buf)); - } + jpeg_data->data.u.lines_data.chunks = src->data; + jpeg_data->data.u.lines_data.stride = src->stride; + jpeg_data->usr.more_lines = jpeg_usr_more_lines; + if ((src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { + jpeg_data->data.u.lines_data.next = 0; + jpeg_data->data.u.lines_data.reverse = 0; + stride = src->stride; } else { - int stride; - - if ((src->flags & QXL_BITMAP_UNSTABLE)) { - red_printf_once("unexpected unstable bitmap"); - return FALSE; - } - jpeg_data->data.u.lines_data.enc_get_virt = cb_get_virt; - jpeg_data->data.u.lines_data.enc_get_virt_opaque = &worker->mem_slots; - jpeg_data->data.u.lines_data.enc_validate_virt = cb_validate_virt; - jpeg_data->data.u.lines_data.enc_validate_virt_opaque = &worker->mem_slots; - jpeg_data->data.u.lines_data.stride = src->stride; - jpeg_data->data.u.lines_data.group_id = group_id; - - if ((src->flags & QXL_BITMAP_TOP_DOWN)) { - jpeg_data->data.u.lines_data.next = src->data; - jpeg_data->usr.more_lines = jpeg_usr_more_lines; - stride = src->stride; - } else { - SPICE_ADDRESS prev_addr = src->data; - QXLDataChunk *chunk = (QXLDataChunk *)get_virt(&worker->mem_slots, src->data, - sizeof(QXLDataChunk), group_id); - while (chunk->next_chunk) { - prev_addr = chunk->next_chunk; - chunk = (QXLDataChunk *)get_virt(&worker->mem_slots, chunk->next_chunk, sizeof(QXLDataChunk), - group_id); - ASSERT(chunk->prev_chunk); - } - jpeg_data->data.u.lines_data.next = (SPICE_ADDRESS)prev_addr; - jpeg_data->usr.more_lines = jpeg_usr_more_lines_reverse; - stride = -src->stride; - } - jpeg_size = jpeg_encode(jpeg, display_channel->jpeg_quality, jpeg_in_type, src->x, src->y, NULL, - 0, stride, (uint8_t*)jpeg_data->data.bufs_head->buf, - sizeof(jpeg_data->data.bufs_head->buf)); + jpeg_data->data.u.lines_data.next = src->data->num_chunks - 1; + jpeg_data->data.u.lines_data.reverse = 1; + stride = -src->stride; } + jpeg_size = jpeg_encode(jpeg, display_channel->jpeg_quality, jpeg_in_type, + src->x, src->y, NULL, + 0, stride, (uint8_t*)jpeg_data->data.bufs_head->buf, + sizeof(jpeg_data->data.bufs_head->buf)); // the compressed buffer is bigger than the original data if (jpeg_size > (src->y * src->stride)) { @@ -6352,7 +5945,7 @@ static int red_jpeg_compress_image(DisplayChannel *display_channel, RedImage *de if (!has_alpha) { dest->descriptor.type = SPICE_IMAGE_TYPE_JPEG; - dest->jpeg.data_size = jpeg_size; + dest->u.jpeg.data_size = jpeg_size; o_comp_data->comp_buf = jpeg_data->data.bufs_head; o_comp_data->comp_buf_size = jpeg_size; @@ -6372,32 +5965,17 @@ static int red_jpeg_compress_image(DisplayChannel *display_channel, RedImage *de lz_data->data.display_channel = display_channel; - if ((src->flags & QXL_BITMAP_DIRECT)) { - lz_data->usr.more_lines = lz_usr_no_more_lines; - alpha_lz_size = lz_encode(lz, LZ_IMAGE_TYPE_XXXA, src->x, src->y, - (src->flags & QXL_BITMAP_TOP_DOWN), - (uint8_t*)get_virt(&worker->mem_slots, src->data, - src->stride * src->y, group_id), - src->y, src->stride, - lz_out_start_byte, - comp_head_left); - } else { - lz_data->data.u.lines_data.enc_get_virt = cb_get_virt; - lz_data->data.u.lines_data.enc_get_virt_opaque = &worker->mem_slots; - lz_data->data.u.lines_data.enc_validate_virt = cb_validate_virt; - lz_data->data.u.lines_data.enc_validate_virt_opaque = &worker->mem_slots; - lz_data->data.u.lines_data.stride = src->stride; - lz_data->data.u.lines_data.next = src->data; - lz_data->data.u.lines_data.group_id = group_id; - lz_data->usr.more_lines = lz_usr_more_lines; - - alpha_lz_size = lz_encode(lz, LZ_IMAGE_TYPE_XXXA, src->x, src->y, - (src->flags & QXL_BITMAP_TOP_DOWN), - NULL, 0, src->stride, - lz_out_start_byte, - comp_head_left); - } - + lz_data->data.u.lines_data.chunks = src->data; + lz_data->data.u.lines_data.stride = src->stride; + lz_data->data.u.lines_data.next = 0; + lz_data->data.u.lines_data.reverse = 0; + lz_data->usr.more_lines = lz_usr_more_lines; + + alpha_lz_size = lz_encode(lz, LZ_IMAGE_TYPE_XXXA, src->x, src->y, + (src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN), + NULL, 0, src->stride, + lz_out_start_byte, + comp_head_left); // the compressed buffer is bigger than the original data if ((jpeg_size + alpha_lz_size) > (src->y * src->stride)) { @@ -6405,13 +5983,13 @@ static int red_jpeg_compress_image(DisplayChannel *display_channel, RedImage *de } dest->descriptor.type = SPICE_IMAGE_TYPE_JPEG_ALPHA; - dest->jpeg_alpha.flags = 0; - if (src->flags & QXL_BITMAP_TOP_DOWN) { - dest->jpeg_alpha.flags |= SPICE_JPEG_ALPHA_FLAGS_TOP_DOWN; + dest->u.jpeg_alpha.flags = 0; + if (src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN) { + dest->u.jpeg_alpha.flags |= SPICE_JPEG_ALPHA_FLAGS_TOP_DOWN; } - dest->jpeg_alpha.jpeg_size = jpeg_size; - dest->jpeg_alpha.data_size = jpeg_size + alpha_lz_size; + dest->u.jpeg_alpha.jpeg_size = jpeg_size; + dest->u.jpeg_alpha.data_size = jpeg_size + alpha_lz_size; o_comp_data->comp_buf = jpeg_data->data.bufs_head; o_comp_data->comp_buf_size = jpeg_size + alpha_lz_size; @@ -6421,7 +5999,7 @@ static int red_jpeg_compress_image(DisplayChannel *display_channel, RedImage *de return TRUE; } -static inline int red_quic_compress_image(DisplayChannel *display_channel, RedImage *dest, +static inline int red_quic_compress_image(DisplayChannel *display_channel, SpiceImage *dest, SpiceBitmap *src, compress_send_data_t* o_comp_data, uint32_t group_id) { @@ -6429,7 +6007,7 @@ static inline int red_quic_compress_image(DisplayChannel *display_channel, RedIm QuicData *quic_data = &worker->quic_data; QuicContext *quic = worker->quic; QuicImageType type; - int size; + int size, stride; #ifdef COMPRESS_STAT stat_time_t start_time = stat_now(); @@ -6471,80 +6049,25 @@ static inline int red_quic_compress_image(DisplayChannel *display_channel, RedIm return FALSE; } - if ((src->flags & QXL_BITMAP_DIRECT)) { - int stride; - uint8_t *data; + if (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE) { + spice_chunks_linearize(src->data); + } - if (!(src->flags & QXL_BITMAP_TOP_DOWN)) { - data = (uint8_t*)get_virt(&worker->mem_slots, src->data, src->stride * src->y, group_id) + - src->stride * (src->y - 1); - stride = -src->stride; - } else { - data = (uint8_t*)get_virt(&worker->mem_slots, src->data, src->stride * src->y, group_id); - stride = src->stride; - } - - if ((src->flags & QXL_BITMAP_UNSTABLE)) { - quic_data->data.u.unstable_lines_data.next = data; - quic_data->data.u.unstable_lines_data.src_stride = stride; - quic_data->data.u.unstable_lines_data.dest_stride = src->stride; - quic_data->data.u.unstable_lines_data.lines = src->y; - quic_data->data.u.unstable_lines_data.input_bufs_pos = 0; - if (!(quic_data->data.u.unstable_lines_data.input_bufs[0] = - red_display_alloc_compress_buf(display_channel)) || - !(quic_data->data.u.unstable_lines_data.input_bufs[1] = - red_display_alloc_compress_buf(display_channel))) { - return FALSE; - } - quic_data->data.u.unstable_lines_data.max_lines_bunch = - sizeof(quic_data->data.u.unstable_lines_data.input_bufs[0]->buf) / - quic_data->data.u.unstable_lines_data.dest_stride; - quic_data->usr.more_lines = quic_usr_more_lines_unstable; - size = quic_encode(quic, type, src->x, src->y, NULL, 0, src->stride, - quic_data->data.bufs_head->buf, - sizeof(quic_data->data.bufs_head->buf) >> 2); - } else { - quic_data->usr.more_lines = quic_usr_no_more_lines; - size = quic_encode(quic, type, src->x, src->y, data, src->y, stride, - quic_data->data.bufs_head->buf, - sizeof(quic_data->data.bufs_head->buf) >> 2); - } + quic_data->data.u.lines_data.chunks = src->data; + quic_data->data.u.lines_data.stride = src->stride; + quic_data->usr.more_lines = quic_usr_more_lines; + if ((src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { + quic_data->data.u.lines_data.next = 0; + quic_data->data.u.lines_data.reverse = 0; + stride = src->stride; } else { - int stride; - - if ((src->flags & QXL_BITMAP_UNSTABLE)) { - red_printf_once("unexpected unstable bitmap"); - return FALSE; - } - quic_data->data.u.lines_data.enc_get_virt = cb_get_virt; - quic_data->data.u.lines_data.enc_get_virt_opaque = &worker->mem_slots; - quic_data->data.u.lines_data.enc_validate_virt = cb_validate_virt; - quic_data->data.u.lines_data.enc_validate_virt_opaque = &worker->mem_slots; - quic_data->data.u.lines_data.stride = src->stride; - quic_data->data.u.lines_data.group_id = group_id; - - if ((src->flags & QXL_BITMAP_TOP_DOWN)) { - quic_data->data.u.lines_data.next = src->data; - quic_data->usr.more_lines = quic_usr_more_lines; - stride = src->stride; - } else { - SPICE_ADDRESS prev_addr = src->data; - QXLDataChunk *chunk = (QXLDataChunk *)get_virt(&worker->mem_slots, src->data, - sizeof(QXLDataChunk), group_id); - while (chunk->next_chunk) { - prev_addr = chunk->next_chunk; - chunk = (QXLDataChunk *)get_virt(&worker->mem_slots, chunk->next_chunk, sizeof(QXLDataChunk), - group_id); - ASSERT(chunk->prev_chunk); - } - quic_data->data.u.lines_data.next = prev_addr; - quic_data->usr.more_lines = quic_usr_more_lines_reverse; - stride = -src->stride; - } - size = quic_encode(quic, type, src->x, src->y, NULL, 0, stride, - quic_data->data.bufs_head->buf, - sizeof(quic_data->data.bufs_head->buf) >> 2); + quic_data->data.u.lines_data.next = src->data->num_chunks - 1; + quic_data->data.u.lines_data.reverse = 1; + stride = -src->stride; } + size = quic_encode(quic, type, src->x, src->y, NULL, 0, stride, + quic_data->data.bufs_head->buf, + sizeof(quic_data->data.bufs_head->buf) >> 2); // the compressed buffer is bigger than the original data if ((size << 2) > (src->y * src->stride)) { @@ -6552,7 +6075,7 @@ static inline int red_quic_compress_image(DisplayChannel *display_channel, RedIm } dest->descriptor.type = SPICE_IMAGE_TYPE_QUIC; - dest->quic.data_size = size << 2; + dest->u.quic.data_size = size << 2; o_comp_data->comp_buf = quic_data->data.bufs_head; o_comp_data->comp_buf_size = size << 2; @@ -6565,7 +6088,7 @@ static inline int red_quic_compress_image(DisplayChannel *display_channel, RedIm #define MIN_SIZE_TO_COMPRESS 54 #define MIN_DIMENSION_TO_QUIC 3 static inline int red_compress_image(DisplayChannel *display_channel, - RedImage *dest, SpiceBitmap *src, Drawable *drawable, + SpiceImage *dest, SpiceBitmap *src, Drawable *drawable, int can_lossy, compress_send_data_t* o_comp_data) { @@ -6587,7 +6110,7 @@ static inline int red_compress_image(DisplayChannel *display_channel, lz doesn't handle (1) bitmaps with strides that are larger than the width of the image in bytes (2) unstable bitmaps */ - if (_stride_is_extra(src) || (src->flags & QXL_BITMAP_UNSTABLE)) { + if (_stride_is_extra(src) || (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE)) { if ((image_compression == SPICE_IMAGE_COMPRESS_LZ) || (image_compression == SPICE_IMAGE_COMPRESS_GLZ) || BITMAP_FMT_IS_PLT[src->format]) { @@ -6676,14 +6199,14 @@ 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, + SpiceImage *image, SpiceImage *io_image, int is_lossy) { - if ((qxl_image->descriptor.flags & QXL_IMAGE_CACHE)) { - ASSERT(qxl_image->descriptor.width * qxl_image->descriptor.height > 0); + if ((image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME)) { + ASSERT(image->descriptor.width * image->descriptor.height > 0); 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, + if (pixmap_cache_add(display_channel->pixmap_cache, image->descriptor.id, + image->descriptor.width * 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); @@ -6708,36 +6231,22 @@ typedef enum { /* 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 FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller *m, - QXLPHYSICAL in_bitmap, Drawable *drawable, int can_lossy) + SpiceImage *simage, Drawable *drawable, int can_lossy) { RedChannel *channel = &display_channel->base; RedWorker *worker = channel->worker; - RedImage image; - QXLImage *qxl_image; - uint8_t *data; - int memslot_id; + SpiceImage image; compress_send_data_t comp_send_data = {0}; SpiceMarshaller *bitmap_palette_out, *data_out, *lzplt_palette_out; - if (in_bitmap == 0) { + if (simage == NULL) { ASSERT(drawable->self_bitmap); - qxl_image = (QXLImage *)drawable->self_bitmap; - } else { - qxl_image = (QXLImage *)get_virt(&worker->mem_slots, in_bitmap, sizeof(QXLImage), - drawable->group_id); + simage = drawable->self_bitmap; } - image.descriptor.id = qxl_image->descriptor.id; - image.descriptor.type = qxl_image->descriptor.type; - image.descriptor.flags = 0; - if (qxl_image->descriptor.flags & QXL_IMAGE_HIGH_BITS_SET) { - image.descriptor.flags |= SPICE_IMAGE_FLAGS_HIGH_BITS_SET; - } - image.descriptor.width = qxl_image->descriptor.width; - image.descriptor.height = qxl_image->descriptor.height; + image.descriptor = simage->descriptor; - memslot_id = get_memslot_id(&worker->mem_slots, in_bitmap); - if ((qxl_image->descriptor.flags & QXL_IMAGE_CACHE)) { + if ((simage->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME)) { int lossy_cache_item; if (pixmap_cache_hit(display_channel->pixmap_cache, image.descriptor.id, &lossy_cache_item, display_channel)) { @@ -6750,7 +6259,7 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller * // will be retrieved as lossless by another display channel. image.descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS; } - spice_marshall_Image(m, (SpiceImageDescriptor *)&image, + spice_marshall_Image(m, &image, &bitmap_palette_out, &data_out, &lzplt_palette_out); ASSERT(bitmap_palette_out == NULL); ASSERT(data_out == NULL); @@ -6758,19 +6267,19 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller * stat_inc_counter(display_channel->cache_hits_counter, 1); return FILL_BITS_TYPE_CACHE; } else { - pixmap_cache_set_lossy(display_channel->pixmap_cache, qxl_image->descriptor.id, + pixmap_cache_set_lossy(display_channel->pixmap_cache, simage->descriptor.id, FALSE); image.descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME; } } } - switch (qxl_image->descriptor.type) { + switch (simage->descriptor.type) { case SPICE_IMAGE_TYPE_SURFACE: { int surface_id; RedSurface *surface; - surface_id = qxl_image->surface_image.surface_id; + surface_id = simage->u.surface.surface_id; validate_surface(worker, surface_id); surface = &worker->surfaces[surface_id]; @@ -6779,68 +6288,63 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller * image.descriptor.width = surface->context.width; image.descriptor.height = surface->context.height; - image.surface.surface_id = surface_id; - spice_marshall_Image(m, (SpiceImageDescriptor *)&image, + image.u.surface.surface_id = surface_id; + spice_marshall_Image(m, &image, &bitmap_palette_out, &data_out, &lzplt_palette_out); ASSERT(bitmap_palette_out == NULL); ASSERT(data_out == NULL); ASSERT(lzplt_palette_out == NULL); return FILL_BITS_TYPE_SURFACE; } - case SPICE_IMAGE_TYPE_BITMAP: + case SPICE_IMAGE_TYPE_BITMAP: { + SpiceBitmap *bitmap = &image.u.bitmap; #ifdef DUMP_BITMAP - dump_bitmap(display_channel->base.worker, &qxl_image->bitmap, drawable->group_id); + dump_bitmap(display_channel->base.worker, &simage->u.bitmap, drawable->group_id); #endif /* Images must be added to the cache only after they are compressed 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, + if (!red_compress_image(display_channel, &image, &simage->u.bitmap, drawable, can_lossy, &comp_send_data)) { - uint32_t y; + uint32_t y, i; uint32_t stride; - SPICE_ADDRESS image_data; SpicePalette *palette; + SpiceChunk *chunk; - red_display_add_image_to_pixmap_cache(display_channel, qxl_image, &image, FALSE); + red_display_add_image_to_pixmap_cache(display_channel, simage, &image, FALSE); - image.bitmap = qxl_image->bitmap; - y = image.bitmap.y; - stride = image.bitmap.stride; - image_data = image.bitmap.data; - image.bitmap.flags = image.bitmap.flags & SPICE_BITMAP_FLAGS_TOP_DOWN; + *bitmap = simage->u.bitmap; + y = bitmap->y; + stride = bitmap->stride; + bitmap->flags = bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN; - fill_palette(display_channel, &image.bitmap.palette, &image.bitmap.flags, - drawable->group_id, &palette); - spice_marshall_Image(m, (SpiceImageDescriptor *)&image, + palette = bitmap->palette; + fill_palette(display_channel, palette, &bitmap->flags); + spice_marshall_Image(m, &image, &bitmap_palette_out, &data_out, &lzplt_palette_out); ASSERT(lzplt_palette_out == NULL); - if (palette) { + if (bitmap_palette_out && palette) { spice_marshall_Palette(bitmap_palette_out, palette); } - if (qxl_image->bitmap.flags & QXL_BITMAP_DIRECT) { - data = (uint8_t *)get_virt(&worker->mem_slots, image_data, stride * y, drawable->group_id); - spice_marshaller_add_ref(data_out, data, y * stride); - } else { - data = (uint8_t *)get_virt(&worker->mem_slots, image_data, sizeof(QXLDataChunk), - drawable->group_id); - marshaller_add_chunk(worker, data_out, (QXLDataChunk *)data, - y * stride, memslot_id, drawable->group_id); + chunk = bitmap->data->chunk; + for (i = 0; i < bitmap->data->num_chunks; i++) { + spice_marshaller_add_ref(data_out, chunk[i].data, chunk[i].len); } return FILL_BITS_TYPE_BITMAP; } else { - red_display_add_image_to_pixmap_cache(display_channel, qxl_image, &image, + red_display_add_image_to_pixmap_cache(display_channel, simage, &image, comp_send_data.is_lossy); - spice_marshall_Image(m, (SpiceImageDescriptor *)&image, + spice_marshall_Image(m, &image, &bitmap_palette_out, &data_out, &lzplt_palette_out); ASSERT(bitmap_palette_out == NULL); marshaller_add_compressed(worker, m, comp_send_data.comp_buf, comp_send_data.comp_buf_size); - if (comp_send_data.lzplt_palette) { + if (lzplt_palette_out && comp_send_data.lzplt_palette) { spice_marshall_Palette(lzplt_palette_out, comp_send_data.lzplt_palette); } @@ -6849,16 +6353,15 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller * FILL_BITS_TYPE_COMPRESS_LOSSLESS); } break; + } case SPICE_IMAGE_TYPE_QUIC: - red_display_add_image_to_pixmap_cache(display_channel, qxl_image, &image, FALSE); - image.quic = qxl_image->quic; - spice_marshall_Image(m, (SpiceImageDescriptor *)&image, + red_display_add_image_to_pixmap_cache(display_channel, simage, &image, FALSE); + image.u.quic = simage->u.quic; + spice_marshall_Image(m, &image, &bitmap_palette_out, &data_out, &lzplt_palette_out); ASSERT(bitmap_palette_out == NULL); ASSERT(lzplt_palette_out == NULL); - marshaller_add_chunk(worker, m, (QXLDataChunk *)qxl_image->quic.data, - qxl_image->quic.data_size, - memslot_id, drawable->group_id); + spice_marshaller_add_ref_chunks(m, image.u.quic.data); return FILL_BITS_TYPE_COMPRESS_LOSSLESS; default: red_error("invalid image type %u", image.descriptor.type); @@ -6866,7 +6369,7 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller * } static void fill_mask(DisplayChannel *display_channel, SpiceMarshaller *m, - SPICE_ADDRESS mask_bitmap, Drawable *drawable) + SpiceImage *mask_bitmap, Drawable *drawable) { if (mask_bitmap && m) { if (display_channel->base.worker->image_compression != SPICE_IMAGE_COMPRESS_OFF) { @@ -7010,26 +6513,20 @@ static int is_surface_area_lossy(DisplayChannel *display_channel, uint32_t surfa to the client, returns false. "area" is for surfaces. If area = NULL, all the surface is considered. out_lossy_data will hold info about the bitmap, and its lossy area in case it is lossy and part of a surface. */ -static int is_bitmap_lossy(DisplayChannel *display_channel, SPICE_ADDRESS bitmap, SpiceRect *area, +static int is_bitmap_lossy(DisplayChannel *display_channel, SpiceImage *image, SpiceRect *area, Drawable *drawable, BitmapData *out_data) { - RedWorker *worker = display_channel->base.worker; - QXLImage *qxl_image; - - if (bitmap == 0) { + if (image == NULL) { // self bitmap out_data->type = BITMAP_DATA_TYPE_BITMAP; return FALSE; } - qxl_image = (QXLImage *)get_virt(&worker->mem_slots, bitmap, sizeof(QXLImage), - drawable->group_id); - - if ((qxl_image->descriptor.flags & QXL_IMAGE_CACHE)) { + if ((image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME)) { int is_hit_lossy; - out_data->id = qxl_image->descriptor.id; - if (pixmap_cache_hit(display_channel->pixmap_cache, qxl_image->descriptor.id, + out_data->id = image->descriptor.id; + if (pixmap_cache_hit(display_channel->pixmap_cache, image->descriptor.id, &is_hit_lossy, display_channel)) { out_data->type = BITMAP_DATA_TYPE_CACHE; if (is_hit_lossy) { @@ -7044,14 +6541,14 @@ static int is_bitmap_lossy(DisplayChannel *display_channel, SPICE_ADDRESS bitmap out_data->type = BITMAP_DATA_TYPE_BITMAP; } - if (qxl_image->descriptor.type != SPICE_IMAGE_TYPE_SURFACE) { + if (image->descriptor.type != SPICE_IMAGE_TYPE_SURFACE) { return FALSE; } out_data->type = BITMAP_DATA_TYPE_SURFACE; - out_data->id = qxl_image->surface_image.surface_id; + out_data->id = image->u.surface.surface_id; - if (is_surface_area_lossy(display_channel, qxl_image->surface_image.surface_id, + if (is_surface_area_lossy(display_channel, out_data->id, area, &out_data->lossy_rect)) { return TRUE; @@ -8373,31 +7870,28 @@ static inline void red_unref_channel(RedChannel *channel) } } -static inline uint8_t *red_get_image_line(RedWorker *worker, QXLDataChunk **chunk, int *offset, - int stride, long phys_delta, int memslot_id, - uint32_t group_id) +static inline uint8_t *red_get_image_line(RedWorker *worker, SpiceChunks *chunks, size_t *offset, + int *chunk_nr, int stride) { uint8_t *ret; - uint32_t data_size; + SpiceChunk *chunk; - validate_virt(&worker->mem_slots, (unsigned long)*chunk, memslot_id, sizeof(QXLDataChunk), - group_id); - data_size = (*chunk)->data_size; - validate_virt(&worker->mem_slots, (unsigned long)(*chunk)->data, memslot_id, data_size, group_id); + chunk = &chunks->chunk[*chunk_nr]; - if (data_size == *offset) { - if ((*chunk)->next_chunk == 0) { - return NULL; + if (*offset == chunk->len) { + if (*chunk_nr == chunks->num_chunks - 1) { + return NULL; /* Last chunk */ } *offset = 0; - *chunk = (QXLDataChunk *)((*chunk)->next_chunk + phys_delta); + (*chunk_nr)++; + chunk = &chunks->chunk[*chunk_nr]; } - if (data_size - *offset < stride) { + if (chunk->len - *offset < stride) { red_printf("bad chunk alignment"); return NULL; } - ret = (*chunk)->data + *offset; + ret = chunk->data + *offset; *offset += stride; return ret; } @@ -8413,31 +7907,29 @@ static void red_display_unshare_stream_buf(DisplayChannel *display_channel) static int red_rgb32bpp_to_24 (RedWorker *worker, const SpiceRect *src, const SpiceBitmap *image, uint8_t *frame, size_t frame_stride, - long phys_delta, int memslot_id, int id, - Stream *stream, uint32_t group_id) + int id, Stream *stream) { - QXLDataChunk *chunk; + SpiceChunks *chunks; uint32_t image_stride; uint8_t *frame_row; - int offset; - int i, x; + size_t offset; + int i, x, chunk; + chunks = image->data; offset = 0; - chunk = (QXLDataChunk *)(image->data + phys_delta); + chunk = 0; image_stride = image->stride; const int skip_lines = stream->top_down ? src->top : image->y - (src->bottom - 0); for (i = 0; i < skip_lines; i++) { - red_get_image_line(worker, &chunk, &offset, image_stride, phys_delta, memslot_id, - group_id); + red_get_image_line(worker, chunks, &offset, &chunk, image_stride); } const int image_height = src->bottom - src->top; const int image_width = src->right - src->left; for (i = 0; i < image_height; i++) { uint32_t *src_line = - (uint32_t *)red_get_image_line(worker, &chunk, &offset, image_stride, phys_delta, - memslot_id, group_id); + (uint32_t *)red_get_image_line(worker, chunks, &offset, &chunk, image_stride); if (!src_line) { return FALSE; @@ -8462,31 +7954,29 @@ static int red_rgb32bpp_to_24 (RedWorker *worker, const SpiceRect *src, static int red_rgb24bpp_to_24 (RedWorker *worker, const SpiceRect *src, const SpiceBitmap *image, uint8_t *frame, size_t frame_stride, - long phys_delta, int memslot_id, int id, - Stream *stream, uint32_t group_id) + int id, Stream *stream) { - QXLDataChunk *chunk; + SpiceChunks *chunks; uint32_t image_stride; uint8_t *frame_row; - int offset; - int i; + size_t offset; + int i, chunk; + chunks = image->data; offset = 0; - chunk = (QXLDataChunk *)(image->data + phys_delta); + chunk = 0; image_stride = image->stride; const int skip_lines = stream->top_down ? src->top : image->y - (src->bottom - 0); for (i = 0; i < skip_lines; i++) { - red_get_image_line(worker, &chunk, &offset, image_stride, phys_delta, memslot_id, - group_id); + red_get_image_line(worker, chunks, &offset, &chunk, image_stride); } const int image_height = src->bottom - src->top; const int image_width = src->right - src->left; for (i = 0; i < image_height; i++) { uint8_t *src_line = - (uint8_t *)red_get_image_line(worker, &chunk, &offset, image_stride, phys_delta, - memslot_id, group_id); + (uint8_t *)red_get_image_line(worker, chunks, &offset, &chunk, image_stride); if (!src_line) { return FALSE; @@ -8505,31 +7995,29 @@ static int red_rgb24bpp_to_24 (RedWorker *worker, const SpiceRect *src, static int red_rgb16bpp_to_24 (RedWorker *worker, const SpiceRect *src, const SpiceBitmap *image, uint8_t *frame, size_t frame_stride, - long phys_delta, int memslot_id, int id, - Stream *stream, uint32_t group_id) + int id, Stream *stream) { - QXLDataChunk *chunk; + SpiceChunks *chunks; uint32_t image_stride; uint8_t *frame_row; - int offset; - int i, x; + size_t offset; + int i, x, chunk; + chunks = image->data; offset = 0; - chunk = (QXLDataChunk *)(image->data + phys_delta); + chunk = 0; image_stride = image->stride; const int skip_lines = stream->top_down ? src->top : image->y - (src->bottom - 0); for (i = 0; i < skip_lines; i++) { - red_get_image_line(worker, &chunk, &offset, image_stride, phys_delta, memslot_id, - group_id); + red_get_image_line(worker, chunks, &offset, &chunk, image_stride); } const int image_height = src->bottom - src->top; const int image_width = src->right - src->left; for (i = 0; i < image_height; i++) { uint16_t *src_line = - (uint16_t *)red_get_image_line(worker, &chunk, &offset, image_stride, phys_delta, - memslot_id, group_id); + (uint16_t *)red_get_image_line(worker, chunks, &offset, &chunk, image_stride); if (!src_line) { return FALSE; @@ -8556,10 +8044,9 @@ static int red_rgb16bpp_to_24 (RedWorker *worker, const SpiceRect *src, static inline int red_send_stream_data(DisplayChannel *display_channel, Drawable *drawable) { Stream *stream = drawable->stream; - QXLImage *qxl_image; + SpiceImage *image; RedChannel *channel; RedWorker* worker; - unsigned long data; uint8_t *frame; size_t frame_stride; int n; @@ -8569,11 +8056,9 @@ static inline int red_send_stream_data(DisplayChannel *display_channel, Drawable channel = &display_channel->base; worker = channel->worker; - qxl_image = (QXLImage *)get_virt(&worker->mem_slots, drawable->red_drawable->u.copy.src_bitmap, - sizeof(QXLImage), drawable->group_id); + image = drawable->red_drawable->u.copy.src_bitmap; - if (qxl_image->descriptor.type != SPICE_IMAGE_TYPE_BITMAP || - (qxl_image->bitmap.flags & QXL_BITMAP_DIRECT)) { + if (image->descriptor.type != SPICE_IMAGE_TYPE_BITMAP) { return FALSE; } @@ -8584,40 +8069,33 @@ static inline int red_send_stream_data(DisplayChannel *display_channel, Drawable return TRUE; } - data = qxl_image->bitmap.data; frame = mjpeg_encoder_get_frame(stream->mjpeg_encoder); frame_stride = mjpeg_encoder_get_frame_stride(stream->mjpeg_encoder); - switch (qxl_image->bitmap.format) { + switch (image->u.bitmap.format) { case SPICE_BITMAP_FMT_32BIT: if (!red_rgb32bpp_to_24(worker, &drawable->red_drawable->u.copy.src_area, - &qxl_image->bitmap, frame, frame_stride, - get_virt_delta(&worker->mem_slots, data, drawable->group_id), - get_memslot_id(&worker->mem_slots, data), - stream - worker->streams_buf, stream, drawable->group_id)) { + &image->u.bitmap, frame, frame_stride, + stream - worker->streams_buf, stream)) { return FALSE; } break; case SPICE_BITMAP_FMT_16BIT: if (!red_rgb16bpp_to_24(worker, &drawable->red_drawable->u.copy.src_area, - &qxl_image->bitmap, frame, frame_stride, - get_virt_delta(&worker->mem_slots, data, drawable->group_id), - get_memslot_id(&worker->mem_slots, data), - stream - worker->streams_buf, stream, drawable->group_id)) { + &image->u.bitmap, frame, frame_stride, + stream - worker->streams_buf, stream)) { return FALSE; } break; case SPICE_BITMAP_FMT_24BIT: if (!red_rgb24bpp_to_24(worker, &drawable->red_drawable->u.copy.src_area, - &qxl_image->bitmap, frame, frame_stride, - get_virt_delta(&worker->mem_slots, data, drawable->group_id), - get_memslot_id(&worker->mem_slots, data), - stream - worker->streams_buf, stream, drawable->group_id)) { + &image->u.bitmap, frame, frame_stride, + stream - worker->streams_buf, stream)) { return FALSE; } break; default: - red_printf_some(1000, "unsupported format %d", qxl_image->bitmap.format); + red_printf_some(1000, "unsupported format %d", image->u.bitmap.format); return FALSE; } @@ -8804,9 +8282,10 @@ static void display_channel_reset_cache(DisplayChannel *display_channel) static void red_send_image(DisplayChannel *display_channel, ImageItem *item) { RedChannel *channel; - RedImage red_image; + SpiceImage red_image; RedWorker *worker; SpiceBitmap bitmap; + SpiceChunks *chunks; QRegion *surface_lossy_region; int comp_succeeded; int lossy_comp = FALSE; @@ -8827,13 +8306,17 @@ static void red_send_image(DisplayChannel *display_channel, ImageItem *item) red_image.descriptor.height = item->height; bitmap.format = item->image_format; - bitmap.flags = QXL_BITMAP_DIRECT; - bitmap.flags |= item->top_down ? QXL_BITMAP_TOP_DOWN : 0; + if (item->top_down) { + bitmap.flags |= SPICE_BITMAP_FLAGS_TOP_DOWN; + } bitmap.x = item->width; bitmap.y = item->height; bitmap.stride = item->stride; bitmap.palette = 0; - bitmap.data = (SPICE_ADDRESS)item->data; + bitmap.palette_id = 0; + + chunks = spice_chunks_new_linear(item->data, bitmap.stride * bitmap.y); + bitmap.data = chunks; channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_COPY; @@ -8903,13 +8386,13 @@ static void red_send_image(DisplayChannel *display_channel, ImageItem *item) surface_lossy_region = &display_channel->surface_client_lossy_region[item->surface_id]; if (comp_succeeded) { - spice_marshall_Image(src_bitmap_out, (SpiceImageDescriptor *)&red_image, + spice_marshall_Image(src_bitmap_out, &red_image, &bitmap_palette_out, &data_out, &lzplt_palette_out); marshaller_add_compressed(worker, src_bitmap_out, comp_send_data.comp_buf, comp_send_data.comp_buf_size); - if (comp_send_data.lzplt_palette) { + if (lzplt_palette_out && comp_send_data.lzplt_palette) { spice_marshall_Palette(lzplt_palette_out, comp_send_data.lzplt_palette); } @@ -8920,15 +8403,16 @@ static void red_send_image(DisplayChannel *display_channel, ImageItem *item) } } else { red_image.descriptor.type = SPICE_IMAGE_TYPE_BITMAP; - red_image.bitmap = bitmap; - red_image.bitmap.flags &= ~QXL_BITMAP_DIRECT; + red_image.u.bitmap = bitmap; - spice_marshall_Image(src_bitmap_out, (SpiceImageDescriptor *)&red_image, + spice_marshall_Image(src_bitmap_out, &red_image, &bitmap_palette_out, &data_out, &lzplt_palette_out); spice_marshaller_add_ref(data_out, item->data, bitmap.y * bitmap.stride); region_remove(surface_lossy_region, ©.base.box); } display_begin_send_massage(display_channel, &item->link); + + spice_chunks_destroy(chunks); } static void red_display_send_upgrade(DisplayChannel *display_channel, UpgradeItem *item) @@ -9493,8 +8977,7 @@ static SpiceCanvas *create_ogl_context_common(RedWorker *worker, OGLCtx *ctx, ui oglctx_make_current(ctx); if (!(canvas = gl_canvas_create(width, height, depth, &worker->image_cache.base, - &worker->image_surfaces, NULL, NULL, NULL, - &worker->preload_group_virt_mapping))) { + &worker->image_surfaces, NULL, NULL, NULL))) { return NULL; } @@ -9552,8 +9035,7 @@ static inline void *create_canvas_for_surface(RedWorker *worker, RedSurface *sur canvas = canvas_create_for_data(width, height, format, line_0, stride, &worker->image_cache.base, - &worker->image_surfaces, NULL, NULL, NULL, - &worker->preload_group_virt_mapping); + &worker->image_surfaces, NULL, NULL, NULL); surface->context.top_down = TRUE; surface->context.canvas_draws_on_surface = TRUE; return canvas; @@ -11055,10 +10537,6 @@ static void red_init(RedWorker *worker, WorkerInitData *init_data) struct epoll_event event; RedWorkerMessage message; int epoll; - static SpiceVirtMappingOps preload_group_virt_mapping_ops = { - op_get_virt_preload_group, - op_validate_virt_preload_group - }; ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE); @@ -11115,8 +10593,6 @@ static void red_init(RedWorker *worker, WorkerInitData *init_data) PANIC_ON(init_data->n_surfaces > NUM_SURFACES); worker->n_surfaces = init_data->n_surfaces; - worker->preload_group_virt_mapping.ops = &preload_group_virt_mapping_ops; - message = RED_WORKER_MESSAGE_READY; write_message(worker->channel, &message); } @@ -11128,7 +10604,6 @@ void *red_worker_main(void *arg) red_printf("begin"); ASSERT(MAX_PIPE_SIZE > WIDE_CLIENT_ACK_WINDOW && MAX_PIPE_SIZE > NARROW_CLIENT_ACK_WINDOW); //ensure wakeup by ack message - ASSERT(QXL_BITMAP_TOP_DOWN == SPICE_BITMAP_FLAGS_TOP_DOWN); #if defined(RED_WORKER_STAT) || defined(COMPRESS_STAT) if (pthread_getcpuclockid(pthread_self(), &clock_id)) { @@ -11239,6 +10714,7 @@ static void dump_bitmap(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_i int32_t tmp_32; uint16_t tmp_u16; FILE *f; + int i; switch (bitmap->format) { case SPICE_BITMAP_FMT_1BIT_BE: @@ -11276,7 +10752,7 @@ static void dump_bitmap(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_i if (!bitmap->palette) { return; // dont dump masks. } - plt = (SpicePalette *)get_virt(&worker->mem_slots, bitmap->palette, sizeof(SpicePalette), group_id); + plt = bitmap->palette; } row_size = (((bitmap->x * n_pixel_bits) + 31) / 32) * 4; bitmap_data_offset = header_size; @@ -11331,29 +10807,11 @@ static void dump_bitmap(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_i dump_palette(f, plt); } /* writing the data */ - if ((bitmap->flags & QXL_BITMAP_DIRECT)) { - uint8_t *lines = (uint8_t*)get_virt(&worker->mem_slots, bitmap->data, bitmap->stride * bitmap->y, - group_id); - int i; - for (i = 0; i < bitmap->y; i++) { - dump_line(f, lines + (i * bitmap->stride), n_pixel_bits, bitmap->x, row_size); - } - } else { - QXLDataChunk *chunk = NULL; - int num_lines; - SPICE_ADDRESS relative_address = bitmap->data; - - while (relative_address) { - int i; - chunk = (QXLDataChunk *)get_virt(&worker->mem_slots, relative_address, sizeof(QXLDataChunk), - group_id); - validate_virt(&worker->mem_slots, chunk->data, get_memslot_id(&worker->mem_slots, relative_address), - chunk->data_size, group_id); - num_lines = chunk->data_size / bitmap->stride; - for (i = 0; i < num_lines; i++) { - dump_line(f, chunk->data + (i * bitmap->stride), n_pixel_bits, bitmap->x, row_size); - } - relative_address = chunk->next_chunk; + for (i = 0; i < bitmap->data->num_chunks; i++) { + SpiceChunk *chunk = &bitmap->data->chunk[i]; + int num_lines = chunk->len / bitmap->stride; + for (i = 0; i < num_lines; i++) { + dump_line(f, chunk->data + (i * bitmap->stride), n_pixel_bits, bitmap->x, row_size); } } fclose(f); diff --git a/spice.proto b/spice.proto index e437630..e16250f 100644 --- a/spice.proto +++ b/spice.proto @@ -111,7 +111,7 @@ channel BaseChannel { message { uint32 id; uint64 timestamp; - uint8 data[] @end @ctype(uint8_t) @as_ptr(data_len); + uint8 data[] @ctype(uint8_t) @as_ptr(data_len); } ping; message { @@ -435,16 +435,16 @@ struct BitmapData { uint32 stride; switch (flags) { case PAL_FROM_CACHE: - uint64 palette; + uint64 palette_id; default: - Palette *palette @outvar(bitmap); + Palette *palette @outvar(bitmap) @c_ptr; } pal @anon; - uint8 *data[image_size(8, stride, y)] @nocopy; /* pointer to array, not array of pointers as in C */ + uint8 *data[image_size(8, stride, y)] @chunk; /* pointer to array, not array of pointers as in C */ } @ctype(SpiceBitmap); struct BinaryData { uint32 data_size; - uint8 data[data_size] @end @nomarshal; + uint8 data[data_size] @nomarshal @chunk; } @ctype(SpiceQUICData); struct LZPLTData { @@ -452,58 +452,63 @@ struct LZPLTData { uint32 data_size; switch (flags) { case PAL_FROM_CACHE: - uint64 palette; + uint64 palette_id; default: - Palette *palette @nonnull @outvar(lzplt); + Palette *palette @nonnull @outvar(lzplt) @c_ptr; } pal @anon; - uint8 data[data_size] @end @nomarshal; + uint8 data[data_size] @nomarshal @chunk; }; struct ZlibGlzRGBData { uint32 glz_data_size; uint32 data_size; - uint8 data[data_size] @end @nomarshal; + uint8 data[data_size] @nomarshal @chunk; } @ctype(SpiceZlibGlzRGBData); struct JPEGAlphaData { jpeg_alpha_flags flags; uint32 jpeg_size; uint32 data_size; - uint8 data[data_size] @end @nomarshal; + uint8 data[data_size] @nomarshal @chunk; } @ctype(SpiceJPEGAlphaData); struct Surface { uint32 surface_id; }; -struct Image { - uint64 id; - image_type type; - image_flags flags; - uint32 width; - uint32 height; - switch (type) { +struct Image { + struct ImageDescriptor { + uint64 id; + image_type type; + image_flags flags; + uint32 width; + uint32 height; + } descriptor; + + switch (descriptor.type) { case BITMAP: - BitmapData bitmap_data @ctype(SpiceBitmap); + BitmapData bitmap; case QUIC: + BinaryData quic; case LZ_RGB: case GLZ_RGB: + BinaryData lz_rgb; case JPEG: - BinaryData binary_data @ctype(SpiceQUICData); + BinaryData jpeg; case LZ_PLT: - LZPLTData lzplt_data @ctype(SpiceLZPLTData); + LZPLTData lz_plt; case ZLIB_GLZ_RGB: - ZlibGlzRGBData zlib_glz_data @ctype(SpiceZlibGlzRGBData); + ZlibGlzRGBData zlib_glz; case JPEG_ALPHA: - JPEGAlphaData jpeg_alpha_data @ctype(SpiceJPEGAlphaData); + JPEGAlphaData jpeg_alpha; case SURFACE: - Surface surface_data; - } u @end; -} @ctype(SpiceImageDescriptor); + Surface surface; + } u; +}; struct Pattern { - Image *pat @nonnull; + Image *pat @nonnull @c_ptr; Point pos; }; @@ -520,7 +525,7 @@ struct Brush { struct QMask { mask_flags flags; Point pos; - Image *bitmap; + Image *bitmap @c_ptr; }; struct LineAttr { @@ -649,7 +654,7 @@ channel DisplayChannel : BaseChannel { message { DisplayBase base; struct Opaque { - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; Brush brush; ropd rop_descriptor; @@ -661,7 +666,7 @@ channel DisplayChannel : BaseChannel { message { DisplayBase base; struct Copy { - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; ropd rop_descriptor; image_scale_mode scale_mode; @@ -672,7 +677,7 @@ channel DisplayChannel : BaseChannel { message { DisplayBase base; struct Blend { - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; ropd rop_descriptor; image_scale_mode scale_mode; @@ -704,7 +709,7 @@ channel DisplayChannel : BaseChannel { message { DisplayBase base; struct Rop3 { - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; Brush brush; uint8 rop3; @@ -739,7 +744,7 @@ channel DisplayChannel : BaseChannel { message { DisplayBase base; struct Transparent { - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; uint32 src_color; uint32 true_color; @@ -751,7 +756,7 @@ channel DisplayChannel : BaseChannel { struct AlphaBlnd { alpha_flags alpha_flags; uint8 alpha; - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; } data; } draw_alpha_blend; @@ -875,7 +880,7 @@ struct CursorHeader { struct Cursor { cursor_flags flags; CursorHeader header; - uint8 data[] @end @as_ptr(data_size); + uint8 data[] @as_ptr(data_size); }; channel CursorChannel : BaseChannel { @@ -929,13 +934,13 @@ channel PlaybackChannel : BaseChannel { server: message { uint32 time; - uint8 data[] @end @as_ptr(data_size); + uint8 data[] @as_ptr(data_size); } @ctype(SpiceMsgPlaybackPacket) data = 101; message { uint32 time; audio_data_mode mode; - uint8 data[] @end @as_ptr(data_size); + uint8 data[] @as_ptr(data_size); } mode; message { @@ -960,13 +965,13 @@ channel RecordChannel : BaseChannel { client: message { uint32 time; - uint8 data[] @end @nomarshal @as_ptr(data_size); + uint8 data[] @nomarshal @as_ptr(data_size); } @ctype(SpiceMsgcRecordPacket) data = 101; message { uint32 time; audio_data_mode mode; - uint8 data[] @end @as_ptr(data_size); + uint8 data[] @as_ptr(data_size); } mode; message { diff --git a/spice1.proto b/spice1.proto index b49371a..7bbccb7 100644 --- a/spice1.proto +++ b/spice1.proto @@ -111,7 +111,7 @@ channel BaseChannel { message { uint32 id; uint64 timestamp; - uint8 data[] @end @ctype(uint8_t) @as_ptr(data_len); + uint8 data[] @ctype(uint8_t) @as_ptr(data_len); } ping; message { @@ -419,16 +419,16 @@ struct BitmapData { uint32 stride; switch (flags) { case PAL_FROM_CACHE: - uint64 palette; + uint64 palette_id; default: - Palette *palette @outvar(bitmap); + Palette *palette @outvar(bitmap) @c_ptr; } pal @anon; - uint8 *data[image_size(8, stride, y)] @nocopy; /* pointer to array, not array of pointers as in C */ + uint8 *data[image_size(8, stride, y)] @chunk; /* pointer to array, not array of pointers as in C */ } @ctype(SpiceBitmap); struct BinaryData { uint32 data_size; - uint8 data[data_size] @end @nomarshal; + uint8 data[data_size] @nomarshal @chunk; } @ctype(SpiceQUICData); struct LZPLTData { @@ -436,34 +436,37 @@ struct LZPLTData { uint32 data_size; switch (flags) { case PAL_FROM_CACHE: - uint64 palette; + uint64 palette_id; default: - Palette *palette @nonnull @outvar(lzplt); + Palette *palette @nonnull @outvar(lzplt) @c_ptr; } pal @anon; - uint8 data[data_size] @end @nomarshal; + uint8 data[data_size] @nomarshal @chunk; }; struct Image { - uint64 id; - image_type type; - image_flags flags; - uint32 width; - uint32 height; - - switch (type) { + struct ImageDescriptor { + uint64 id; + image_type type; + image_flags flags; + uint32 width; + uint32 height; + } descriptor; + + switch (descriptor.type) { case BITMAP: - BitmapData bitmap_data @ctype(SpiceBitmap); + BitmapData bitmap; case QUIC: + BinaryData quic; case LZ_RGB: case GLZ_RGB: - BinaryData binary_data @ctype(SpiceQUICData); + BinaryData lz_rgb; case LZ_PLT: - LZPLTData lzplt_data @ctype(SpiceLZPLTData); - } u @end; -} @ctype(SpiceImageDescriptor); + LZPLTData lz_plt; + } u; +}; struct Pattern { - Image *pat @nonnull; + Image *pat @nonnull @c_ptr; Point pos; }; @@ -480,7 +483,7 @@ struct Brush { struct QMask { mask_flags flags; Point pos; - Image *bitmap; + Image *bitmap @c_ptr; }; struct LineAttr { @@ -608,7 +611,7 @@ channel DisplayChannel : BaseChannel { message { DisplayBase base; struct Opaque { - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; Brush brush; ropd rop_descriptor; @@ -620,7 +623,7 @@ channel DisplayChannel : BaseChannel { message { DisplayBase base; struct Copy { - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; ropd rop_descriptor; image_scale_mode scale_mode; @@ -631,7 +634,7 @@ channel DisplayChannel : BaseChannel { message { DisplayBase base; struct Blend { - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; ropd rop_descriptor; image_scale_mode scale_mode; @@ -663,7 +666,7 @@ channel DisplayChannel : BaseChannel { message { DisplayBase base; struct Rop3 { - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; Brush brush; uint8 rop3; @@ -698,7 +701,7 @@ channel DisplayChannel : BaseChannel { message { DisplayBase base; struct Transparent { - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; uint32 src_color; uint32 true_color; @@ -710,7 +713,7 @@ channel DisplayChannel : BaseChannel { struct AlphaBlnd { int8 alpha_flags @virtual(0); uint8 alpha; - Image *src_bitmap; + Image *src_bitmap @c_ptr; Rect src_area; } data; } draw_alpha_blend; @@ -822,7 +825,7 @@ struct CursorHeader { struct Cursor { cursor_flags flags; CursorHeader header; - uint8 data[] @end @as_ptr(data_size); + uint8 data[] @as_ptr(data_size); }; channel CursorChannel : BaseChannel { @@ -876,13 +879,13 @@ channel PlaybackChannel : BaseChannel { server: message { uint32 time; - uint8 data[] @end @as_ptr(data_size); + uint8 data[] @as_ptr(data_size); } @ctype(SpiceMsgPlaybackPacket) data = 101; message { uint32 time; audio_data_mode mode; - uint8 data[] @end @as_ptr(data_size); + uint8 data[] @as_ptr(data_size); } mode; message { @@ -907,13 +910,13 @@ channel RecordChannel : BaseChannel { client: message { uint32 time; - uint8 data[] @end @nomarshal @as_ptr(data_size); + uint8 data[] @nomarshal @as_ptr(data_size); } @ctype(SpiceMsgcRecordPacket) data = 101; message { uint32 time; audio_data_mode mode; - uint8 data[] @end @as_ptr(data_size); + uint8 data[] @as_ptr(data_size); } mode; message { |