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).
This commit is contained in:
Gerd Hoffmann 2010-07-01 17:55:33 +02:00 committed by Alexander Larsson
parent 26c1a0767f
commit 5ac88aa79f
14 changed files with 815 additions and 1210 deletions

View File

@ -69,18 +69,6 @@
(((descriptor)->type == SPICE_IMAGE_TYPE_JPEG) || \ (((descriptor)->type == SPICE_IMAGE_TYPE_JPEG) || \
((descriptor)->type == SPICE_IMAGE_TYPE_JPEG_ALPHA)) ((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) static inline int fix_to_int(SPICE_FIXED28_4 fixed)
{ {
int val, rem; int val, rem;
@ -157,11 +145,9 @@ typedef struct QuicData {
QuicUsrContext usr; QuicUsrContext usr;
QuicContext *quic; QuicContext *quic;
jmp_buf jmp_env; jmp_buf jmp_env;
#ifndef SW_CANVAS_NO_CHUNKS
SPICE_ADDRESS next;
SpiceVirtMapping *virt_mapping;
#endif
char message_buf[512]; char message_buf[512];
SpiceChunks *chunks;
int current_chunk;
} QuicData; } QuicData;
typedef struct CanvasBase { typedef struct CanvasBase {
@ -196,32 +182,6 @@ typedef struct CanvasBase {
spice_destroy_fn_t usr_data_destroy; spice_destroy_fn_t usr_data_destroy;
} CanvasBase; } 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 { typedef enum {
ROP_INPUT_SRC, ROP_INPUT_SRC,
ROP_INPUT_BRUSH, ROP_INPUT_BRUSH,
@ -434,7 +394,7 @@ static pixman_format_code_t canvas_get_target_format(CanvasBase *canvas,
return format; 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) int invers, int want_original)
{ {
pixman_image_t *surface = NULL; pixman_image_t *surface = NULL;
@ -445,30 +405,21 @@ static pixman_image_t *canvas_get_quic(CanvasBase *canvas, SpiceQUICImage *image
int stride; int stride;
int width; int width;
int height; int height;
#ifndef SW_CANVAS_NO_CHUNKS
DataChunk **tmp;
DataChunk *chunk;
#endif
if (setjmp(quic_data->jmp_env)) { if (setjmp(quic_data->jmp_env)) {
pixman_image_unref(surface); pixman_image_unref(surface);
CANVAS_ERROR("quic error, %s", quic_data->message_buf); CANVAS_ERROR("quic error, %s", quic_data->message_buf);
} }
#ifdef SW_CANVAS_NO_CHUNKS quic_data->chunks = image->u.quic.data;
if (quic_decode_begin(quic_data->quic, (uint32_t *)image->quic.data, quic_data->current_chunk = 0;
image->quic.data_size >> 2, &type, &width, &height) == QUIC_ERROR) {
CANVAS_ERROR("quic decode begin failed"); if (quic_decode_begin(quic_data->quic,
} (uint32_t *)image->u.quic.data->chunk[0].data,
#else image->u.quic.data->chunk[0].len >> 2,
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,
&type, &width, &height) == QUIC_ERROR) { &type, &width, &height) == QUIC_ERROR) {
CANVAS_ERROR("quic decode begin failed"); CANVAS_ERROR("quic decode begin failed");
} }
#endif
switch (type) { switch (type) {
case QUIC_IMAGE_TYPE_RGBA: case QUIC_IMAGE_TYPE_RGBA:
@ -564,7 +515,7 @@ static void dump_jpeg(uint8_t* data, int data_size)
} }
#endif #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; pixman_image_t *surface = NULL;
int stride; int stride;
@ -572,7 +523,8 @@ static pixman_image_t *canvas_get_jpeg(CanvasBase *canvas, SpiceJPEGImage *image
int height; int height;
uint8_t *dest; 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); &width, &height);
ASSERT((uint32_t)width == image->descriptor.width); ASSERT((uint32_t)width == image->descriptor.width);
ASSERT((uint32_t)height == image->descriptor.height); 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 #ifdef DUMP_JPEG
dump_jpeg(image->jpeg.data, image->jpeg.data_size); dump_jpeg(image->u.jpeg.data, image->u.jpeg.data_size);
#endif #endif
return surface; return surface;
} }
static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas, static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas,
SpiceJPEGAlphaImage *image, int invers) SpiceImage *image, int invers)
{ {
pixman_image_t *surface = NULL; pixman_image_t *surface = NULL;
int stride; int stride;
@ -627,13 +579,15 @@ static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas,
int alpha_size; int alpha_size;
int lz_alpha_width, lz_alpha_height, n_comp_pixels, lz_alpha_top_down; 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, ASSERT(image->u.jpeg_alpha.data->num_chunks == 1);
image->jpeg_alpha.jpeg_size, 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); &width, &height);
ASSERT((uint32_t)width == image->descriptor.width); ASSERT((uint32_t)width == image->descriptor.width);
ASSERT((uint32_t)height == image->descriptor.height); 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; alpha_top_down = TRUE;
} }
@ -642,7 +596,7 @@ static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas,
#endif #endif
surface = alloc_lz_image_surface(&lz_data->decode_data, PIXMAN_a8r8g8b8, surface = alloc_lz_image_surface(&lz_data->decode_data, PIXMAN_a8r8g8b8,
width, height, width*height, alpha_top_down); width, height, width*height, alpha_top_down);
if (surface == NULL) { if (surface == NULL) {
CANVAS_ERROR("create surface failed"); 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); stride = pixman_image_get_stride(surface);
canvas->jpeg->ops->decode(canvas->jpeg, dest, stride, SPICE_BITMAP_FMT_32BIT); canvas->jpeg->ops->decode(canvas->jpeg, dest, stride, SPICE_BITMAP_FMT_32BIT);
comp_alpha_buf = image->jpeg_alpha.data + 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->jpeg_alpha.data_size - image->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_decode_begin(lz_data->lz, comp_alpha_buf, alpha_size, &lz_alpha_type,
&lz_alpha_width, &lz_alpha_height, &n_comp_pixels, &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 #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 #endif
return surface; return surface;
} }
@ -698,7 +652,9 @@ static pixman_image_t *canvas_bitmap_to_surface(CanvasBase *canvas, SpiceBitmap*
pixman_image_t *image; pixman_image_t *image;
pixman_format_code_t format; 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; src_stride = bitmap->stride;
if (want_original) { if (want_original) {
@ -730,27 +686,24 @@ static pixman_image_t *canvas_bitmap_to_surface(CanvasBase *canvas, SpiceBitmap*
#ifdef SW_CANVAS_CACHE #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; SpicePalette *palette;
if (!base_palette) {
return NULL;
}
if (flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE) { if (flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE) {
palette = canvas->palette_cache->ops->get(canvas->palette_cache, base_palette); palette = canvas->palette_cache->ops->get(canvas->palette_cache, palette_id);
} 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);
} else { } 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; 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; SpicePalette *copy;
uint32_t *now, *end; uint32_t *now, *end;
size_t size; size_t size;
@ -784,7 +737,7 @@ static inline SpicePalette *canvas_get_localized_palette(CanvasBase *canvas, SPI
return copy; 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) int want_original)
{ {
LzData *lz_data = &canvas->lz_data; 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; free_palette = FALSE;
if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB) { if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB) {
comp_buf = image->lz_rgb.data; ASSERT(image->u.lz_rgb.data->num_chunks == 1); /* TODO: Handle chunks */
comp_size = image->lz_rgb.data_size; comp_buf = image->u.lz_rgb.data->chunk[0].data;
comp_size = image->u.lz_rgb.data->chunk[0].len;
palette = NULL; palette = NULL;
} else if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) { } else if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) {
comp_buf = image->lz_plt.data; ASSERT(image->u.lz_plt.data->num_chunks == 1); /* TODO: Handle chunks */
comp_size = image->lz_plt.data_size; comp_buf = image->u.lz_plt.data->chunk[0].data;
palette = canvas_get_localized_palette(canvas, image->lz_plt.palette, image->lz_plt.flags, &free_palette); 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 { } else {
CANVAS_ERROR("unexpected image type"); 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 // 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) // 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) int want_original)
{ {
ASSERT(image->descriptor.type == SPICE_IMAGE_TYPE_GLZ_RGB); 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; canvas->glz_data.decode_data.dc = canvas->dc;
#endif #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) int want_original)
{ {
uint8_t *glz_data; 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"); CANVAS_ERROR("zlib not supported");
} }
glz_data = (uint8_t*)spice_malloc(image->zlib_glz.glz_data_size); ASSERT(image->u.zlib_glz.data->num_chunks == 1); /* TODO: Handle chunks */
canvas->zlib->ops->decode(canvas->zlib, image->zlib_glz.data, image->zlib_glz.data_size, glz_data = (uint8_t*)spice_malloc(image->u.zlib_glz.glz_data_size);
glz_data, image->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); surface = canvas_get_glz_rgb_common(canvas, glz_data, want_original);
free(glz_data); free(glz_data);
return surface; return surface;
@ -993,7 +951,7 @@ static pixman_image_t *canvas_get_bits(CanvasBase *canvas, SpiceBitmap *bitmap,
pixman_image_t* surface; pixman_image_t* surface;
SpicePalette *palette; 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 #ifdef DEBUG_DUMP_BITMAP
if (palette) { if (palette) {
dump_bitmap(bitmap, palette); dump_bitmap(bitmap, palette);
@ -1079,26 +1037,20 @@ static void dump_surface(pixman_image_t *surface, int cache)
#endif #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 (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) {
SpiceSurface *surface = &image->u.surface;
if (descriptor->type == SPICE_IMAGE_TYPE_SURFACE) { return canvas->surfaces->ops->get(canvas->surfaces, surface->surface_id);
SpiceSurfaceImage *surface = (SpiceSurfaceImage *)descriptor;
return canvas->surfaces->ops->get(canvas->surfaces, surface->surface.surface_id);
} }
return NULL; 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; if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) {
SpiceSurface *surface = &image->u.surface;
descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr); return canvas->surfaces->ops->get(canvas->surfaces, surface->surface_id);
if (descriptor->type == SPICE_IMAGE_TYPE_SURFACE) {
SpiceSurfaceImage *surface = (SpiceSurfaceImage *)descriptor;
return canvas->surfaces->ops->get(canvas->surfaces, surface->surface.surface_id);
} }
return NULL; 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 * 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. * 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) int want_original, int real_get)
{ {
SpiceImageDescriptor *descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr); SpiceImageDescriptor *descriptor = &image->descriptor;
pixman_image_t *surface, *converted; pixman_image_t *surface, *converted;
pixman_format_code_t wanted_format, surface_format; pixman_format_code_t wanted_format, surface_format;
int saved_want_original; int saved_want_original;
@ -1150,40 +1102,33 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
switch (descriptor->type) { switch (descriptor->type) {
case SPICE_IMAGE_TYPE_QUIC: { case SPICE_IMAGE_TYPE_QUIC: {
SpiceQUICImage *image = (SpiceQUICImage *)descriptor;
surface = canvas_get_quic(canvas, image, 0, want_original); surface = canvas_get_quic(canvas, image, 0, want_original);
break; break;
} }
#ifdef SW_CANVAS_NO_CHUNKS #if defined(SW_CANVAS_CACHE)
case SPICE_IMAGE_TYPE_LZ_PLT: { case SPICE_IMAGE_TYPE_LZ_PLT: {
LZImage *image = (LZImage *)descriptor;
surface = canvas_get_lz(canvas, image, 0, want_original); surface = canvas_get_lz(canvas, image, 0, want_original);
break; break;
} }
case SPICE_IMAGE_TYPE_LZ_RGB: { case SPICE_IMAGE_TYPE_LZ_RGB: {
LZImage *image = (LZImage *)descriptor;
surface = canvas_get_lz(canvas, image, 0, want_original); surface = canvas_get_lz(canvas, image, 0, want_original);
break; break;
} }
#endif #endif
case SPICE_IMAGE_TYPE_JPEG: { case SPICE_IMAGE_TYPE_JPEG: {
SpiceJPEGImage *image = (SpiceJPEGImage *)descriptor;
surface = canvas_get_jpeg(canvas, image, 0); surface = canvas_get_jpeg(canvas, image, 0);
break; break;
} }
case SPICE_IMAGE_TYPE_JPEG_ALPHA: { case SPICE_IMAGE_TYPE_JPEG_ALPHA: {
SpiceJPEGAlphaImage *image = (SpiceJPEGAlphaImage *)descriptor;
surface = canvas_get_jpeg_alpha(canvas, image, 0); surface = canvas_get_jpeg_alpha(canvas, image, 0);
break; break;
} }
#if defined(SW_CANVAS_CACHE) #if defined(SW_CANVAS_CACHE)
case SPICE_IMAGE_TYPE_GLZ_RGB: { case SPICE_IMAGE_TYPE_GLZ_RGB: {
LZImage *image = (LZImage *)descriptor;
surface = canvas_get_glz(canvas, image, want_original); surface = canvas_get_glz(canvas, image, want_original);
break; break;
} }
case SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB: { case SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB: {
SpiceZlibGlzRGBImage *image = (SpiceZlibGlzRGBImage *)descriptor;
surface = canvas_get_zlib_glz_rgb(canvas, image, want_original); surface = canvas_get_zlib_glz_rgb(canvas, image, want_original);
break; break;
} }
@ -1197,8 +1142,7 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
break; break;
#endif #endif
case SPICE_IMAGE_TYPE_BITMAP: { case SPICE_IMAGE_TYPE_BITMAP: {
SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor; surface = canvas_get_bits(canvas, &image->u.bitmap, want_original);
surface = canvas_get_bits(canvas, &bitmap->bitmap, want_original);
break; break;
} }
default: default:
@ -1298,10 +1242,10 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
#else #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) int want_original, int real_get)
{ {
SpiceImageDescriptor *descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr); SpiceImageDescriptor *descriptor = &image->descriptor;
pixman_format_code_t format; pixman_format_code_t format;
/* When touching, never load image. */ /* When touching, never load image. */
@ -1311,12 +1255,10 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
switch (descriptor->type) { switch (descriptor->type) {
case SPICE_IMAGE_TYPE_QUIC: { case SPICE_IMAGE_TYPE_QUIC: {
SpiceQUICImage *image = (SpiceQUICImage *)descriptor;
return canvas_get_quic(canvas, image, 0); return canvas_get_quic(canvas, image, 0);
} }
case SPICE_IMAGE_TYPE_BITMAP: { case SPICE_IMAGE_TYPE_BITMAP: {
SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor; return canvas_get_bits(canvas, &image->u.bitmap, want_original, &format);
return canvas_get_bits(canvas, &bitmap->bitmap, want_original, &format);
} }
default: default:
CANVAS_ERROR("invalid image type"); CANVAS_ERROR("invalid image type");
@ -1325,25 +1267,25 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
#endif #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) 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, 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"); 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; src_stride = bitmap->stride;
end_line = src_line + (bitmap->y * src_stride); end_line = src_line + (bitmap->y * src_stride);
line_size = SPICE_ALIGN(bitmap->x, 8) >> 3; 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) static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int *needs_invert_out)
{ {
SpiceImageDescriptor *descriptor; SpiceImage *image;
pixman_image_t *surface; pixman_image_t *surface;
int need_invers; int need_invers;
int is_invers; int is_invers;
@ -1540,31 +1483,30 @@ static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int
*needs_invert_out = 0; *needs_invert_out = 0;
} }
descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(mask->bitmap); image = mask->bitmap;
need_invers = mask->flags & SPICE_MASK_FLAGS_INVERS; need_invers = mask->flags & SPICE_MASK_FLAGS_INVERS;
#ifdef SW_CANVAS_CACHE #ifdef SW_CANVAS_CACHE
cache_me = descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME; cache_me = image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME;
#else #else
cache_me = 0; cache_me = 0;
#endif #endif
switch (descriptor->type) { switch (image->descriptor.type) {
case SPICE_IMAGE_TYPE_BITMAP: { case SPICE_IMAGE_TYPE_BITMAP: {
SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor;
is_invers = need_invers && !cache_me; 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; break;
} }
#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE) #if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
case SPICE_IMAGE_TYPE_FROM_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; is_invers = 0;
break; break;
#endif #endif
#ifdef SW_CANVAS_CACHE #ifdef SW_CANVAS_CACHE
case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS: 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; is_invers = 0;
break; break;
#endif #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 defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
if (cache_me) { 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 if (need_invers && !is_invers) { // surface is in cache
@ -1847,13 +1789,6 @@ static void quic_usr_free(QuicUsrContext *usr, void *ptr)
free(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, ...) static void lz_usr_warn(LzUsrContext *usr, const char *fmt, ...)
{ {
LzData *usr_data = (LzData *)usr; LzData *usr_data = (LzData *)usr;
@ -1896,29 +1831,19 @@ static int lz_usr_more_lines(LzUsrContext *usr, uint8_t **lines)
return 0; return 0;
} }
#else
static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed) static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed)
{ {
QuicData *quic_data = (QuicData *)usr; 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; return 0;
} }
chunk = (DataChunk *)quic_data->virt_mapping->ops->get_virt(quic_data->virt_mapping, quic_data->next, quic_data->current_chunk++;
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->next = chunk->next; *io_ptr = (uint32_t *)quic_data->chunks->chunk[quic_data->current_chunk].data;
*io_ptr = (uint32_t *)chunk->data; return quic_data->chunks->chunk[quic_data->current_chunk].len >> 2;
return size >> 2;
} }
#endif
static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines) 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) static void canvas_base_destroy(CanvasBase *canvas)
{ {
quic_destroy(canvas->quic_data.quic); quic_destroy(canvas->quic_data.quic);
#ifdef SW_CANVAS_NO_CHUNKS
lz_destroy(canvas->lz_data.lz); lz_destroy(canvas->lz_data.lz);
#endif
#ifdef GDI_CANVAS #ifdef GDI_CANVAS
DeleteDC(canvas->dc); DeleteDC(canvas->dc);
#endif #endif
@ -3398,9 +3321,6 @@ static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops,
, SpiceGlzDecoder *glz_decoder , SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder , SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder , SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
) )
{ {
canvas->parent.ops = ops; 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.free = quic_usr_free;
canvas->quic_data.usr.more_space = quic_usr_more_space; canvas->quic_data.usr.more_space = quic_usr_more_space;
canvas->quic_data.usr.more_lines = quic_usr_more_lines; 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))) { if (!(canvas->quic_data.quic = quic_create(&canvas->quic_data.usr))) {
return 0; return 0;
} }
#ifdef SW_CANVAS_NO_CHUNKS
canvas->lz_data.usr.error = lz_usr_error; canvas->lz_data.usr.error = lz_usr_error;
canvas->lz_data.usr.warn = lz_usr_warn; canvas->lz_data.usr.warn = lz_usr_warn;
canvas->lz_data.usr.info = 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))) { if (!(canvas->lz_data.lz = lz_create(&canvas->lz_data.usr))) {
return 0; return 0;
} }
#endif
canvas->surfaces = surfaces; canvas->surfaces = surfaces;
canvas->glz_data.decoder = glz_decoder; canvas->glz_data.decoder = glz_decoder;
canvas->jpeg = jpeg_decoder; canvas->jpeg = jpeg_decoder;

View File

@ -33,7 +33,6 @@ typedef struct _SpicePaletteCache SpicePaletteCache;
typedef struct _SpiceGlzDecoder SpiceGlzDecoder; typedef struct _SpiceGlzDecoder SpiceGlzDecoder;
typedef struct _SpiceJpegDecoder SpiceJpegDecoder; typedef struct _SpiceJpegDecoder SpiceJpegDecoder;
typedef struct _SpiceZlibDecoder SpiceZlibDecoder; typedef struct _SpiceZlibDecoder SpiceZlibDecoder;
typedef struct _SpiceVirtMapping SpiceVirtMapping;
typedef struct _SpiceCanvas SpiceCanvas; typedef struct _SpiceCanvas SpiceCanvas;
typedef struct { typedef struct {
@ -120,16 +119,6 @@ struct _SpiceZlibDecoder {
SpiceZlibDecoderOps *ops; SpiceZlibDecoderOps *ops;
}; };
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 { typedef struct {
void (*draw_fill)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill); void (*draw_fill)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill);
void (*draw_copy)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy); void (*draw_copy)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy);

View File

@ -806,9 +806,6 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
, SpiceGlzDecoder *glz_decoder , SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder , SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder , SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
) )
{ {
GLCanvas *canvas; GLCanvas *canvas;
@ -835,9 +832,6 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
, glz_decoder , glz_decoder
, jpeg_decoder , jpeg_decoder
, zlib_decoder , zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, virt_mapping
#endif
); );
if (!init_ok) { if (!init_ok) {
goto error_2; goto error_2;

View File

@ -32,9 +32,6 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
, SpiceGlzDecoder *glz_decoder , SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder , SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_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_set_textures_lost(SpiceCanvas *canvas, int textures_lost);
void gl_canvas_init(); void gl_canvas_init();

View File

@ -1173,9 +1173,6 @@ static SpiceCanvas *canvas_create_common(pixman_image_t *image,
, SpiceGlzDecoder *glz_decoder , SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder , SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder , SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
) )
{ {
SwCanvas *canvas; SwCanvas *canvas;
@ -1202,9 +1199,6 @@ static SpiceCanvas *canvas_create_common(pixman_image_t *image,
, glz_decoder , glz_decoder
, jpeg_decoder , jpeg_decoder
, zlib_decoder , zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, virt_mapping
#endif
); );
canvas->private_data = NULL; canvas->private_data = NULL;
canvas->private_data_size = 0; canvas->private_data_size = 0;
@ -1225,9 +1219,6 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format
, SpiceGlzDecoder *glz_decoder , SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder , SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder , SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
) )
{ {
pixman_image_t *image; pixman_image_t *image;
@ -1246,9 +1237,6 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format
, glz_decoder , glz_decoder
, jpeg_decoder , jpeg_decoder
, zlib_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 , SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder , SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder , SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
) )
{ {
pixman_image_t *image; pixman_image_t *image;
@ -1285,9 +1270,6 @@ SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format,
, glz_decoder , glz_decoder
, jpeg_decoder , jpeg_decoder
, zlib_decoder , zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, virt_mapping
#endif
); );
} }

View File

@ -37,9 +37,6 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format
, SpiceGlzDecoder *glz_decoder , SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder , SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_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 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 , SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder , SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder , SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
); );

View File

@ -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.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size"))
writer.error_check("pos + %s > message_end" % m.member_type.get_fixed_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): if not scope.variable_defined(var):
scope.variable_def(m.member_type.c_type(), var) scope.variable_def(m.member_type.c_type(), var)
writer.assign(var, "read_%s(pos)" % (m.member_type.primitive_type())) 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()) assert(item.type.is_primitive())
writer.assign("pos", item.get_position()) writer.assign("pos", item.get_position())
writer.error_check("pos + %s > message_end" % item.type.get_fixed_nw_size()) 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) scope.variable_def(item.type.c_type(), var)
writer.assign(var, "read_%s(pos)" % (item.type.primitive_type())) writer.assign(var, "read_%s(pos)" % (item.type.primitive_type()))
return var return var

View File

@ -811,14 +811,31 @@ class ContainerType(Type):
return str(fixed) return str(fixed)
def lookup_member(self, name): 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): if self.members_by_name.has_key(name):
return self.members_by_name[name] member = self.members_by_name[name]
for m in self.members: else:
if m.is_switch(): for m in self.members:
member = m.lookup_case_member(name) if m.is_switch():
if member: member = m.lookup_case_member(name)
return member if member != None:
raise Exception, "No member called %s found" % name 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): class StructType(ContainerType):
def __init__(self, name, members, attribute_list): def __init__(self, name, members, attribute_list):

View File

@ -95,7 +95,7 @@ def SPICE_BNF():
switchCase = Group(Group(OneOrMore(default_.setParseAction(replaceWith(None)) + colon | case_.suppress() + identifier + colon)) + variableDef) \ 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])) .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])) .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) 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])) structSpec = Group(struct_ + identifier + structBody + attributes).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3]))

View File

@ -17,6 +17,7 @@
*/ */
#include <stdbool.h> #include <stdbool.h>
#include <inttypes.h>
#include "red_common.h" #include "red_common.h"
#include "red_memslots.h" #include "red_memslots.h"
#include "red_parse_qxl.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; return data_size;
} }
#if 0
static size_t red_get_data_chunks(RedMemSlotInfo *slots, int group_id, static size_t red_get_data_chunks(RedMemSlotInfo *slots, int group_id,
RedDataChunk *red, SPICE_ADDRESS addr) 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); qxl = (QXLDataChunk*)get_virt(slots, addr, sizeof(*qxl), group_id);
return red_get_data_chunks_ptr(slots, group_id, memslot_id, red, qxl); return red_get_data_chunks_ptr(slots, group_id, memslot_id, red, qxl);
} }
#endif
static void red_put_data_chunks(RedDataChunk *red) 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; 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, static void red_get_brush_ptr(RedMemSlotInfo *slots, int group_id,
SpiceBrush *red, QXLBrush *qxl) 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; red->u.color = qxl->u.color;
break; break;
case SPICE_BRUSH_TYPE_PATTERN: 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); red_get_point_ptr(&red->u.pattern.pos, &qxl->u.pattern.pos);
break; 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, static void red_get_qmask_ptr(RedMemSlotInfo *slots, int group_id,
SpiceQMask *red, QXLQMask *qxl) SpiceQMask *red, QXLQMask *qxl)
{ {
red->flags = qxl->flags; red->flags = qxl->flags;
red_get_point_ptr(&red->pos, &qxl->pos); 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, 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); 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, static void red_get_opaque_ptr(RedMemSlotInfo *slots, int group_id,
SpiceOpaque *red, QXLOpaque *qxl) 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_rect_ptr(&red->src_area, &qxl->src_area);
red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush); red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush);
red->rop_descriptor = qxl->rop_descriptor; 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); 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, static void red_get_copy_ptr(RedMemSlotInfo *slots, int group_id,
SpiceCopy *red, QXLCopy *qxl) 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_get_rect_ptr(&red->src_area, &qxl->src_area);
red->rop_descriptor = qxl->rop_descriptor; red->rop_descriptor = qxl->rop_descriptor;
red->scale_mode = qxl->scale_mode; red->scale_mode = qxl->scale_mode;
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); 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, static void red_get_blend_ptr(RedMemSlotInfo *slots, int group_id,
SpiceBlend *red, QXLBlend *qxl) 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_get_rect_ptr(&red->src_area, &qxl->src_area);
red->rop_descriptor = qxl->rop_descriptor; red->rop_descriptor = qxl->rop_descriptor;
red->scale_mode = qxl->scale_mode; red->scale_mode = qxl->scale_mode;
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); 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, static void red_get_transparent_ptr(RedMemSlotInfo *slots, int group_id,
SpiceTransparent *red, QXLTransparent *qxl) 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_get_rect_ptr(&red->src_area, &qxl->src_area);
red->src_color = qxl->src_color; red->src_color = qxl->src_color;
red->true_color = qxl->true_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, static void red_get_alpha_blend_ptr(RedMemSlotInfo *slots, int group_id,
SpiceAlphaBlnd *red, QXLAlphaBlnd *qxl) SpiceAlphaBlnd *red, QXLAlphaBlnd *qxl)
{ {
red->alpha_flags = qxl->alpha_flags; red->alpha_flags = qxl->alpha_flags;
red->alpha = qxl->alpha; 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); 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) SpiceAlphaBlnd *red, QXLCompatAlphaBlnd *qxl)
{ {
red->alpha = qxl->alpha; 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); 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, static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id,
SpiceRop3 *red, QXLRop3 *qxl) 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_rect_ptr(&red->src_area, &qxl->src_area);
red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush); red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush);
red->rop3 = qxl->rop3; 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); 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, static void red_get_stroke_ptr(RedMemSlotInfo *slots, int group_id,
SpiceStroke *red, QXLStroke *qxl) 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; 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); 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) static void red_put_text_ptr(SpiceText *red)
{ {
free(red->str); 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, 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); 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, static void red_get_blackness_ptr(RedMemSlotInfo *slots, int group_id,
SpiceBlackness *red, QXLBlackness *qxl) SpiceBlackness *red, QXLBlackness *qxl)
{ {
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); 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, static void red_get_invers_ptr(RedMemSlotInfo *slots, int group_id,
SpiceInvers *red, QXLInvers *qxl) SpiceInvers *red, QXLInvers *qxl)
{ {
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask); 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, static void red_get_clip_ptr(RedMemSlotInfo *slots, int group_id,
SpiceClip *red, QXLClip *qxl) 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); red_get_whiteness_ptr(slots, group_id, &red->u.whiteness, &qxl->u.whiteness);
break; break;
default: default:
red_error("unknown type"); red_error("%s: unknown type %d", __FUNCTION__, red->type);
break; 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); red_get_whiteness_ptr(slots, group_id, &red->u.whiteness, &qxl->u.whiteness);
break; break;
default: default:
red_error("unknown type"); red_error("%s: unknown type %d", __FUNCTION__, red->type);
break; break;
}; };
} }
@ -646,12 +864,42 @@ void red_put_drawable(RedDrawable *red)
{ {
red_put_clip(&red->clip); red_put_clip(&red->clip);
switch (red->type) { 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: case QXL_DRAW_STROKE:
red_put_stroke_ptr(&red->u.stroke); red_put_stroke(&red->u.stroke);
break; break;
case QXL_DRAW_TEXT: case QXL_DRAW_TEXT:
red_put_text_ptr(&red->u.text); red_put_text_ptr(&red->u.text);
break; break;
case QXL_DRAW_TRANSPARENT:
red_put_transparent(&red->u.transparent);
break;
case QXL_DRAW_WHITENESS:
red_put_whiteness(&red->u.whiteness);
break;
} }
} }

View File

@ -118,6 +118,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id, void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
RedDrawable *red, SPICE_ADDRESS addr); RedDrawable *red, SPICE_ADDRESS addr);
void red_put_drawable(RedDrawable *red); void red_put_drawable(RedDrawable *red);
void red_put_image(SpiceImage *red);
void red_get_update_cmd(RedMemSlotInfo *slots, int group_id, void red_get_update_cmd(RedMemSlotInfo *slots, int group_id,
RedUpdateCmd *red, SPICE_ADDRESS addr); RedUpdateCmd *red, SPICE_ADDRESS addr);

File diff suppressed because it is too large Load Diff

View File

@ -111,7 +111,7 @@ channel BaseChannel {
message { message {
uint32 id; uint32 id;
uint64 timestamp; uint64 timestamp;
uint8 data[] @end @ctype(uint8_t) @as_ptr(data_len); uint8 data[] @ctype(uint8_t) @as_ptr(data_len);
} ping; } ping;
message { message {
@ -435,16 +435,16 @@ struct BitmapData {
uint32 stride; uint32 stride;
switch (flags) { switch (flags) {
case PAL_FROM_CACHE: case PAL_FROM_CACHE:
uint64 palette; uint64 palette_id;
default: default:
Palette *palette @outvar(bitmap); Palette *palette @outvar(bitmap) @c_ptr;
} pal @anon; } 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); } @ctype(SpiceBitmap);
struct BinaryData { struct BinaryData {
uint32 data_size; uint32 data_size;
uint8 data[data_size] @end @nomarshal; uint8 data[data_size] @nomarshal @chunk;
} @ctype(SpiceQUICData); } @ctype(SpiceQUICData);
struct LZPLTData { struct LZPLTData {
@ -452,58 +452,63 @@ struct LZPLTData {
uint32 data_size; uint32 data_size;
switch (flags) { switch (flags) {
case PAL_FROM_CACHE: case PAL_FROM_CACHE:
uint64 palette; uint64 palette_id;
default: default:
Palette *palette @nonnull @outvar(lzplt); Palette *palette @nonnull @outvar(lzplt) @c_ptr;
} pal @anon; } pal @anon;
uint8 data[data_size] @end @nomarshal; uint8 data[data_size] @nomarshal @chunk;
}; };
struct ZlibGlzRGBData { struct ZlibGlzRGBData {
uint32 glz_data_size; uint32 glz_data_size;
uint32 data_size; uint32 data_size;
uint8 data[data_size] @end @nomarshal; uint8 data[data_size] @nomarshal @chunk;
} @ctype(SpiceZlibGlzRGBData); } @ctype(SpiceZlibGlzRGBData);
struct JPEGAlphaData { struct JPEGAlphaData {
jpeg_alpha_flags flags; jpeg_alpha_flags flags;
uint32 jpeg_size; uint32 jpeg_size;
uint32 data_size; uint32 data_size;
uint8 data[data_size] @end @nomarshal; uint8 data[data_size] @nomarshal @chunk;
} @ctype(SpiceJPEGAlphaData); } @ctype(SpiceJPEGAlphaData);
struct Surface { struct Surface {
uint32 surface_id; 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: case BITMAP:
BitmapData bitmap_data @ctype(SpiceBitmap); BitmapData bitmap;
case QUIC: case QUIC:
BinaryData quic;
case LZ_RGB: case LZ_RGB:
case GLZ_RGB: case GLZ_RGB:
BinaryData lz_rgb;
case JPEG: case JPEG:
BinaryData binary_data @ctype(SpiceQUICData); BinaryData jpeg;
case LZ_PLT: case LZ_PLT:
LZPLTData lzplt_data @ctype(SpiceLZPLTData); LZPLTData lz_plt;
case ZLIB_GLZ_RGB: case ZLIB_GLZ_RGB:
ZlibGlzRGBData zlib_glz_data @ctype(SpiceZlibGlzRGBData); ZlibGlzRGBData zlib_glz;
case JPEG_ALPHA: case JPEG_ALPHA:
JPEGAlphaData jpeg_alpha_data @ctype(SpiceJPEGAlphaData); JPEGAlphaData jpeg_alpha;
case SURFACE: case SURFACE:
Surface surface_data; Surface surface;
} u @end; } u;
} @ctype(SpiceImageDescriptor); };
struct Pattern { struct Pattern {
Image *pat @nonnull; Image *pat @nonnull @c_ptr;
Point pos; Point pos;
}; };
@ -520,7 +525,7 @@ struct Brush {
struct QMask { struct QMask {
mask_flags flags; mask_flags flags;
Point pos; Point pos;
Image *bitmap; Image *bitmap @c_ptr;
}; };
struct LineAttr { struct LineAttr {
@ -649,7 +654,7 @@ channel DisplayChannel : BaseChannel {
message { message {
DisplayBase base; DisplayBase base;
struct Opaque { struct Opaque {
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
Brush brush; Brush brush;
ropd rop_descriptor; ropd rop_descriptor;
@ -661,7 +666,7 @@ channel DisplayChannel : BaseChannel {
message { message {
DisplayBase base; DisplayBase base;
struct Copy { struct Copy {
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
ropd rop_descriptor; ropd rop_descriptor;
image_scale_mode scale_mode; image_scale_mode scale_mode;
@ -672,7 +677,7 @@ channel DisplayChannel : BaseChannel {
message { message {
DisplayBase base; DisplayBase base;
struct Blend { struct Blend {
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
ropd rop_descriptor; ropd rop_descriptor;
image_scale_mode scale_mode; image_scale_mode scale_mode;
@ -704,7 +709,7 @@ channel DisplayChannel : BaseChannel {
message { message {
DisplayBase base; DisplayBase base;
struct Rop3 { struct Rop3 {
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
Brush brush; Brush brush;
uint8 rop3; uint8 rop3;
@ -739,7 +744,7 @@ channel DisplayChannel : BaseChannel {
message { message {
DisplayBase base; DisplayBase base;
struct Transparent { struct Transparent {
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
uint32 src_color; uint32 src_color;
uint32 true_color; uint32 true_color;
@ -751,7 +756,7 @@ channel DisplayChannel : BaseChannel {
struct AlphaBlnd { struct AlphaBlnd {
alpha_flags alpha_flags; alpha_flags alpha_flags;
uint8 alpha; uint8 alpha;
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
} data; } data;
} draw_alpha_blend; } draw_alpha_blend;
@ -875,7 +880,7 @@ struct CursorHeader {
struct Cursor { struct Cursor {
cursor_flags flags; cursor_flags flags;
CursorHeader header; CursorHeader header;
uint8 data[] @end @as_ptr(data_size); uint8 data[] @as_ptr(data_size);
}; };
channel CursorChannel : BaseChannel { channel CursorChannel : BaseChannel {
@ -929,13 +934,13 @@ channel PlaybackChannel : BaseChannel {
server: server:
message { message {
uint32 time; uint32 time;
uint8 data[] @end @as_ptr(data_size); uint8 data[] @as_ptr(data_size);
} @ctype(SpiceMsgPlaybackPacket) data = 101; } @ctype(SpiceMsgPlaybackPacket) data = 101;
message { message {
uint32 time; uint32 time;
audio_data_mode mode; audio_data_mode mode;
uint8 data[] @end @as_ptr(data_size); uint8 data[] @as_ptr(data_size);
} mode; } mode;
message { message {
@ -960,13 +965,13 @@ channel RecordChannel : BaseChannel {
client: client:
message { message {
uint32 time; uint32 time;
uint8 data[] @end @nomarshal @as_ptr(data_size); uint8 data[] @nomarshal @as_ptr(data_size);
} @ctype(SpiceMsgcRecordPacket) data = 101; } @ctype(SpiceMsgcRecordPacket) data = 101;
message { message {
uint32 time; uint32 time;
audio_data_mode mode; audio_data_mode mode;
uint8 data[] @end @as_ptr(data_size); uint8 data[] @as_ptr(data_size);
} mode; } mode;
message { message {

View File

@ -111,7 +111,7 @@ channel BaseChannel {
message { message {
uint32 id; uint32 id;
uint64 timestamp; uint64 timestamp;
uint8 data[] @end @ctype(uint8_t) @as_ptr(data_len); uint8 data[] @ctype(uint8_t) @as_ptr(data_len);
} ping; } ping;
message { message {
@ -419,16 +419,16 @@ struct BitmapData {
uint32 stride; uint32 stride;
switch (flags) { switch (flags) {
case PAL_FROM_CACHE: case PAL_FROM_CACHE:
uint64 palette; uint64 palette_id;
default: default:
Palette *palette @outvar(bitmap); Palette *palette @outvar(bitmap) @c_ptr;
} pal @anon; } 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); } @ctype(SpiceBitmap);
struct BinaryData { struct BinaryData {
uint32 data_size; uint32 data_size;
uint8 data[data_size] @end @nomarshal; uint8 data[data_size] @nomarshal @chunk;
} @ctype(SpiceQUICData); } @ctype(SpiceQUICData);
struct LZPLTData { struct LZPLTData {
@ -436,34 +436,37 @@ struct LZPLTData {
uint32 data_size; uint32 data_size;
switch (flags) { switch (flags) {
case PAL_FROM_CACHE: case PAL_FROM_CACHE:
uint64 palette; uint64 palette_id;
default: default:
Palette *palette @nonnull @outvar(lzplt); Palette *palette @nonnull @outvar(lzplt) @c_ptr;
} pal @anon; } pal @anon;
uint8 data[data_size] @end @nomarshal; uint8 data[data_size] @nomarshal @chunk;
}; };
struct Image { struct Image {
uint64 id; struct ImageDescriptor {
image_type type; uint64 id;
image_flags flags; image_type type;
uint32 width; image_flags flags;
uint32 height; uint32 width;
uint32 height;
} descriptor;
switch (type) { switch (descriptor.type) {
case BITMAP: case BITMAP:
BitmapData bitmap_data @ctype(SpiceBitmap); BitmapData bitmap;
case QUIC: case QUIC:
BinaryData quic;
case LZ_RGB: case LZ_RGB:
case GLZ_RGB: case GLZ_RGB:
BinaryData binary_data @ctype(SpiceQUICData); BinaryData lz_rgb;
case LZ_PLT: case LZ_PLT:
LZPLTData lzplt_data @ctype(SpiceLZPLTData); LZPLTData lz_plt;
} u @end; } u;
} @ctype(SpiceImageDescriptor); };
struct Pattern { struct Pattern {
Image *pat @nonnull; Image *pat @nonnull @c_ptr;
Point pos; Point pos;
}; };
@ -480,7 +483,7 @@ struct Brush {
struct QMask { struct QMask {
mask_flags flags; mask_flags flags;
Point pos; Point pos;
Image *bitmap; Image *bitmap @c_ptr;
}; };
struct LineAttr { struct LineAttr {
@ -608,7 +611,7 @@ channel DisplayChannel : BaseChannel {
message { message {
DisplayBase base; DisplayBase base;
struct Opaque { struct Opaque {
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
Brush brush; Brush brush;
ropd rop_descriptor; ropd rop_descriptor;
@ -620,7 +623,7 @@ channel DisplayChannel : BaseChannel {
message { message {
DisplayBase base; DisplayBase base;
struct Copy { struct Copy {
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
ropd rop_descriptor; ropd rop_descriptor;
image_scale_mode scale_mode; image_scale_mode scale_mode;
@ -631,7 +634,7 @@ channel DisplayChannel : BaseChannel {
message { message {
DisplayBase base; DisplayBase base;
struct Blend { struct Blend {
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
ropd rop_descriptor; ropd rop_descriptor;
image_scale_mode scale_mode; image_scale_mode scale_mode;
@ -663,7 +666,7 @@ channel DisplayChannel : BaseChannel {
message { message {
DisplayBase base; DisplayBase base;
struct Rop3 { struct Rop3 {
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
Brush brush; Brush brush;
uint8 rop3; uint8 rop3;
@ -698,7 +701,7 @@ channel DisplayChannel : BaseChannel {
message { message {
DisplayBase base; DisplayBase base;
struct Transparent { struct Transparent {
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
uint32 src_color; uint32 src_color;
uint32 true_color; uint32 true_color;
@ -710,7 +713,7 @@ channel DisplayChannel : BaseChannel {
struct AlphaBlnd { struct AlphaBlnd {
int8 alpha_flags @virtual(0); int8 alpha_flags @virtual(0);
uint8 alpha; uint8 alpha;
Image *src_bitmap; Image *src_bitmap @c_ptr;
Rect src_area; Rect src_area;
} data; } data;
} draw_alpha_blend; } draw_alpha_blend;
@ -822,7 +825,7 @@ struct CursorHeader {
struct Cursor { struct Cursor {
cursor_flags flags; cursor_flags flags;
CursorHeader header; CursorHeader header;
uint8 data[] @end @as_ptr(data_size); uint8 data[] @as_ptr(data_size);
}; };
channel CursorChannel : BaseChannel { channel CursorChannel : BaseChannel {
@ -876,13 +879,13 @@ channel PlaybackChannel : BaseChannel {
server: server:
message { message {
uint32 time; uint32 time;
uint8 data[] @end @as_ptr(data_size); uint8 data[] @as_ptr(data_size);
} @ctype(SpiceMsgPlaybackPacket) data = 101; } @ctype(SpiceMsgPlaybackPacket) data = 101;
message { message {
uint32 time; uint32 time;
audio_data_mode mode; audio_data_mode mode;
uint8 data[] @end @as_ptr(data_size); uint8 data[] @as_ptr(data_size);
} mode; } mode;
message { message {
@ -907,13 +910,13 @@ channel RecordChannel : BaseChannel {
client: client:
message { message {
uint32 time; uint32 time;
uint8 data[] @end @nomarshal @as_ptr(data_size); uint8 data[] @nomarshal @as_ptr(data_size);
} @ctype(SpiceMsgcRecordPacket) data = 101; } @ctype(SpiceMsgcRecordPacket) data = 101;
message { message {
uint32 time; uint32 time;
audio_data_mode mode; audio_data_mode mode;
uint8 data[] @end @as_ptr(data_size); uint8 data[] @as_ptr(data_size);
} mode; } mode;
message { message {