[Spice-commits] 2 commits - common/canvas_base.c common/canvas_base.h common/canvas_utils.c common/draw.h common/lz.c common/lz_common.h common/lz_compress_tmpl.c common/lz_decompress_tmpl.c common/Makefile.am common/messages.h common/pixman_utils.c common/sw_canvas.c spice.proto spice-protocol

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Fri Aug 24 10:41:17 PDT 2012


 common/Makefile.am          |    2 
 common/canvas_base.c        |  138 ++++++++++++++++++++++++++++++++++++++++++--
 common/canvas_base.h        |    3 
 common/canvas_utils.c       |    3 
 common/draw.h               |   20 ++++++
 common/lz.c                 |   24 +++++++
 common/lz_common.h          |    5 -
 common/lz_compress_tmpl.c   |   28 +++++++-
 common/lz_decompress_tmpl.c |   19 +++++-
 common/messages.h           |    5 +
 common/pixman_utils.c       |   15 ++++
 common/sw_canvas.c          |   20 +++++-
 spice-protocol              |    2 
 spice.proto                 |   56 +++++++++++++++++
 14 files changed, 320 insertions(+), 20 deletions(-)

New commits:
commit c0b048ebef41b3a79d42e96c0ecaef65e1bb7599
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri May 18 17:01:29 2012 -0400

    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.

diff --git a/common/Makefile.am b/common/Makefile.am
index 5f2c6e5..0e335b1 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -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
 
diff --git a/common/canvas_base.c b/common/canvas_base.c
index 4f40306..0ec8526 100644
--- a/common/canvas_base.c
+++ b/common/canvas_base.c
@@ -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;
 }
diff --git a/common/canvas_base.h b/common/canvas_base.h
index bdf12a1..637cdc1 100644
--- a/common/canvas_base.h
+++ b/common/canvas_base.h
@@ -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);
diff --git a/common/draw.h b/common/draw.h
index 8fad0e5..3704358 100644
--- a/common/draw.h
+++ b/common/draw.h
@@ -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;
diff --git a/common/lz.c b/common/lz.c
index 568aae7..3d77aed 100644
--- a/common/lz.c
+++ b/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:
diff --git a/common/lz_common.h b/common/lz_common.h
index 2ec374b..b5ce212 100644
--- a/common/lz_common.h
+++ b/common/lz_common.h
@@ -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  ")
diff --git a/common/lz_compress_tmpl.c b/common/lz_compress_tmpl.c
index 6db5387..7e2ce42 100644
--- a/common/lz_compress_tmpl.c
+++ b/common/lz_compress_tmpl.c
@@ -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
diff --git a/common/lz_decompress_tmpl.c b/common/lz_decompress_tmpl.c
index fb41e77..04a5121 100644
--- a/common/lz_decompress_tmpl.c
+++ b/common/lz_decompress_tmpl.c
@@ -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
diff --git a/common/messages.h b/common/messages.h
index 2b6d68a..b5f3368 100644
--- a/common/messages.h
+++ b/common/messages.h
@@ -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;
diff --git a/common/pixman_utils.c b/common/pixman_utils.c
index d4020e6..311c22e 100644
--- a/common/pixman_utils.c
+++ b/common/pixman_utils.c
@@ -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;
diff --git a/common/sw_canvas.c b/common/sw_canvas.c
index 4b10383..f947dde 100644
--- a/common/sw_canvas.c
+++ b/common/sw_canvas.c
@@ -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;
 }
diff --git a/spice-protocol b/spice-protocol
index da908f8..473a14b 160000
--- a/spice-protocol
+++ b/spice-protocol
@@ -1 +1 @@
-Subproject commit da908f89b581fd4725da997fdaea209f8e6548f6
+Subproject commit 473a14b39fd7568e50456c61c95d89c742427ca1
diff --git a/spice.proto b/spice.proto
index 1fdead9..29d6a8b 100644
--- a/spice.proto
+++ b/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;
commit 0c1b6de4ad1b3e9d6da50979bb259f0acdc2fd2f
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Jun 15 14:09:33 2012 -0400

    canvas_utils: Make sure strides are aligned to multiple of 4
    
    Pixman requires all strides to be aligned to a multiple of 4. With the
    upcoming a8 images, this is not guaranteed anymore.

diff --git a/common/canvas_utils.c b/common/canvas_utils.c
index 7b92436..feb89cb 100644
--- a/common/canvas_utils.c
+++ b/common/canvas_utils.c
@@ -282,6 +282,9 @@ pixman_image_t *alloc_lz_image_surface(LzDecodeUsrData *canvas_data,
 
     stride = (gross_pixels / height) * (PIXMAN_FORMAT_BPP (pixman_format) / 8);
 
+    /* pixman requires strides to be 4-byte aligned */
+    stride = SPICE_ALIGN(stride, 4);
+    
     if (!top_down) {
         stride = -stride;
     }


More information about the Spice-commits mailing list