mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-common
synced 2025-12-26 14:18:36 +00:00
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:
parent
0c1b6de4ad
commit
c0b048ebef
@ -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
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
24
common/lz.c
24
common/lz.c
@ -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:
|
||||
|
||||
@ -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 ")
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
56
spice.proto
56
spice.proto
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user