summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2012-05-18 17:01:29 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2012-07-02 17:20:46 -0400
commit552b3441b5bef8f9481b216bd1f2104b260d2f3c (patch)
tree1f8555b2dca50ec385c56bfd08f71ca6b879ec22
parentc6c5dd6313625210c9986f053f58c3c2fc768a12 (diff)
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.
-rw-r--r--common/canvas_base.c4
-rw-r--r--common/lz.c24
-rw-r--r--common/lz_common.h5
-rw-r--r--common/lz_compress_tmpl.c28
-rw-r--r--common/lz_decompress_tmpl.c19
-rw-r--r--common/pixman_utils.c15
m---------spice-protocol0
-rw-r--r--spice.proto3
8 files changed, 88 insertions, 10 deletions
diff --git a/common/canvas_base.c b/common/canvas_base.c
index 4f40306..c60c5cf 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 ||
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/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/spice-protocol b/spice-protocol
-Subproject 86eb1a334ebef63a43df9a267cfa42e4128966a
+Subproject 243390b431f7f4180afe15d5905030baba12056
diff --git a/spice.proto b/spice.proto
index a86bfa7..8dda736 100644
--- a/spice.proto
+++ b/spice.proto
@@ -321,7 +321,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 */,
+ A8 /* 1 byte, alpha */
};
flags8 bitmap_flags {