From: Søren Sandmann Pedersen <ssp@xxxxxxxxxx> This format is needed to add Render support to the X driver, so we need the ability to compress and decompress it. --- common/canvas_base.c | 4 ++++ common/lz.c | 24 +++++++++++++++++++++++- common/lz_common.h | 5 +++-- common/lz_compress_tmpl.c | 28 +++++++++++++++++++++++----- common/lz_decompress_tmpl.c | 19 ++++++++++++++++++- common/pixman_utils.c | 15 +++++++++++++++ spice-protocol | 2 +- spice.proto | 3 ++- 8 files changed, 89 insertions(+), 11 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 index da908f8..6ef7050 160000 --- a/spice-protocol +++ b/spice-protocol @@ -1 +1 @@ -Subproject commit da908f89b581fd4725da997fdaea209f8e6548f6 +Subproject commit 6ef7050b0725dbe385eed290e73a2603af7d3fbc diff --git a/spice.proto b/spice.proto index 1fdead9..87894a0 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 { -- 1.7.11.4 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel