summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2010-07-01 17:55:33 +0200
committerAlexander Larsson <alexl@redhat.com>2010-07-07 23:58:33 +0200
commit5ac88aa79fa6445f96e5419d8bf4fce81da63b90 (patch)
treeae702a8569fda96e8bfe27c6b2655d90bcef7ce4
parent26c1a0767f3fdcd0211b6b4c91a63ac9bc7abc6f (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.c267
-rw-r--r--common/canvas_base.h11
-rw-r--r--common/gl_canvas.c6
-rw-r--r--common/gl_canvas.h3
-rw-r--r--common/sw_canvas.c18
-rw-r--r--common/sw_canvas.h6
-rw-r--r--python_modules/demarshal.py4
-rw-r--r--python_modules/ptypes.py31
-rw-r--r--python_modules/spice_parser.py2
-rw-r--r--server/red_parse_qxl.c278
-rw-r--r--server/red_parse_qxl.h1
-rw-r--r--server/red_worker.c1244
-rw-r--r--spice.proto81
-rw-r--r--spice1.proto69
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, &copy.src_bitmap, drawable->group_id);
- localize_mask(worker, &copy.mask, drawable->group_id);
+ SpiceImage img1, img2;
+ localize_bitmap(worker, &copy.src_bitmap, &img1);
+ localize_mask(worker, &copy.mask, &img2);
canvas->ops->draw_copy(canvas, &drawable->red_drawable->bbox,
&clip, &copy);
- unlocalize_mask(&copy.mask);
- unlocalize_bitmap(&copy.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, &copy.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 {