Add support for A8 images to the LZ routines

This format is needed to add Render support to the X driver, so we
need the ability to compress and decompress it.
This commit is contained in:
Søren Sandmann Pedersen 2012-05-18 17:01:29 -04:00
parent 0c1b6de4ad
commit c0b048ebef
13 changed files with 317 additions and 20 deletions

View File

@ -115,7 +115,7 @@ generated_client_marshallers1.c: $(top_srcdir)/spice1.proto $(MARSHALLERS_DEPS)
generated_server_demarshallers.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS)
$(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --server --include messages.h $< $@ >/dev/null
STRUCTS = -M String -M Rect -M Point -M DisplayBase -M Fill -M Opaque -M Copy -M Blend -M Blackness -M Whiteness -M Invers -M Rop3 -M Stroke -M Text -M Transparent -M AlphaBlend
STRUCTS = -M String -M Rect -M Point -M DisplayBase -M Fill -M Opaque -M Copy -M Blend -M Blackness -M Whiteness -M Invers -M Rop3 -M Stroke -M Text -M Transparent -M AlphaBlend -M Composite
generated_server_marshallers.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS)
$(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --server --include messages.h $< $@ >/dev/null

View File

@ -776,6 +776,10 @@ static pixman_image_t *canvas_get_lz(CanvasBase *canvas, SpiceImage *image, int
as_type = LZ_IMAGE_TYPE_RGB32;
pixman_format = PIXMAN_x8r8g8b8;
break;
case LZ_IMAGE_TYPE_A8:
as_type = LZ_IMAGE_TYPE_A8;
pixman_format = PIXMAN_a8;
break;
case LZ_IMAGE_TYPE_RGB16:
if (!want_original &&
(canvas->format == SPICE_SURFACE_FMT_32_xRGB ||
@ -1271,13 +1275,25 @@ static void canvas_touch_image(CanvasBase *canvas, SpiceImage *image)
static pixman_image_t* canvas_get_image_from_self(SpiceCanvas *canvas,
int x, int y,
int32_t width, int32_t height)
int32_t width, int32_t height,
int force_opaque)
{
CanvasBase *canvas_base = (CanvasBase *)canvas;
pixman_image_t *surface;
uint8_t *dest;
int dest_stride;
SpiceRect area;
pixman_format_code_t format;
format = spice_surface_format_to_pixman (canvas_base->format);
if (force_opaque)
{
/* Set alpha bits of the format to 0 */
format = (pixman_format_code_t)(((uint32_t)format) & ~(0xf << 12));
spice_return_val_if_fail (
pixman_format_supported_destination (format), NULL);
}
surface = pixman_image_create_bits(spice_surface_format_to_pixman (canvas_base->format),
width, height, NULL, 0);
@ -1919,7 +1935,7 @@ static void canvas_mask_pixman(CanvasBase *canvas,
surface_canvas = canvas_get_surface_mask(canvas, mask->bitmap);
if (surface_canvas) {
needs_invert = mask->flags & SPICE_MASK_FLAGS_INVERS;
image = surface_canvas->ops->get_image(surface_canvas);
image = surface_canvas->ops->get_image(surface_canvas, FALSE);
} else {
needs_invert = FALSE;
image = canvas_get_mask(canvas,
@ -3174,10 +3190,10 @@ static void canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox,
width = bbox->right - bbox->left;
heigth = bbox->bottom - bbox->top;
d = canvas_get_image_from_self(spice_canvas, bbox->left, bbox->top, width, heigth);
d = canvas_get_image_from_self(spice_canvas, bbox->left, bbox->top, width, heigth, FALSE);
surface_canvas = canvas_get_surface(canvas, rop3->src_bitmap);
if (surface_canvas) {
s = surface_canvas->ops->get_image(surface_canvas);
s = surface_canvas->ops->get_image(surface_canvas, FALSE);
} else {
s = canvas_get_image(canvas, rop3->src_bitmap, FALSE);
}
@ -3204,7 +3220,7 @@ static void canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox,
_surface_canvas = canvas_get_surface(canvas, rop3->brush.u.pattern.pat);
if (_surface_canvas) {
p = _surface_canvas->ops->get_image(_surface_canvas);
p = _surface_canvas->ops->get_image(_surface_canvas, FALSE);
} else {
p = canvas_get_image(canvas, rop3->brush.u.pattern.pat, FALSE);
}
@ -3228,6 +3244,117 @@ static void canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox,
pixman_region32_fini(&dest_region);
}
static void transform_to_pixman_transform(SpiceTransform *transform,
pixman_transform_t *p)
{
p->matrix[0][0] = transform->t00;
p->matrix[0][1] = transform->t01;
p->matrix[0][2] = transform->t02;
p->matrix[1][0] = transform->t10;
p->matrix[1][1] = transform->t11;
p->matrix[1][2] = transform->t12;
p->matrix[2][0] = 0;
p->matrix[2][1] = 0;
p->matrix[2][2] = pixman_fixed_1;
}
#define MASK(lo, hi) \
(((1U << (hi)) - 1) - (((1U << (lo))) - 1))
#define EXTRACT(v, lo, hi) \
((v & MASK(lo, hi)) >> lo)
static void canvas_draw_composite(SpiceCanvas *spice_canvas, SpiceRect *bbox,
SpiceClip *clip, SpiceComposite *composite)
{
CanvasBase *canvas = (CanvasBase *)spice_canvas;
SpiceCanvas *surface_canvas;
pixman_region32_t dest_region;
pixman_image_t *d;
pixman_image_t *s;
pixman_image_t *m;
pixman_repeat_t src_repeat;
pixman_filter_t src_filter;
pixman_op_t op;
pixman_transform_t transform;
int width, height;
pixman_region32_init_rect(&dest_region,
bbox->left, bbox->top,
bbox->right - bbox->left,
bbox->bottom - bbox->top);
canvas_clip_pixman(canvas, &dest_region, clip);
width = bbox->right - bbox->left;
height = bbox->bottom - bbox->top;
/* Dest */
d = canvas_get_image_from_self(spice_canvas, bbox->left, bbox->top, width, height,
(composite->flags & SPICE_COMPOSITE_DEST_OPAQUE));
/* Src */
surface_canvas = canvas_get_surface(canvas, composite->src_bitmap);
if (surface_canvas) {
s = surface_canvas->ops->get_image(surface_canvas,
(composite->flags & SPICE_COMPOSITE_SOURCE_OPAQUE));
} else {
s = canvas_get_image(canvas, composite->src_bitmap, FALSE);
}
if (composite->flags & SPICE_COMPOSITE_HAS_SRC_TRANSFORM)
{
transform_to_pixman_transform (&composite->src_transform, &transform);
pixman_image_set_transform (s, &transform);
}
src_filter = (pixman_filter_t) EXTRACT (composite->flags, 8, 11);
src_repeat = (pixman_repeat_t) EXTRACT (composite->flags, 14, 16);
pixman_image_set_filter (s, src_filter, NULL, 0);
pixman_image_set_repeat (s, src_repeat);
/* Mask */
m = NULL;
if (composite->flags & SPICE_COMPOSITE_HAS_MASK) {
pixman_filter_t mask_filter = (pixman_filter_t) EXTRACT (composite->flags, 11, 14);
pixman_repeat_t mask_repeat = (pixman_repeat_t) EXTRACT (composite->flags, 16, 18);
pixman_bool_t component_alpha = EXTRACT (composite->flags, 18, 19);
surface_canvas = canvas_get_surface(canvas, composite->mask_bitmap);
if (surface_canvas) {
m = surface_canvas->ops->get_image(surface_canvas, FALSE);
} else {
m = canvas_get_image(canvas, composite->mask_bitmap, FALSE);
}
if (composite->flags & SPICE_COMPOSITE_HAS_MASK_TRANSFORM) {
transform_to_pixman_transform (&composite->mask_transform, &transform);
pixman_image_set_transform (m, &transform);
}
pixman_image_set_repeat (m, mask_repeat);
pixman_image_set_filter (m, mask_filter, NULL, 0);
pixman_image_set_component_alpha (m, component_alpha);
}
op = (pixman_op_t) EXTRACT (composite->flags, 0, 8);
pixman_image_composite32 (op, s, m, d,
composite->src_origin.x, composite->src_origin.y,
composite->mask_origin.x, composite->mask_origin.y,
0, 0, width, height);
pixman_image_unref(s);
if (m)
pixman_image_unref(m);
spice_canvas->ops->blit_image(spice_canvas, &dest_region, d,
bbox->left,
bbox->top);
pixman_image_unref(d);
pixman_region32_fini(&dest_region);
}
static void canvas_copy_bits(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos)
{
CanvasBase *canvas = (CanvasBase *)spice_canvas;
@ -3315,6 +3442,7 @@ inline static void canvas_base_init_ops(SpiceCanvasOps *ops)
ops->draw_alpha_blend = canvas_draw_alpha_blend;
ops->draw_stroke = canvas_draw_stroke;
ops->draw_rop3 = canvas_draw_rop3;
ops->draw_composite = canvas_draw_composite;
ops->group_start = canvas_base_group_start;
ops->group_end = canvas_base_group_end;
}

View File

@ -133,6 +133,7 @@ typedef struct {
void (*draw_text)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceText *text);
void (*draw_stroke)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceStroke *stroke);
void (*draw_rop3)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceRop3 *rop3);
void (*draw_composite)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceComposite *composite);
void (*draw_blend)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend);
void (*draw_blackness)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness);
void (*draw_whiteness)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness);
@ -306,7 +307,7 @@ typedef struct {
void (*copy_region)(SpiceCanvas *canvas,
pixman_region32_t *dest_region,
int dx, int dy);
pixman_image_t *(*get_image)(SpiceCanvas *canvas);
pixman_image_t *(*get_image)(SpiceCanvas *canvas, int force_opaque);
} SpiceCanvasOps;
void spice_canvas_set_usr_data(SpiceCanvas *canvas, void *data, spice_destroy_fn_t destroy_fn);

View File

@ -223,6 +223,26 @@ typedef struct SpiceRop3 {
SpiceQMask mask;
} SpiceRop3;
/* Given in 16.16 fixed point */
typedef struct SpiceTransform {
uint32_t t00;
uint32_t t01;
uint32_t t02;
uint32_t t10;
uint32_t t11;
uint32_t t12;
} SpiceTransform;
typedef struct SpiceComposite {
uint32_t flags;
SpiceImage *src_bitmap;
SpiceImage *mask_bitmap;
SpiceTransform src_transform;
SpiceTransform mask_transform;
SpicePoint16 src_origin;
SpicePoint16 mask_origin;
} SpiceComposite;
typedef struct SpiceBlackness {
SpiceQMask mask;
} SpiceBlackness, SpiceInvers, SpiceWhiteness;

View File

@ -465,6 +465,13 @@ typedef uint16_t rgb16_pixel_t;
#define TO_RGB32
#include "lz_decompress_tmpl.c"
#define LZ_A8
#include "lz_compress_tmpl.c"
#define LZ_A8
#include "lz_decompress_tmpl.c"
#define LZ_A8
#define TO_RGB32
#include "lz_decompress_tmpl.c"
#define LZ_RGB16
#include "lz_compress_tmpl.c"
@ -514,7 +521,8 @@ int lz_encode(LzContext *lz, LzImageType type, int width, int height, int top_do
}
} else {
if (encoder->stride != width * RGB_BYTES_PER_PIXEL[encoder->type]) {
encoder->usr->error(encoder->usr, "stride != width*bytes_per_pixel (rgb)\n");
encoder->usr->error(encoder->usr, "stride != width*bytes_per_pixel (rgb) %d %d %d\n",
encoder->stride, width, RGB_BYTES_PER_PIXEL[encoder->type]);
}
}
@ -560,6 +568,9 @@ int lz_encode(LzContext *lz, LzImageType type, int width, int height, int top_do
case LZ_IMAGE_TYPE_XXXA:
lz_rgb_alpha_compress(encoder);
break;
case LZ_IMAGE_TYPE_A8:
lz_a8_compress(encoder);
break;
case LZ_IMAGE_TYPE_INVALID:
default:
encoder->usr->error(encoder->usr, "bad image type\n");
@ -709,6 +720,17 @@ void lz_decode(LzContext *lz, LzImageType to_type, uint8_t *buf)
encoder->usr->error(encoder->usr, "unsupported output format\n");
}
break;
case LZ_IMAGE_TYPE_A8:
if (encoder->type == to_type) {
alpha_size = lz_a8_decompress(encoder, (one_byte_pixel_t *)buf, size);
out_size = alpha_size;
} else if (to_type == LZ_IMAGE_TYPE_RGB32) {
alpha_size = lz_a8_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size);
out_size = alpha_size;
} else {
encoder->usr->error(encoder->usr, "unsupported output format\n");
}
break;
case LZ_IMAGE_TYPE_PLT1_LE:
case LZ_IMAGE_TYPE_PLT1_BE:
case LZ_IMAGE_TYPE_PLT4_LE:

View File

@ -44,7 +44,8 @@ typedef enum {
LZ_IMAGE_TYPE_RGB24,
LZ_IMAGE_TYPE_RGB32,
LZ_IMAGE_TYPE_RGBA,
LZ_IMAGE_TYPE_XXXA
LZ_IMAGE_TYPE_XXXA,
LZ_IMAGE_TYPE_A8
} LzImageType;
#define LZ_IMAGE_TYPE_MASK 0x0f
@ -54,7 +55,7 @@ typedef enum {
static const int IS_IMAGE_TYPE_PLT[] = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
static const int IS_IMAGE_TYPE_RGB[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
static const int PLT_PIXELS_PER_BYTE[] = {0, 8, 8, 2, 2, 1};
static const int RGB_BYTES_PER_PIXEL[] = {0, 1, 1, 1, 1, 1, 2, 3, 4, 4, 4};
static const int RGB_BYTES_PER_PIXEL[] = {0, 1, 1, 1, 1, 1, 2, 3, 4, 4, 4, 1};
#define LZ_MAGIC (*(uint32_t *)"LZ ")

View File

@ -71,6 +71,21 @@
}
#endif
#ifdef LZ_A8
#define PIXEL one_byte_pixel_t
#define FNAME(name) lz_a8_##name
#define ENCODE_PIXEL(e, pix) encode(e, (pix).a) // gets the pixel and write only the needed bytes
// from the pixel
#define SAME_PIXEL(pix1, pix2) ((pix1).a == (pix2).a)
#define HASH_FUNC(v, p) { \
v = DJB2_START; \
DJB2_HASH(v, p[0].a); \
DJB2_HASH(v, p[1].a); \
DJB2_HASH(v, p[2].a); \
v &= HASH_MASK; \
}
#endif
#ifdef LZ_RGB_ALPHA
//#undef LZ_RGB_ALPHA
#define PIXEL rgb32_pixel_t
@ -177,7 +192,7 @@ static void FNAME(compress_seg)(Encoder *encoder, LzImageSegment *seg, PIXEL *fr
size_t distance;
/* minimum match length */
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA)
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_A8)
size_t len = 3;
#elif defined(LZ_RGB16)
size_t len = 2;
@ -234,7 +249,7 @@ static void FNAME(compress_seg)(Encoder *encoder, LzImageSegment *seg, PIXEL *fr
ip++;
/* minimum match length for rgb16 is 2 and for plt and alpha is 3 */
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_RGB16)
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_RGB16) || defined(LZ_A8)
if (!SAME_PIXEL(*ref, *ip)) {
ref++;
ip++;
@ -244,7 +259,7 @@ static void FNAME(compress_seg)(Encoder *encoder, LzImageSegment *seg, PIXEL *fr
ip++;
#endif
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA)
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_A8)
if (!SAME_PIXEL(*ref, *ip)) {
ref++;
ip++;
@ -255,7 +270,7 @@ static void FNAME(compress_seg)(Encoder *encoder, LzImageSegment *seg, PIXEL *fr
#endif
/* far, needs at least 5-byte match */
if (distance >= MAX_DISTANCE) {
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA)
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_A8)
if (ref >= (ref_limit - 1)) {
goto literal;
}
@ -272,7 +287,7 @@ static void FNAME(compress_seg)(Encoder *encoder, LzImageSegment *seg, PIXEL *fr
ref++;
ip++;
len++;
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA)
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_A8)
if (!SAME_PIXEL(*ref, *ip)) {
ref++;
ip++;
@ -464,9 +479,11 @@ static void FNAME(compress)(Encoder *encoder)
LzImageSegment *cur_seg = encoder->head_image_segs;
HashEntry *hslot;
PIXEL *ip;
PIXEL *ip_start;
// fetch the first image segment that is not too small
while (cur_seg && ((((PIXEL *)cur_seg->lines_end) - ((PIXEL *)cur_seg->lines)) < 4)) {
ip_start = cur_seg->lines;
// coping the segment
if (cur_seg->lines != cur_seg->lines_end) {
ip = (PIXEL *)cur_seg->lines;
@ -526,4 +543,5 @@ static void FNAME(compress)(Encoder *encoder)
#undef LZ_RGB16
#undef LZ_RGB24
#undef LZ_RGB32
#undef LZ_A8
#undef HASH_FUNC2

View File

@ -153,6 +153,22 @@
#endif // TO_RGB32
#endif
#ifdef LZ_A8
#ifndef TO_RGB32
#define OUT_PIXEL one_byte_pixel_t
#define FNAME(name) lz_a8_##name
#define COPY_COMP_PIXEL(encoder, out) {out->a = decode(encoder); out++;}
#else // TO_RGB32
#define OUT_PIXEL rgb32_pixel_t
#define FNAME(name) lz_a8_to_rgb32_##name
#define COPY_COMP_PIXEL(encoder, out) { \
(out)->b = (out)->g = (out)->r = 0; \
(out)->pad = decode(encoder); \
(out)++; \
}
#endif
#endif
#ifdef LZ_RGB16
#ifndef TO_RGB32
#define OUT_PIXEL rgb16_pixel_t
@ -237,7 +253,7 @@ static size_t FNAME(decompress)(Encoder *encoder, OUT_PIXEL *out_buf, int size)
}
}
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA)
#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_A8)
len += 3; // length is biased by 2 + 1 (fixing bias)
#elif defined(LZ_RGB16)
len += 2; // length is biased by 1 + 1 (fixing bias)
@ -315,6 +331,7 @@ static size_t FNAME(decompress)(Encoder *encoder, OUT_PIXEL *out_buf, int size)
#undef LZ_RGB16
#undef LZ_RGB24
#undef LZ_RGB32
#undef LZ_A8
#undef LZ_RGB_ALPHA
#undef TO_RGB32
#undef OUT_PIXEL

View File

@ -253,6 +253,11 @@ typedef struct SpiceMsgDisplayDrawAlphaBlend {
SpiceAlphaBlend data;
} SpiceMsgDisplayDrawAlphaBlend;
typedef struct SpiceMsgDisplayDrawComposite {
SpiceMsgDisplayBase base;
SpiceComposite data;
} SpiceMsgDisplayDrawComposite;
typedef struct SpiceMsgDisplayCopyBits {
SpiceMsgDisplayBase base;
SpicePoint src_pos;

View File

@ -963,6 +963,9 @@ pixman_format_code_t spice_bitmap_format_to_pixman(int bitmap_format,
case SPICE_BITMAP_FMT_RGBA:
return PIXMAN_a8r8g8b8;
case SPICE_BITMAP_FMT_8BIT_A:
return PIXMAN_a8;
case SPICE_BITMAP_FMT_INVALID:
default:
printf("Unknown bitmap format %d\n", bitmap_format);
@ -1083,6 +1086,15 @@ static void bitmap_32_to_32(uint8_t* dest, int dest_stride,
#endif
}
static void bitmap_8_to_8(uint8_t* dest, int dest_stride,
uint8_t* src, int src_stride,
int width, uint8_t* end)
{
for (; src != end; src += src_stride, dest += dest_stride) {
memcpy(dest, src, width);
}
}
static void bitmap_24_to_32(uint8_t* dest, int dest_stride,
uint8_t* src, int src_stride,
int width, uint8_t* end)
@ -1477,6 +1489,9 @@ pixman_image_t *spice_bitmap_to_pixman(pixman_image_t *dest_image,
case SPICE_BITMAP_FMT_RGBA:
bitmap_32_to_32(dest, dest_stride, src, src_stride, width, end);
break;
case SPICE_BITMAP_FMT_8BIT_A:
bitmap_8_to_8(dest, dest_stride, src, src_stride, width, end);
break;
case SPICE_BITMAP_FMT_24BIT:
bitmap_24_to_32(dest, dest_stride, src, src_stride, width, end);
break;

View File

@ -85,11 +85,27 @@ static pixman_image_t *canvas_get_pixman_brush(SwCanvas *canvas,
return NULL;
}
static pixman_image_t *get_image(SpiceCanvas *canvas)
static pixman_image_t *get_image(SpiceCanvas *canvas, int force_opaque)
{
SwCanvas *sw_canvas = (SwCanvas *)canvas;
pixman_format_code_t format;
pixman_image_ref(sw_canvas->image);
spice_pixman_image_get_format (sw_canvas->image, &format);
if (force_opaque && PIXMAN_FORMAT_A (format) != 0) {
uint32_t *data;
int stride;
int width, height;
/* Remove alpha bits from format */
format = (pixman_format_code_t)(((uint32_t)format) & ~(0xf << 12));
data = pixman_image_get_data (sw_canvas->image);
stride = pixman_image_get_stride (sw_canvas->image);
width = pixman_image_get_width (sw_canvas->image);
height = pixman_image_get_height (sw_canvas->image);
return pixman_image_create_bits (format, width, height, data, stride);
} else {
pixman_image_ref(sw_canvas->image);
}
return sw_canvas->image;
}

@ -1 +1 @@
Subproject commit da908f89b581fd4725da997fdaea209f8e6548f6
Subproject commit 473a14b39fd7568e50456c61c95d89c742427ca1

View File

@ -26,6 +26,15 @@ struct Rect {
int32 right;
};
struct Transform {
uint32 t00;
uint32 t01;
uint32 t02;
uint32 t10;
uint32 t11;
uint32 t12;
};
enum32 link_err {
OK,
ERROR,
@ -52,6 +61,28 @@ flags32 migrate_flags {
NEED_DATA_TRANSFER
} @prefix(SPICE_MIGRATE_);
flags32 composite_flags {
OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7,
SRC_FILTER0, SRC_FILTER1, SRC_FILTER2,
MASK_FILTER0, MASK_FITLER1, MASK_FILTER2,
SRC_REPEAT0, SRC_REPEAT1,
MASK_REPEAT0, MASK_REPEAT1,
COMPONENT_ALPHA,
HAS_MASK,
HAS_SRC_TRANSFORM,
HAS_MASK_TRANSFORM,
/* These are used to override the formats given in the images. For
* example, if the mask image has format a8r8g8b8, but MASK_OPAQUE
* is set, the image should be treated as if it were x8r8g8b8
*/
SOURCE_OPAQUE,
MASK_OPAQUE,
DEST_OPAQUE,
} @prefix(SPICE_COMPOSITE_);
enum32 notify_severity {
INFO,
WARN,
@ -321,7 +352,8 @@ enum8 bitmap_fmt {
16BIT, /* 0555 mode */
24BIT /* 3 byte, brg */,
32BIT /* 4 byte, xrgb in little endian format */,
RGBA /* 4 byte, argb in little endian format */
RGBA /* 4 byte, argb in little endian format */,
8BIT_A /* 1 byte, alpha */
};
flags8 bitmap_flags {
@ -814,6 +846,28 @@ channel DisplayChannel : BaseChannel {
Head heads[count] @end;
} monitors_config;
message {
DisplayBase base;
struct Composite {
composite_flags flags;
Image *src_bitmap;
switch (flags) {
case HAS_MASK:
Image *mask_bitmap;
} a @anon;
switch (flags) {
case HAS_SRC_TRANSFORM:
Transform src_transform;
} b @anon;
switch (flags) {
case HAS_MASK_TRANSFORM:
Transform mask_transform;
} c @anon;
Point16 src_origin;
Point16 mask_origin;
} data;
} draw_composite;
client:
message {
uint8 pixmap_cache_id;