[Spice-devel] [Common patch 2/2] Add support for A8 images to the LZ routines

Alon Levy alevy at redhat.com
Sun Jun 17 01:40:32 PDT 2012


On Fri, Jun 15, 2012 at 02:59:24PM -0400, Søren Sandmann wrote:
> From: Søren Sandmann Pedersen <ssp at redhat.com>
> 

Looks good, one comment below.

> 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 +-
>  7 files changed, 87 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;

Is this a debugging left over? I don't see it being used.

>  
>      // 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 bf0daeb..bba7ed7 160000
> --- a/spice-protocol
> +++ b/spice-protocol
> @@ -1 +1 @@
> -Subproject commit bf0daeb3a3c834133e781439f76b1c702470581b
> +Subproject commit bba7ed70380dc702c180d4a16a1e82c2887f9830
> -- 
> 1.7.4
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel


More information about the Spice-devel mailing list