> > On Thu, 2015-11-19 at 14:16 +0000, Frediano Ziglio wrote: > > Signed-off-by: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> > > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> > > --- > > server/dcc.c | 631 +++++++++++++++++++++++++++++++++++++++++++ > > server/dcc.h | 31 +++ > > server/display-channel.h | 4 + > > server/red_parse_qxl.h | 6 + > > server/red_worker.c | 678 > > +--------------------------------------------- > > - > > 5 files changed, 681 insertions(+), 669 deletions(-) > > > > diff --git a/server/dcc.c b/server/dcc.c > > index a14247c..1e18814 100644 > > --- a/server/dcc.c > > +++ b/server/dcc.c > > @@ -309,3 +309,634 @@ void dcc_destroy_surface(DisplayChannelClient *dcc, > > uint32_t surface_id) > > destroy = surface_destroy_item_new(channel, surface_id); > > red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &destroy > > ->pipe_item); > > } > > + > > +/* if already exists, returns it. Otherwise allocates and adds it (1) to > > the > > ring tail > > + in the channel (2) to the Drawable*/ > > +static RedGlzDrawable *get_glz_drawable(DisplayChannelClient *dcc, > > Drawable > > *drawable) > > +{ > > + RedGlzDrawable *ret; > > + RingItem *item, *next; > > + > > + // TODO - I don't really understand what's going on here, so doing the > > technical equivalent > > + // now that we have multiple glz_dicts, so the only way to go from dcc > > to > > drawable glz is to go > > + // over the glz_ring (unless adding some better data structure then a > > ring) > > + DRAWABLE_FOREACH_GLZ_SAFE(drawable, item, next, ret) { > > + if (ret->dcc == dcc) { > > + return ret; > > + } > > + } > > + > > + ret = spice_new(RedGlzDrawable, 1); > > + > > + ret->dcc = dcc; > > + ret->red_drawable = red_drawable_ref(drawable->red_drawable); > > + ret->drawable = drawable; > > + ret->group_id = drawable->group_id; > > + ret->instances_count = 0; > > + ring_init(&ret->instances); > > + > > + ring_item_init(&ret->link); > > + ring_item_init(&ret->drawable_link); > > + ring_add_before(&ret->link, &dcc->glz_drawables); > > + ring_add(&drawable->glz_ring, &ret->drawable_link); > > + DCC_TO_DC(dcc)->glz_drawable_count++; > > + return ret; > > +} > > + > > +/* allocates new instance and adds it to instances in the given drawable. > > + NOTE - the caller should set the glz_instance returned by the encoder > > by > > itself.*/ > > +static GlzDrawableInstanceItem *add_glz_drawable_instance(RedGlzDrawable > > *glz_drawable) > > +{ > > + spice_assert(glz_drawable->instances_count < > > MAX_GLZ_DRAWABLE_INSTANCES); > > + // NOTE: We assume the additions are performed consecutively, without > > removals in the middle > > + GlzDrawableInstanceItem *ret = glz_drawable->instances_pool + > > glz_drawable->instances_count; > > + glz_drawable->instances_count++; > > + > > + ring_item_init(&ret->free_link); > > + ring_item_init(&ret->glz_link); > > + ring_add(&glz_drawable->instances, &ret->glz_link); > > + ret->context = NULL; > > + ret->glz_drawable = glz_drawable; > > + > > + return ret; > > +} > > + > > +#define MIN_GLZ_SIZE_FOR_ZLIB 100 > > + > > +int dcc_compress_image_glz(DisplayChannelClient *dcc, > > + SpiceImage *dest, SpiceBitmap *src, Drawable > > *drawable, > > + compress_send_data_t* o_comp_data) > > +{ > > + DisplayChannel *display_channel = DCC_TO_DC(dcc); > > +#ifdef COMPRESS_STAT > > + stat_time_t start_time = stat_now(display_channel->glz_stat.clock); > > +#endif > > + spice_assert(bitmap_fmt_is_rgb(src->format)); > > + GlzData *glz_data = &dcc->glz_data; > > + ZlibData *zlib_data; > > + LzImageType type = MAP_BITMAP_FMT_TO_LZ_IMAGE_TYPE[src->format]; > > + RedGlzDrawable *glz_drawable; > > + GlzDrawableInstanceItem *glz_drawable_instance; > > + int glz_size; > > + int zlib_size; > > + > > + glz_data->data.bufs_tail = compress_buf_new(); > > + glz_data->data.bufs_head = glz_data->data.bufs_tail; > > + glz_data->data.dcc = dcc; > > + > > + glz_drawable = get_glz_drawable(dcc, drawable); > > + glz_drawable_instance = add_glz_drawable_instance(glz_drawable); > > + > > + glz_data->data.u.lines_data.chunks = src->data; > > + glz_data->data.u.lines_data.stride = src->stride; > > + glz_data->data.u.lines_data.next = 0; > > + glz_data->data.u.lines_data.reverse = 0; > > + > > + glz_size = glz_encode(dcc->glz, type, src->x, src->y, > > + (src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN), > > NULL, > > 0, > > + src->stride, > > glz_data->data.bufs_head->buf.bytes, > > + sizeof(glz_data->data.bufs_head->buf), > > + glz_drawable_instance, > > + &glz_drawable_instance->context); > > + > > + stat_compress_add(&display_channel->glz_stat, start_time, src->stride > > * > > src->y, glz_size); > > + > > + if (!display_channel->enable_zlib_glz_wrap || (glz_size < > > MIN_GLZ_SIZE_FOR_ZLIB)) { > > + goto glz; > > + } > > +#ifdef COMPRESS_STAT > > + start_time = stat_now(display_channel->zlib_glz_stat.clock); > > +#endif > > + zlib_data = &dcc->zlib_data; > > + > > + zlib_data->data.bufs_tail = compress_buf_new(); > > + zlib_data->data.bufs_head = zlib_data->data.bufs_tail; > > + zlib_data->data.dcc = dcc; > > + > > + zlib_data->data.u.compressed_data.next = glz_data->data.bufs_head; > > + zlib_data->data.u.compressed_data.size_left = glz_size; > > + > > + zlib_size = zlib_encode(dcc->zlib, dcc->zlib_level, > > + glz_size, > > zlib_data->data.bufs_head->buf.bytes, > > + sizeof(zlib_data->data.bufs_head->buf)); > > + > > + // the compressed buffer is bigger than the original data > > + if (zlib_size >= glz_size) { > > + while (zlib_data->data.bufs_head) { > > + RedCompressBuf *buf = zlib_data->data.bufs_head; > > + zlib_data->data.bufs_head = buf->send_next; > > + compress_buf_free(buf); > > + } > > + goto glz; > > + } > > + > > + dest->descriptor.type = SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB; > > + dest->u.zlib_glz.glz_data_size = glz_size; > > + dest->u.zlib_glz.data_size = zlib_size; > > + > > + o_comp_data->comp_buf = zlib_data->data.bufs_head; > > + o_comp_data->comp_buf_size = zlib_size; > > + > > + stat_compress_add(&display_channel->zlib_glz_stat, start_time, > > glz_size, > > zlib_size); > > + return TRUE; > > +glz: > > + dest->descriptor.type = SPICE_IMAGE_TYPE_GLZ_RGB; > > + dest->u.lz_rgb.data_size = glz_size; > > + > > + o_comp_data->comp_buf = glz_data->data.bufs_head; > > + o_comp_data->comp_buf_size = glz_size; > > + > > + return TRUE; > > +} > > + > > +int dcc_compress_image_lz(DisplayChannelClient *dcc, > > + SpiceImage *dest, SpiceBitmap *src, > > + compress_send_data_t* o_comp_data, uint32_t > > group_id) > > +{ > > + LzData *lz_data = &dcc->lz_data; > > + LzContext *lz = dcc->lz; > > + LzImageType type = MAP_BITMAP_FMT_TO_LZ_IMAGE_TYPE[src->format]; > > + int size; // size of the compressed data > > + > > +#ifdef COMPRESS_STAT > > + stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->lz_stat.clock); > > +#endif > > + > > + lz_data->data.bufs_tail = compress_buf_new(); > > + lz_data->data.bufs_head = lz_data->data.bufs_tail; > > + lz_data->data.dcc = dcc; > > + > > + if (setjmp(lz_data->data.jmp_env)) { > > + while (lz_data->data.bufs_head) { > > + RedCompressBuf *buf = lz_data->data.bufs_head; > > + lz_data->data.bufs_head = buf->send_next; > > + compress_buf_free(buf); > > + } > > + return FALSE; > > + } > > + > > + lz_data->data.u.lines_data.chunks = src->data; > > + lz_data->data.u.lines_data.stride = src->stride; > > + lz_data->data.u.lines_data.next = 0; > > + lz_data->data.u.lines_data.reverse = 0; > > + > > + size = lz_encode(lz, type, src->x, src->y, > > + !!(src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN), > > + NULL, 0, src->stride, > > + lz_data->data.bufs_head->buf.bytes, > > + sizeof(lz_data->data.bufs_head->buf)); > > + > > + // the compressed buffer is bigger than the original data > > + if (size > (src->y * src->stride)) { > > + longjmp(lz_data->data.jmp_env, 1); > > + } > > + > > + if (bitmap_fmt_is_rgb(src->format)) { > > + dest->descriptor.type = SPICE_IMAGE_TYPE_LZ_RGB; > > + dest->u.lz_rgb.data_size = size; > > + > > + o_comp_data->comp_buf = lz_data->data.bufs_head; > > + o_comp_data->comp_buf_size = size; > > + } else { > > + /* masks are 1BIT bitmaps without palettes, but they are not > > compressed > > + * (see fill_mask) */ > > + spice_assert(src->palette); > > + dest->descriptor.type = SPICE_IMAGE_TYPE_LZ_PLT; > > + dest->u.lz_plt.data_size = size; > > + dest->u.lz_plt.flags = src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN; > > + dest->u.lz_plt.palette = src->palette; > > + dest->u.lz_plt.palette_id = src->palette->unique; > > + o_comp_data->comp_buf = lz_data->data.bufs_head; > > + o_comp_data->comp_buf_size = size; > > + > > + dcc_palette_cache_palette(dcc, dest->u.lz_plt.palette, &(dest > > ->u.lz_plt.flags)); > > + o_comp_data->lzplt_palette = dest->u.lz_plt.palette; > > + } > > + > > + stat_compress_add(&DCC_TO_DC(dcc)->lz_stat, start_time, src->stride * > > src > > ->y, > > + o_comp_data->comp_buf_size); > > + return TRUE; > > +} > > + > > +int dcc_compress_image_jpeg(DisplayChannelClient *dcc, SpiceImage *dest, > > + SpiceBitmap *src, compress_send_data_t* > > o_comp_data, > > + uint32_t group_id) > > +{ > > + JpegData *jpeg_data = &dcc->jpeg_data; > > + LzData *lz_data = &dcc->lz_data; > > + JpegEncoderContext *jpeg = dcc->jpeg; > > + LzContext *lz = dcc->lz; > > + volatile JpegEncoderImageType jpeg_in_type; > > + int jpeg_size = 0; > > + volatile int has_alpha = FALSE; > > + int alpha_lz_size = 0; > > + int comp_head_filled; > > + int comp_head_left; > > + int stride; > > + uint8_t *lz_out_start_byte; > > + > > +#ifdef COMPRESS_STAT > > + stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->jpeg_stat.clock); > > +#endif > > + switch (src->format) { > > + case SPICE_BITMAP_FMT_16BIT: > > + jpeg_in_type = JPEG_IMAGE_TYPE_RGB16; > > + break; > > + case SPICE_BITMAP_FMT_24BIT: > > + jpeg_in_type = JPEG_IMAGE_TYPE_BGR24; > > + break; > > + case SPICE_BITMAP_FMT_32BIT: > > + jpeg_in_type = JPEG_IMAGE_TYPE_BGRX32; > > + break; > > + case SPICE_BITMAP_FMT_RGBA: > > + jpeg_in_type = JPEG_IMAGE_TYPE_BGRX32; > > + has_alpha = TRUE; > > + break; > > + default: > > + return FALSE; > > + } > > + > > + jpeg_data->data.bufs_tail = compress_buf_new(); > > + jpeg_data->data.bufs_head = jpeg_data->data.bufs_tail; > > + jpeg_data->data.dcc = dcc; > > + > > + if (setjmp(jpeg_data->data.jmp_env)) { > > + while (jpeg_data->data.bufs_head) { > > + RedCompressBuf *buf = jpeg_data->data.bufs_head; > > + jpeg_data->data.bufs_head = buf->send_next; > > + compress_buf_free(buf); > > + } > > + return FALSE; > > + } > > + > > + if (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE) { > > + spice_chunks_linearize(src->data); > > + } > > + > > + jpeg_data->data.u.lines_data.chunks = src->data; > > + jpeg_data->data.u.lines_data.stride = src->stride; > > + if ((src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { > > + jpeg_data->data.u.lines_data.next = 0; > > + jpeg_data->data.u.lines_data.reverse = 0; > > + stride = src->stride; > > + } else { > > + jpeg_data->data.u.lines_data.next = src->data->num_chunks - 1; > > + jpeg_data->data.u.lines_data.reverse = 1; > > + stride = -src->stride; > > + } > > + jpeg_size = jpeg_encode(jpeg, dcc->jpeg_quality, jpeg_in_type, > > + src->x, src->y, NULL, > > + 0, stride, > > jpeg_data->data.bufs_head->buf.bytes, > > + sizeof(jpeg_data->data.bufs_head->buf)); > > + > > + // the compressed buffer is bigger than the original data > > + if (jpeg_size > (src->y * src->stride)) { > > + longjmp(jpeg_data->data.jmp_env, 1); > > + } > > + > > + if (!has_alpha) { > > + dest->descriptor.type = SPICE_IMAGE_TYPE_JPEG; > > + dest->u.jpeg.data_size = jpeg_size; > > + > > + o_comp_data->comp_buf = jpeg_data->data.bufs_head; > > + o_comp_data->comp_buf_size = jpeg_size; > > + o_comp_data->is_lossy = TRUE; > > + > > + stat_compress_add(&DCC_TO_DC(dcc)->jpeg_stat, start_time, > > src->stride > > * src->y, > > + o_comp_data->comp_buf_size); > > + return TRUE; > > + } > > + > > + lz_data->data.bufs_head = jpeg_data->data.bufs_tail; > > + lz_data->data.bufs_tail = lz_data->data.bufs_head; > > + > > + comp_head_filled = jpeg_size % sizeof(lz_data->data.bufs_head->buf); > > + comp_head_left = sizeof(lz_data->data.bufs_head->buf) - > > comp_head_filled; > > + lz_out_start_byte = lz_data->data.bufs_head->buf.bytes + > > comp_head_filled; > > + > > + lz_data->data.dcc = dcc; > > + > > + lz_data->data.u.lines_data.chunks = src->data; > > + lz_data->data.u.lines_data.stride = src->stride; > > + lz_data->data.u.lines_data.next = 0; > > + lz_data->data.u.lines_data.reverse = 0; > > + > > + alpha_lz_size = lz_encode(lz, LZ_IMAGE_TYPE_XXXA, src->x, src->y, > > + !!(src->flags & > > SPICE_BITMAP_FLAGS_TOP_DOWN), > > + NULL, 0, src->stride, > > + lz_out_start_byte, > > + comp_head_left); > > + > > + // the compressed buffer is bigger than the original data > > + if ((jpeg_size + alpha_lz_size) > (src->y * src->stride)) { > > + longjmp(jpeg_data->data.jmp_env, 1); > > + } > > + > > + dest->descriptor.type = SPICE_IMAGE_TYPE_JPEG_ALPHA; > > + dest->u.jpeg_alpha.flags = 0; > > + if (src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN) { > > + dest->u.jpeg_alpha.flags |= SPICE_JPEG_ALPHA_FLAGS_TOP_DOWN; > > + } > > + > > + dest->u.jpeg_alpha.jpeg_size = jpeg_size; > > + dest->u.jpeg_alpha.data_size = jpeg_size + alpha_lz_size; > > + > > + o_comp_data->comp_buf = jpeg_data->data.bufs_head; > > + o_comp_data->comp_buf_size = jpeg_size + alpha_lz_size; > > + o_comp_data->is_lossy = TRUE; > > + stat_compress_add(&DCC_TO_DC(dcc)->jpeg_alpha_stat, start_time, src > > ->stride * src->y, > > + o_comp_data->comp_buf_size); > > + return TRUE; > > +} > > + > > +#ifdef USE_LZ4 > > +int dcc_compress_image_lz4(DisplayChannelClient *dcc, SpiceImage *dest, > > + SpiceBitmap *src, compress_send_data_t* > > o_comp_data, > > + uint32_t group_id) > > +{ > > + DisplayChannel *display_channel = DCC_TO_DC(dcc); > > + Lz4Data *lz4_data = &dcc->lz4_data; > > + Lz4EncoderContext *lz4 = dcc->lz4; > > + int lz4_size = 0; > > + > > +#ifdef COMPRESS_STAT > > + stat_time_t start_time = stat_now(display_channel->lz4_stat.clock); > > +#endif > > + > > + lz4_data->data.bufs_tail = compress_buf_new(); > > + lz4_data->data.bufs_head = lz4_data->data.bufs_tail; > > + > > + if (!lz4_data->data.bufs_head) { > > + spice_warning("failed to allocate compress buffer"); > > + return FALSE; > > + } > > + > > + lz4_data->data.bufs_head->send_next = NULL; > > + lz4_data->data.dcc = dcc; > > + > > + if (setjmp(lz4_data->data.jmp_env)) { > > + while (lz4_data->data.bufs_head) { > > + RedCompressBuf *buf = lz4_data->data.bufs_head; > > + lz4_data->data.bufs_head = buf->send_next; > > + compress_buf_free(buf); > > + } > > + return FALSE; > > + } > > + > > + if (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE) { > > + spice_chunks_linearize(src->data); > > + } > > + > > + lz4_data->data.u.lines_data.chunks = src->data; > > + lz4_data->data.u.lines_data.stride = src->stride; > > + lz4_data->data.u.lines_data.next = 0; > > + lz4_data->data.u.lines_data.reverse = 0; > > + > > + lz4_size = lz4_encode(lz4, src->y, src->stride, > > lz4_data->data.bufs_head > > ->buf.bytes, > > + sizeof(lz4_data->data.bufs_head->buf), > > + src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN, src > > ->format); > > + > > + // the compressed buffer is bigger than the original data > > + if (lz4_size > (src->y * src->stride)) { > > + longjmp(lz4_data->data.jmp_env, 1); > > + } > > + > > + dest->descriptor.type = SPICE_IMAGE_TYPE_LZ4; > > + dest->u.lz4.data_size = lz4_size; > > + > > + o_comp_data->comp_buf = lz4_data->data.bufs_head; > > + o_comp_data->comp_buf_size = lz4_size; > > + > > + stat_compress_add(&display_channel->lz4_stat, start_time, src->stride > > * > > src->y, > > + o_comp_data->comp_buf_size); > > + return TRUE; > > +} > > +#endif > > + > > +int dcc_compress_image_quic(DisplayChannelClient *dcc, SpiceImage *dest, > > + SpiceBitmap *src, compress_send_data_t* > > o_comp_data, > > + uint32_t group_id) > > +{ > > + QuicData *quic_data = &dcc->quic_data; > > + QuicContext *quic = dcc->quic; > > + volatile QuicImageType type; > > + int size, stride; > > + > > +#ifdef COMPRESS_STAT > > + stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->quic_stat.clock); > > +#endif > > + > > + switch (src->format) { > > + case SPICE_BITMAP_FMT_32BIT: > > + type = QUIC_IMAGE_TYPE_RGB32; > > + break; > > + case SPICE_BITMAP_FMT_RGBA: > > + type = QUIC_IMAGE_TYPE_RGBA; > > + break; > > + case SPICE_BITMAP_FMT_16BIT: > > + type = QUIC_IMAGE_TYPE_RGB16; > > + break; > > + case SPICE_BITMAP_FMT_24BIT: > > + type = QUIC_IMAGE_TYPE_RGB24; > > + break; > > + default: > > + return FALSE; > > + } > > + > > + quic_data->data.bufs_tail = compress_buf_new(); > > + quic_data->data.bufs_head = quic_data->data.bufs_tail; > > + quic_data->data.dcc = dcc; > > + > > + if (setjmp(quic_data->data.jmp_env)) { > > + while (quic_data->data.bufs_head) { > > + RedCompressBuf *buf = quic_data->data.bufs_head; > > + quic_data->data.bufs_head = buf->send_next; > > + compress_buf_free(buf); > > + } > > + return FALSE; > > + } > > + > > + if (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE) { > > + spice_chunks_linearize(src->data); > > + } > > + > > + quic_data->data.u.lines_data.chunks = src->data; > > + quic_data->data.u.lines_data.stride = src->stride; > > + if ((src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { > > + quic_data->data.u.lines_data.next = 0; > > + quic_data->data.u.lines_data.reverse = 0; > > + stride = src->stride; > > + } else { > > + quic_data->data.u.lines_data.next = src->data->num_chunks - 1; > > + quic_data->data.u.lines_data.reverse = 1; > > + stride = -src->stride; > > + } > > + size = quic_encode(quic, type, src->x, src->y, NULL, 0, stride, > > + quic_data->data.bufs_head->buf.words, > > + > > G_N_ELEMENTS(quic_data->data.bufs_head->buf.words)); > > + > > + // the compressed buffer is bigger than the original data > > + if ((size << 2) > (src->y * src->stride)) { > > + longjmp(quic_data->data.jmp_env, 1); > > + } > > + > > + dest->descriptor.type = SPICE_IMAGE_TYPE_QUIC; > > + dest->u.quic.data_size = size << 2; > > + > > + o_comp_data->comp_buf = quic_data->data.bufs_head; > > + o_comp_data->comp_buf_size = size << 2; > > + > > + stat_compress_add(&DCC_TO_DC(dcc)->quic_stat, start_time, src->stride > > * > > src->y, > > + o_comp_data->comp_buf_size); > > + return TRUE; > > +} > > + > > +#define MIN_SIZE_TO_COMPRESS 54 > > +#define MIN_DIMENSION_TO_QUIC 3 > > +int dcc_compress_image(DisplayChannelClient *dcc, > > + SpiceImage *dest, SpiceBitmap *src, Drawable > > *drawable, > > + int can_lossy, > > + compress_send_data_t* o_comp_data) > > +{ > > + DisplayChannel *display_channel = DCC_TO_DC(dcc); > > + SpiceImageCompression image_compression = dcc->image_compression; > > + int quic_compress = FALSE; > > + > > + if ((image_compression == SPICE_IMAGE_COMPRESSION_OFF) || > > + ((src->y * src->stride) < MIN_SIZE_TO_COMPRESS)) { // TODO: change > > the size cond > > + return FALSE; > > + } else if (image_compression == SPICE_IMAGE_COMPRESSION_QUIC) { > > + if (bitmap_fmt_is_plt(src->format)) { > > + return FALSE; > > + } else { > > + quic_compress = TRUE; > > + } > > + } else { > > + /* > > + lz doesn't handle (1) bitmaps with strides that are larger > > than > > the width > > + of the image in bytes (2) unstable bitmaps > > + */ > > + if (bitmap_has_extra_stride(src) || (src->data->flags & > > SPICE_CHUNKS_FLAGS_UNSTABLE)) { > > + if ((image_compression == SPICE_IMAGE_COMPRESSION_LZ) || > > + (image_compression == SPICE_IMAGE_COMPRESSION_GLZ) || > > + (image_compression == SPICE_IMAGE_COMPRESSION_LZ4) || > > + bitmap_fmt_is_plt(src->format)) { > > + return FALSE; > > + } else { > > + quic_compress = TRUE; > > + } > > + } else { > > + if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) || > > + (image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ)) { > > + if ((src->x < MIN_DIMENSION_TO_QUIC) || (src->y < > > MIN_DIMENSION_TO_QUIC)) { > > + quic_compress = FALSE; > > + } else { > > + if (drawable->copy_bitmap_graduality == > > BITMAP_GRADUAL_INVALID) { > > + quic_compress = bitmap_fmt_has_graduality(src > > ->format) && > > + bitmap_get_graduality_level(src) == > > BITMAP_GRADUAL_HIGH; > > + } else { > > + quic_compress = (drawable->copy_bitmap_graduality > > == > > BITMAP_GRADUAL_HIGH); > > + } > > + } > > + } else { > > + quic_compress = FALSE; > > + } > > + } > > + } > > + > > + if (quic_compress) { > > +#ifdef COMPRESS_DEBUG > > + spice_info("QUIC compress"); > > +#endif > > + // if bitmaps is picture-like, compress it using jpeg > > + if (can_lossy && display_channel->enable_jpeg && > > + ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) || > > + (image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ))) { > > + // if we use lz for alpha, the stride can't be extra > > + if (src->format != SPICE_BITMAP_FMT_RGBA || > > !bitmap_has_extra_stride(src)) { > > + return dcc_compress_image_jpeg(dcc, dest, > > + src, o_comp_data, drawable > > ->group_id); > > + } > > + } > > + return dcc_compress_image_quic(dcc, dest, > > + src, o_comp_data, > > drawable->group_id); > > + } else { > > + int glz; > > + int ret; > > + if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ) || > > + (image_compression == SPICE_IMAGE_COMPRESSION_GLZ)) { > > + glz = bitmap_fmt_has_graduality(src->format) && ( > > + (src->x * src->y) < glz_enc_dictionary_get_size( > > + dcc->glz_dict->dict)); > > + } else if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) > > || > > + (image_compression == SPICE_IMAGE_COMPRESSION_LZ) || > > + (image_compression == SPICE_IMAGE_COMPRESSION_LZ4)) { > > + glz = FALSE; > > + } else { > > + spice_error("invalid image compression type %u", > > image_compression); > > + return FALSE; > > + } > > + > > + if (glz) { > > + /* using the global dictionary only if it is not frozen */ > > + pthread_rwlock_rdlock(&dcc->glz_dict->encode_lock); > > + if (!dcc->glz_dict->migrate_freeze) { > > + ret = dcc_compress_image_glz(dcc, > > + dest, src, > > + drawable, o_comp_data); > > + } else { > > + glz = FALSE; > > + } > > + pthread_rwlock_unlock(&dcc->glz_dict->encode_lock); > > + } > > + > > + if (!glz) { > > +#ifdef USE_LZ4 > > + if (image_compression == SPICE_IMAGE_COMPRESSION_LZ4 && > > + bitmap_fmt_is_rgb(src->format) && > > + red_channel_client_test_remote_cap(&dcc->common.base, > > + SPICE_DISPLAY_CAP_LZ4_COMPRESSION)) { > > + ret = dcc_compress_image_lz4(dcc, dest, src, o_comp_data, > > + drawable->group_id); > > + } else > > +#endif > > + ret = dcc_compress_image_lz(dcc, dest, src, o_comp_data, > > + drawable->group_id); > > +#ifdef COMPRESS_DEBUG > > + spice_info("LZ LOCAL compress"); > > +#endif > > + } > > +#ifdef COMPRESS_DEBUG > > + else { > > + spice_info("LZ global compress fmt=%d", src->format); > > + } > > +#endif > > + return ret; > > + } > > +} > > + > > +#define CLIENT_PALETTE_CACHE > > +#include "cache_item.tmpl.c" > > +#undef CLIENT_PALETTE_CACHE > > + > > +void dcc_palette_cache_palette(DisplayChannelClient *dcc, SpicePalette > > *palette, > > + uint8_t *flags) > > +{ > > + if (palette == NULL) { > > + return; > > + } > > + if (palette->unique) { > > + if (red_palette_cache_find(dcc, palette->unique)) { > > + *flags |= SPICE_BITMAP_FLAGS_PAL_FROM_CACHE; > > + return; > > + } > > + if (red_palette_cache_add(dcc, palette->unique, 1)) { > > + *flags |= SPICE_BITMAP_FLAGS_PAL_CACHE_ME; > > + } > > + } > > +} > > + > > +void dcc_palette_cache_reset(DisplayChannelClient *dcc) > > +{ > > + red_palette_cache_reset(dcc, CLIENT_PALETTE_CACHE_SIZE); > > +} > > diff --git a/server/dcc.h b/server/dcc.h > > index a6ca9be..7827f72 100644 > > --- a/server/dcc.h > > +++ b/server/dcc.h > > @@ -163,5 +163,36 @@ ImageItem * dcc_add_surface_area_image > > (DisplayCha > > > > SpiceRect *area, > > > > PipeItem *pos, > > int > > can_lossy); > > +void dcc_palette_cache_reset > > (DisplayChannelClient *dcc); > > +void dcc_palette_cache_palette > > (DisplayChannelClient *dcc, > > + > > SpicePalette *palette, > > + > > uint8_t > > *flags); > > + > > +typedef struct compress_send_data_t { > > + void* comp_buf; > > + uint32_t comp_buf_size; > > + SpicePalette *lzplt_palette; > > + int is_lossy; > > +} compress_send_data_t; > > + > > +int dcc_compress_image > > (DisplayChannelClient *dcc, > > + > > SpiceImage *dest, SpiceBitmap *src, Drawable *drawable, > > + int > > can_lossy, > > + > > compress_send_data_t* o_comp_data); > > +int dcc_compress_image_glz > > (DisplayChannelClient *dcc, > > + > > SpiceImage *dest, SpiceBitmap *src, Drawable *drawable, > > + > > compress_send_data_t* o_comp_data); > > +int dcc_compress_image_lz > > (DisplayChannelClient *dcc, > > + > > SpiceImage *dest, SpiceBitmap *src, > > + > > compress_send_data_t* o_comp_data, uint32_t group_id); > > +int dcc_compress_image_jpeg > > (DisplayChannelClient *dcc, SpiceImage *dest, > > + > > SpiceBitmap *src, compress_send_data_t* o_comp_data, > > + > > uint32_t group_id); > > +int dcc_compress_image_quic > > (DisplayChannelClient *dcc, SpiceImage *dest, > > + > > SpiceBitmap *src, compress_send_data_t* o_comp_data, > > + > > uint32_t group_id); > > +int dcc_compress_image_lz4 > > (DisplayChannelClient *dcc, SpiceImage *dest, > > + > > SpiceBitmap *src, compress_send_data_t* o_comp_data, > > + > > uint32_t group_id); > > > > #endif /* DCC_H_ */ > > diff --git a/server/display-channel.h b/server/display-channel.h > > index 7f3949f..111e014 100644 > > --- a/server/display-channel.h > > +++ b/server/display-channel.h > > @@ -91,6 +91,10 @@ struct Drawable { > > #define DRAWABLE_FOREACH_DPI_SAFE(drawable, link, next, dpi) \ > > SAFE_FOREACH(link, next, drawable, &(drawable)->pipes, dpi, > > LINK_TO_DPI(link)) > > > > +#define LINK_TO_GLZ(ptr) SPICE_CONTAINEROF((ptr), RedGlzDrawable, \ > > + drawable_link) > > +#define DRAWABLE_FOREACH_GLZ_SAFE(drawable, link, next, glz) \ > > + SAFE_FOREACH(link, next, drawable, &(drawable)->glz_ring, glz, > > LINK_TO_GLZ(link)) > > > > enum { > > PIPE_ITEM_TYPE_DRAW = PIPE_ITEM_TYPE_COMMON_LAST, > > diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h > > index 87862fa..b3b28e1 100644 > > --- a/server/red_parse_qxl.h > > +++ b/server/red_parse_qxl.h > > @@ -57,6 +57,12 @@ typedef struct RedDrawable { > > } u; > > } RedDrawable; > > > > +static inline RedDrawable *red_drawable_ref(RedDrawable *drawable) > > +{ > > + drawable->refs++; > > + return drawable; > > +} > > + > > typedef struct RedUpdateCmd { > > QXLReleaseInfo *release_info; > > SpiceRect area; > > diff --git a/server/red_worker.c b/server/red_worker.c > > index eab00ff..d744f48 100644 > > --- a/server/red_worker.c > > +++ b/server/red_worker.c > > @@ -73,12 +73,6 @@ > > #define CMD_RING_POLL_RETRIES 200 > > > > #define DISPLAY_CLIENT_SHORT_TIMEOUT 15000000000ULL //nano > > -#define DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT 10000000000ULL //nano, 10 sec > > -#define DISPLAY_CLIENT_RETRY_INTERVAL 10000 //micro > > - > > -#define DISPLAY_FREE_LIST_DEFAULT_SIZE 128 > > - > > -#define MIN_GLZ_SIZE_FOR_ZLIB 100 > > > > #define VALIDATE_SURFACE_RET(worker, surface_id) \ > > if (!validate_surface(worker, surface_id)) { \ > > @@ -202,13 +196,6 @@ static void red_create_surface(DisplayChannel > > *display, > > uint32_t surface_id, uin > > uint32_t height, int32_t stride, uint32_t > > format, > > void *line_0, int data_is_valid, int > > send_client); > > > > - > > -#define LINK_TO_GLZ(ptr) SPICE_CONTAINEROF((ptr), RedGlzDrawable, \ > > - drawable_link) > > -#define DRAWABLE_FOREACH_GLZ_SAFE(drawable, link, next, glz) \ > > - SAFE_FOREACH(link, next, drawable, &(drawable)->glz_ring, glz, > > LINK_TO_GLZ(link)) > > - > > - > > static void display_stream_clip_unref(DisplayChannel *display, > > StreamClipItem > > *item) > > { > > if (--item->refs != 0) > > @@ -545,14 +532,6 @@ static void common_release_recv_buf(RedChannelClient > > *rcc, uint16_t type, uint32 > > } > > } > > > > -#define CLIENT_PALETTE_CACHE > > -#include "cache_item.tmpl.c" > > -#undef CLIENT_PALETTE_CACHE > > - > > -static void red_reset_palette_cache(DisplayChannelClient *dcc) > > -{ > > - red_palette_cache_reset(dcc, CLIENT_PALETTE_CACHE_SIZE); > > -} > > > > static Drawable* drawable_try_new(DisplayChannel *display) > > { > > @@ -592,13 +571,6 @@ static inline void > > set_surface_release_info(QXLReleaseInfoExt *release_info_ext, > > release_info_ext->group_id = group_id; > > } > > > > -static RedDrawable *red_drawable_ref(RedDrawable *drawable) > > -{ > > - drawable->refs++; > > - return drawable; > > -} > > - > > - > > static void red_drawable_unref(RedWorker *worker, RedDrawable > > *red_drawable, > > uint32_t group_id) > > { > > @@ -2032,79 +2004,6 @@ static void fill_base(SpiceMarshaller > > *base_marshaller, > > Drawable *drawable) > > spice_marshall_DisplayBase(base_marshaller, &base); > > } > > > > -static inline void fill_palette(DisplayChannelClient *dcc, > > - SpicePalette *palette, > > - uint8_t *flags) > > -{ > > - if (palette == NULL) { > > - return; > > - } > > - if (palette->unique) { > > - if (red_palette_cache_find(dcc, palette->unique)) { > > - *flags |= SPICE_BITMAP_FLAGS_PAL_FROM_CACHE; > > - return; > > - } > > - if (red_palette_cache_add(dcc, palette->unique, 1)) { > > - *flags |= SPICE_BITMAP_FLAGS_PAL_CACHE_ME; > > - } > > - } > > -} > > - > > -/****************************************************** > > - * Global lz red drawables routines > > -*******************************************************/ > > - > > -/* if already exists, returns it. Otherwise allocates and adds it (1) to > > the > > ring tail > > - in the channel (2) to the Drawable*/ > > -static RedGlzDrawable *red_display_get_glz_drawable(DisplayChannelClient > > *dcc, Drawable *drawable) > > -{ > > - RedGlzDrawable *ret; > > - RingItem *item, *next; > > - > > - // TODO - I don't really understand what's going on here, so doing the > > technical equivalent > > - // now that we have multiple glz_dicts, so the only way to go from dcc > > to > > drawable glz is to go > > - // over the glz_ring (unless adding some better data structure then a > > ring) > > - DRAWABLE_FOREACH_GLZ_SAFE(drawable, item, next, ret) { > > - if (ret->dcc == dcc) { > > - return ret; > > - } > > - } > > - > > - ret = spice_new(RedGlzDrawable, 1); > > - > > - ret->dcc = dcc; > > - ret->red_drawable = red_drawable_ref(drawable->red_drawable); > > - ret->drawable = drawable; > > - ret->group_id = drawable->group_id; > > - ret->instances_count = 0; > > - ring_init(&ret->instances); > > - > > - ring_item_init(&ret->link); > > - ring_item_init(&ret->drawable_link); > > - ring_add_before(&ret->link, &dcc->glz_drawables); > > - ring_add(&drawable->glz_ring, &ret->drawable_link); > > - DCC_TO_DC(dcc)->glz_drawable_count++; > > - return ret; > > -} > > - > > -/* allocates new instance and adds it to instances in the given drawable. > > - NOTE - the caller should set the glz_instance returned by the encoder > > by > > itself.*/ > > -static GlzDrawableInstanceItem > > *red_display_add_glz_drawable_instance(RedGlzDrawable *glz_drawable) > > -{ > > - spice_assert(glz_drawable->instances_count < > > MAX_GLZ_DRAWABLE_INSTANCES); > > - // NOTE: We assume the additions are performed consecutively, without > > removals in the middle > > - GlzDrawableInstanceItem *ret = glz_drawable->instances_pool + > > glz_drawable->instances_count; > > - glz_drawable->instances_count++; > > - > > - ring_item_init(&ret->free_link); > > - ring_item_init(&ret->glz_link); > > - ring_add(&glz_drawable->instances, &ret->glz_link); > > - ret->context = NULL; > > - ret->glz_drawable = glz_drawable; > > - > > - return ret; > > -} > > - > > /* Remove from the to_free list and the instances_list. > > When no instance is left - the RedGlzDrawable is released too. (and the > > qxl drawable too, if > > it is not used by Drawable). > > @@ -2261,565 +2160,6 @@ static int > > red_display_free_some_independent_glz_drawables(DisplayChannelClient > > return n; > > } > > > > -typedef struct compress_send_data_t { > > - void* comp_buf; > > - uint32_t comp_buf_size; > > - SpicePalette *lzplt_palette; > > - int is_lossy; > > -} compress_send_data_t; > > - > > -static inline int red_glz_compress_image(DisplayChannelClient *dcc, > > - SpiceImage *dest, SpiceBitmap > > *src, > > Drawable *drawable, > > - compress_send_data_t* > > o_comp_data) > > -{ > > - DisplayChannel *display_channel = DCC_TO_DC(dcc); > > -#ifdef COMPRESS_STAT > > - stat_time_t start_time = > > stat_now(display_channel->zlib_glz_stat.clock); > > -#endif > > - spice_assert(bitmap_fmt_is_rgb(src->format)); > > - GlzData *glz_data = &dcc->glz_data; > > - ZlibData *zlib_data; > > - LzImageType type = MAP_BITMAP_FMT_TO_LZ_IMAGE_TYPE[src->format]; > > - RedGlzDrawable *glz_drawable; > > - GlzDrawableInstanceItem *glz_drawable_instance; > > - int glz_size; > > - int zlib_size; > > - > > - glz_data->data.bufs_tail = compress_buf_new(); > > - glz_data->data.bufs_head = glz_data->data.bufs_tail; > > - glz_data->data.dcc = dcc; > > - > > - glz_drawable = red_display_get_glz_drawable(dcc, drawable); > > - glz_drawable_instance = > > red_display_add_glz_drawable_instance(glz_drawable); > > - > > - glz_data->data.u.lines_data.chunks = src->data; > > - glz_data->data.u.lines_data.stride = src->stride; > > - glz_data->data.u.lines_data.next = 0; > > - glz_data->data.u.lines_data.reverse = 0; > > - > > - glz_size = glz_encode(dcc->glz, type, src->x, src->y, > > - (src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN), > > NULL, > > 0, > > - src->stride, > > glz_data->data.bufs_head->buf.bytes, > > - sizeof(glz_data->data.bufs_head->buf), > > - glz_drawable_instance, > > - &glz_drawable_instance->context); > > - > > - stat_compress_add(&display_channel->glz_stat, start_time, src->stride > > * > > src->y, glz_size); > > - > > - if (!display_channel->enable_zlib_glz_wrap || (glz_size < > > MIN_GLZ_SIZE_FOR_ZLIB)) { > > - goto glz; > > - } > > -#ifdef COMPRESS_STAT > > - start_time = stat_now(display_channel->zlib_glz_stat.clock); > > -#endif > > - zlib_data = &dcc->zlib_data; > > - > > - zlib_data->data.bufs_tail = compress_buf_new(); > > - zlib_data->data.bufs_head = zlib_data->data.bufs_tail; > > - zlib_data->data.dcc = dcc; > > - > > - zlib_data->data.u.compressed_data.next = glz_data->data.bufs_head; > > - zlib_data->data.u.compressed_data.size_left = glz_size; > > - > > - zlib_size = zlib_encode(dcc->zlib, dcc->zlib_level, > > - glz_size, > > zlib_data->data.bufs_head->buf.bytes, > > - sizeof(zlib_data->data.bufs_head->buf)); > > - > > - // the compressed buffer is bigger than the original data > > - if (zlib_size >= glz_size) { > > - while (zlib_data->data.bufs_head) { > > - RedCompressBuf *buf = zlib_data->data.bufs_head; > > - zlib_data->data.bufs_head = buf->send_next; > > - compress_buf_free(buf); > > - } > > - goto glz; > > - } > > - > > - dest->descriptor.type = SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB; > > - dest->u.zlib_glz.glz_data_size = glz_size; > > - dest->u.zlib_glz.data_size = zlib_size; > > - > > - o_comp_data->comp_buf = zlib_data->data.bufs_head; > > - o_comp_data->comp_buf_size = zlib_size; > > - > > - stat_compress_add(&display_channel->zlib_glz_stat, start_time, > > glz_size, > > zlib_size); > > - return TRUE; > > -glz: > > - dest->descriptor.type = SPICE_IMAGE_TYPE_GLZ_RGB; > > - dest->u.lz_rgb.data_size = glz_size; > > - > > - o_comp_data->comp_buf = glz_data->data.bufs_head; > > - o_comp_data->comp_buf_size = glz_size; > > - > > - return TRUE; > > -} > > - > > -static inline int red_lz_compress_image(DisplayChannelClient *dcc, > > - SpiceImage *dest, SpiceBitmap > > *src, > > - compress_send_data_t* o_comp_data, > > uint32_t group_id) > > -{ > > - LzData *lz_data = &dcc->lz_data; > > - LzContext *lz = dcc->lz; > > - LzImageType type = MAP_BITMAP_FMT_TO_LZ_IMAGE_TYPE[src->format]; > > - int size; // size of the compressed data > > - > > -#ifdef COMPRESS_STAT > > - stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->lz_stat.clock); > > -#endif > > - > > - lz_data->data.bufs_tail = compress_buf_new(); > > - lz_data->data.bufs_head = lz_data->data.bufs_tail; > > - lz_data->data.dcc = dcc; > > - > > - if (setjmp(lz_data->data.jmp_env)) { > > - while (lz_data->data.bufs_head) { > > - RedCompressBuf *buf = lz_data->data.bufs_head; > > - lz_data->data.bufs_head = buf->send_next; > > - compress_buf_free(buf); > > - } > > - return FALSE; > > - } > > - > > - lz_data->data.u.lines_data.chunks = src->data; > > - lz_data->data.u.lines_data.stride = src->stride; > > - lz_data->data.u.lines_data.next = 0; > > - lz_data->data.u.lines_data.reverse = 0; > > - > > - size = lz_encode(lz, type, src->x, src->y, > > - !!(src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN), > > - NULL, 0, src->stride, > > - lz_data->data.bufs_head->buf.bytes, > > - sizeof(lz_data->data.bufs_head->buf)); > > - > > - // the compressed buffer is bigger than the original data > > - if (size > (src->y * src->stride)) { > > - longjmp(lz_data->data.jmp_env, 1); > > - } > > - > > - if (bitmap_fmt_is_rgb(src->format)) { > > - dest->descriptor.type = SPICE_IMAGE_TYPE_LZ_RGB; > > - dest->u.lz_rgb.data_size = size; > > - > > - o_comp_data->comp_buf = lz_data->data.bufs_head; > > - o_comp_data->comp_buf_size = size; > > - } else { > > - /* masks are 1BIT bitmaps without palettes, but they are not > > compressed > > - * (see fill_mask) */ > > - spice_assert(src->palette); > > - dest->descriptor.type = SPICE_IMAGE_TYPE_LZ_PLT; > > - dest->u.lz_plt.data_size = size; > > - dest->u.lz_plt.flags = src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN; > > - dest->u.lz_plt.palette = src->palette; > > - dest->u.lz_plt.palette_id = src->palette->unique; > > - o_comp_data->comp_buf = lz_data->data.bufs_head; > > - o_comp_data->comp_buf_size = size; > > - > > - fill_palette(dcc, dest->u.lz_plt.palette, > > &(dest->u.lz_plt.flags)); > > - o_comp_data->lzplt_palette = dest->u.lz_plt.palette; > > - } > > - > > - stat_compress_add(&DCC_TO_DC(dcc)->lz_stat, start_time, src->stride * > > src > > ->y, > > - o_comp_data->comp_buf_size); > > - return TRUE; > > -} > > - > > -static int red_jpeg_compress_image(DisplayChannelClient *dcc, SpiceImage > > *dest, > > - SpiceBitmap *src, compress_send_data_t* > > o_comp_data, > > - uint32_t group_id) > > -{ > > - JpegData *jpeg_data = &dcc->jpeg_data; > > - LzData *lz_data = &dcc->lz_data; > > - JpegEncoderContext *jpeg = dcc->jpeg; > > - LzContext *lz = dcc->lz; > > - volatile JpegEncoderImageType jpeg_in_type; > > - int jpeg_size = 0; > > - volatile int has_alpha = FALSE; > > - int alpha_lz_size = 0; > > - int comp_head_filled; > > - int comp_head_left; > > - int stride; > > - uint8_t *lz_out_start_byte; > > - > > -#ifdef COMPRESS_STAT > > - stat_time_t start_time = > > stat_now(DCC_TO_DC(dcc)->jpeg_alpha_stat.clock); > > -#endif > > - switch (src->format) { > > - case SPICE_BITMAP_FMT_16BIT: > > - jpeg_in_type = JPEG_IMAGE_TYPE_RGB16; > > - break; > > - case SPICE_BITMAP_FMT_24BIT: > > - jpeg_in_type = JPEG_IMAGE_TYPE_BGR24; > > - break; > > - case SPICE_BITMAP_FMT_32BIT: > > - jpeg_in_type = JPEG_IMAGE_TYPE_BGRX32; > > - break; > > - case SPICE_BITMAP_FMT_RGBA: > > - jpeg_in_type = JPEG_IMAGE_TYPE_BGRX32; > > - has_alpha = TRUE; > > - break; > > - default: > > - return FALSE; > > - } > > - > > - jpeg_data->data.bufs_tail = compress_buf_new(); > > - jpeg_data->data.bufs_head = jpeg_data->data.bufs_tail; > > - jpeg_data->data.dcc = dcc; > > - > > - if (setjmp(jpeg_data->data.jmp_env)) { > > - while (jpeg_data->data.bufs_head) { > > - RedCompressBuf *buf = jpeg_data->data.bufs_head; > > - jpeg_data->data.bufs_head = buf->send_next; > > - compress_buf_free(buf); > > - } > > - return FALSE; > > - } > > - > > - if (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE) { > > - spice_chunks_linearize(src->data); > > - } > > - > > - jpeg_data->data.u.lines_data.chunks = src->data; > > - jpeg_data->data.u.lines_data.stride = src->stride; > > - if ((src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { > > - jpeg_data->data.u.lines_data.next = 0; > > - jpeg_data->data.u.lines_data.reverse = 0; > > - stride = src->stride; > > - } else { > > - jpeg_data->data.u.lines_data.next = src->data->num_chunks - 1; > > - jpeg_data->data.u.lines_data.reverse = 1; > > - stride = -src->stride; > > - } > > - jpeg_size = jpeg_encode(jpeg, dcc->jpeg_quality, jpeg_in_type, > > - src->x, src->y, NULL, > > - 0, stride, > > jpeg_data->data.bufs_head->buf.bytes, > > - sizeof(jpeg_data->data.bufs_head->buf)); > > - > > - // the compressed buffer is bigger than the original data > > - if (jpeg_size > (src->y * src->stride)) { > > - longjmp(jpeg_data->data.jmp_env, 1); > > - } > > - > > - if (!has_alpha) { > > - dest->descriptor.type = SPICE_IMAGE_TYPE_JPEG; > > - dest->u.jpeg.data_size = jpeg_size; > > - > > - o_comp_data->comp_buf = jpeg_data->data.bufs_head; > > - o_comp_data->comp_buf_size = jpeg_size; > > - o_comp_data->is_lossy = TRUE; > > - > > - stat_compress_add(&DCC_TO_DC(dcc)->jpeg_stat, start_time, > > src->stride > > * src->y, > > - o_comp_data->comp_buf_size); > > - return TRUE; > > - } > > - > > - lz_data->data.bufs_head = jpeg_data->data.bufs_tail; > > - lz_data->data.bufs_tail = lz_data->data.bufs_head; > > - > > - comp_head_filled = jpeg_size % sizeof(lz_data->data.bufs_head->buf); > > - comp_head_left = sizeof(lz_data->data.bufs_head->buf) - > > comp_head_filled; > > - lz_out_start_byte = lz_data->data.bufs_head->buf.bytes + > > comp_head_filled; > > - > > - lz_data->data.dcc = dcc; > > - > > - lz_data->data.u.lines_data.chunks = src->data; > > - lz_data->data.u.lines_data.stride = src->stride; > > - lz_data->data.u.lines_data.next = 0; > > - lz_data->data.u.lines_data.reverse = 0; > > - > > - alpha_lz_size = lz_encode(lz, LZ_IMAGE_TYPE_XXXA, src->x, src->y, > > - !!(src->flags & > > SPICE_BITMAP_FLAGS_TOP_DOWN), > > - NULL, 0, src->stride, > > - lz_out_start_byte, > > - comp_head_left); > > - > > - // the compressed buffer is bigger than the original data > > - if ((jpeg_size + alpha_lz_size) > (src->y * src->stride)) { > > - longjmp(jpeg_data->data.jmp_env, 1); > > - } > > - > > - dest->descriptor.type = SPICE_IMAGE_TYPE_JPEG_ALPHA; > > - dest->u.jpeg_alpha.flags = 0; > > - if (src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN) { > > - dest->u.jpeg_alpha.flags |= SPICE_JPEG_ALPHA_FLAGS_TOP_DOWN; > > - } > > - > > - dest->u.jpeg_alpha.jpeg_size = jpeg_size; > > - dest->u.jpeg_alpha.data_size = jpeg_size + alpha_lz_size; > > - > > - o_comp_data->comp_buf = jpeg_data->data.bufs_head; > > - o_comp_data->comp_buf_size = jpeg_size + alpha_lz_size; > > - o_comp_data->is_lossy = TRUE; > > - stat_compress_add(&DCC_TO_DC(dcc)->jpeg_alpha_stat, start_time, src > > ->stride * src->y, > > - o_comp_data->comp_buf_size); > > - return TRUE; > > -} > > - > > -#ifdef USE_LZ4 > > -static int red_lz4_compress_image(DisplayChannelClient *dcc, SpiceImage > > *dest, > > - SpiceBitmap *src, compress_send_data_t* > > o_comp_data, > > - uint32_t group_id) > > -{ > > - Lz4Data *lz4_data = &dcc->lz4_data; > > - Lz4EncoderContext *lz4 = dcc->lz4; > > - int lz4_size = 0; > > - > > -#ifdef COMPRESS_STAT > > - stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->lz4_stat.clock); > > -#endif > > - > > - lz4_data->data.bufs_tail = compress_buf_new(); > > - lz4_data->data.bufs_head = lz4_data->data.bufs_tail; > > - > > - if (!lz4_data->data.bufs_head) { > > - spice_warning("failed to allocate compress buffer"); > > - return FALSE; > > - } > > - > > - lz4_data->data.bufs_head->send_next = NULL; > > - lz4_data->data.dcc = dcc; > > - > > - if (setjmp(lz4_data->data.jmp_env)) { > > - while (lz4_data->data.bufs_head) { > > - RedCompressBuf *buf = lz4_data->data.bufs_head; > > - lz4_data->data.bufs_head = buf->send_next; > > - compress_buf_free(buf); > > - } > > - return FALSE; > > - } > > - > > - if (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE) { > > - spice_chunks_linearize(src->data); > > - } > > - > > - lz4_data->data.u.lines_data.chunks = src->data; > > - lz4_data->data.u.lines_data.stride = src->stride; > > - lz4_data->data.u.lines_data.next = 0; > > - lz4_data->data.u.lines_data.reverse = 0; > > - /* fixme remove? lz4_data->usr.more_lines = lz4_usr_more_lines; */ > > - > > - lz4_size = lz4_encode(lz4, src->y, src->stride, > > lz4_data->data.bufs_head > > ->buf.bytes, > > - sizeof(lz4_data->data.bufs_head->buf), > > - src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN, src > > ->format); > > - > > - // the compressed buffer is bigger than the original data > > - if (lz4_size > (src->y * src->stride)) { > > - longjmp(lz4_data->data.jmp_env, 1); > > - } > > - > > - dest->descriptor.type = SPICE_IMAGE_TYPE_LZ4; > > - dest->u.lz4.data_size = lz4_size; > > - > > - o_comp_data->comp_buf = lz4_data->data.bufs_head; > > - o_comp_data->comp_buf_size = lz4_size; > > - > > - stat_compress_add(&DCC_TO_DC(dcc)->lz4_stat, start_time, src->stride * > > src->y, > > - o_comp_data->comp_buf_size); > > - return TRUE; > > -} > > -#endif > > - > > -static inline int red_quic_compress_image(DisplayChannelClient *dcc, > > SpiceImage *dest, > > - SpiceBitmap *src, > > compress_send_data_t* o_comp_data, > > - uint32_t group_id) > > -{ > > - QuicData *quic_data = &dcc->quic_data; > > - QuicContext *quic = dcc->quic; > > - volatile QuicImageType type; > > - int size, stride; > > - > > -#ifdef COMPRESS_STAT > > - stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->quic_stat.clock); > > -#endif > > - > > - switch (src->format) { > > - case SPICE_BITMAP_FMT_32BIT: > > - type = QUIC_IMAGE_TYPE_RGB32; > > - break; > > - case SPICE_BITMAP_FMT_RGBA: > > - type = QUIC_IMAGE_TYPE_RGBA; > > - break; > > - case SPICE_BITMAP_FMT_16BIT: > > - type = QUIC_IMAGE_TYPE_RGB16; > > - break; > > - case SPICE_BITMAP_FMT_24BIT: > > - type = QUIC_IMAGE_TYPE_RGB24; > > - break; > > - default: > > - return FALSE; > > - } > > - > > - quic_data->data.bufs_tail = compress_buf_new(); > > - quic_data->data.bufs_head = quic_data->data.bufs_tail; > > - quic_data->data.dcc = dcc; > > - > > - if (setjmp(quic_data->data.jmp_env)) { > > - while (quic_data->data.bufs_head) { > > - RedCompressBuf *buf = quic_data->data.bufs_head; > > - quic_data->data.bufs_head = buf->send_next; > > - compress_buf_free(buf); > > - } > > - return FALSE; > > - } > > - > > - if (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE) { > > - spice_chunks_linearize(src->data); > > - } > > - > > - quic_data->data.u.lines_data.chunks = src->data; > > - quic_data->data.u.lines_data.stride = src->stride; > > - if ((src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { > > - quic_data->data.u.lines_data.next = 0; > > - quic_data->data.u.lines_data.reverse = 0; > > - stride = src->stride; > > - } else { > > - quic_data->data.u.lines_data.next = src->data->num_chunks - 1; > > - quic_data->data.u.lines_data.reverse = 1; > > - stride = -src->stride; > > - } > > - size = quic_encode(quic, type, src->x, src->y, NULL, 0, stride, > > - quic_data->data.bufs_head->buf.words, > > - > > G_N_ELEMENTS(quic_data->data.bufs_head->buf.words)); > > - > > - // the compressed buffer is bigger than the original data > > - if ((size << 2) > (src->y * src->stride)) { > > - longjmp(quic_data->data.jmp_env, 1); > > - } > > - > > - dest->descriptor.type = SPICE_IMAGE_TYPE_QUIC; > > - dest->u.quic.data_size = size << 2; > > - > > - o_comp_data->comp_buf = quic_data->data.bufs_head; > > - o_comp_data->comp_buf_size = size << 2; > > - > > - stat_compress_add(&DCC_TO_DC(dcc)->quic_stat, start_time, src->stride > > * > > src->y, > > - o_comp_data->comp_buf_size); > > - return TRUE; > > -} > > - > > -#define MIN_SIZE_TO_COMPRESS 54 > > -#define MIN_DIMENSION_TO_QUIC 3 > > -static inline int red_compress_image(DisplayChannelClient *dcc, > > - SpiceImage *dest, SpiceBitmap *src, > > Drawable *drawable, > > - int can_lossy, > > - compress_send_data_t* o_comp_data) > > -{ > > - DisplayChannel *display_channel = DCC_TO_DC(dcc); > > - SpiceImageCompression image_compression = dcc->image_compression; > > - int quic_compress = FALSE; > > - > > - if ((image_compression == SPICE_IMAGE_COMPRESSION_OFF) || > > - ((src->y * src->stride) < MIN_SIZE_TO_COMPRESS)) { // TODO: change > > the size cond > > - return FALSE; > > - } else if (image_compression == SPICE_IMAGE_COMPRESSION_QUIC) { > > - if (bitmap_fmt_is_plt(src->format)) { > > - return FALSE; > > - } else { > > - quic_compress = TRUE; > > - } > > - } else { > > - /* > > - lz doesn't handle (1) bitmaps with strides that are larger > > than > > the width > > - of the image in bytes (2) unstable bitmaps > > - */ > > - if (bitmap_has_extra_stride(src) || (src->data->flags & > > SPICE_CHUNKS_FLAGS_UNSTABLE)) { > > - if ((image_compression == SPICE_IMAGE_COMPRESSION_LZ) || > > - (image_compression == SPICE_IMAGE_COMPRESSION_GLZ) || > > - (image_compression == SPICE_IMAGE_COMPRESSION_LZ4) || > > - bitmap_fmt_is_plt(src->format)) { > > - return FALSE; > > - } else { > > - quic_compress = TRUE; > > - } > > - } else { > > - if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) || > > - (image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ)) { > > - if ((src->x < MIN_DIMENSION_TO_QUIC) || (src->y < > > MIN_DIMENSION_TO_QUIC)) { > > - quic_compress = FALSE; > > - } else { > > - if (drawable->copy_bitmap_graduality == > > BITMAP_GRADUAL_INVALID) { > > - quic_compress = bitmap_fmt_has_graduality(src > > ->format) && > > - bitmap_get_graduality_level(src) == > > BITMAP_GRADUAL_HIGH; > > - } else { > > - quic_compress = (drawable->copy_bitmap_graduality > > == > > BITMAP_GRADUAL_HIGH); > > - } > > - } > > - } else { > > - quic_compress = FALSE; > > - } > > - } > > - } > > - > > - if (quic_compress) { > > -#ifdef COMPRESS_DEBUG > > - spice_info("QUIC compress"); > > -#endif > > - // if bitmaps is picture-like, compress it using jpeg > > - if (can_lossy && display_channel->enable_jpeg && > > - ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) || > > - (image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ))) { > > - // if we use lz for alpha, the stride can't be extra > > - if (src->format != SPICE_BITMAP_FMT_RGBA || > > !bitmap_has_extra_stride(src)) { > > - return red_jpeg_compress_image(dcc, dest, > > - src, o_comp_data, drawable > > ->group_id); > > - } > > - } > > - return red_quic_compress_image(dcc, dest, > > - src, o_comp_data, > > drawable->group_id); > > - } else { > > - int glz; > > - int ret; > > - if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ) || > > - (image_compression == SPICE_IMAGE_COMPRESSION_GLZ)) { > > - glz = bitmap_fmt_has_graduality(src->format) && ( > > - (src->x * src->y) < glz_enc_dictionary_get_size( > > - dcc->glz_dict->dict)); > > - } else if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) > > || > > - (image_compression == SPICE_IMAGE_COMPRESSION_LZ) || > > - (image_compression == SPICE_IMAGE_COMPRESSION_LZ4)) { > > - glz = FALSE; > > - } else { > > - spice_error("invalid image compression type %u", > > image_compression); > > - return FALSE; > > - } > > - > > - if (glz) { > > - /* using the global dictionary only if it is not frozen */ > > - pthread_rwlock_rdlock(&dcc->glz_dict->encode_lock); > > - if (!dcc->glz_dict->migrate_freeze) { > > - ret = red_glz_compress_image(dcc, > > - dest, src, > > - drawable, o_comp_data); > > - } else { > > - glz = FALSE; > > - } > > - pthread_rwlock_unlock(&dcc->glz_dict->encode_lock); > > - } > > - > > - if (!glz) { > > -#ifdef USE_LZ4 > > - if (image_compression == SPICE_IMAGE_COMPRESSION_LZ4 && > > - bitmap_fmt_is_rgb(src->format) && > > - red_channel_client_test_remote_cap(&dcc->common.base, > > - SPICE_DISPLAY_CAP_LZ4_COMPRESSION)) { > > - ret = red_lz4_compress_image(dcc, dest, src, o_comp_data, > > - drawable->group_id); > > - } else > > -#endif > > - ret = red_lz_compress_image(dcc, dest, src, o_comp_data, > > - drawable->group_id); > > -#ifdef COMPRESS_DEBUG > > - spice_info("LZ LOCAL compress"); > > -#endif > > - } > > -#ifdef COMPRESS_DEBUG > > - else { > > - spice_info("LZ global compress fmt=%d", src->format); > > - } > > -#endif > > - return ret; > > - } > > -} > > - > > int dcc_pixmap_cache_unlocked_add(DisplayChannelClient *dcc, uint64_t id, > > uint32_t size, int lossy) > > { > > PixmapCache *cache = dcc->pixmap_cache; > > @@ -3043,7 +2383,7 @@ static FillBitsType fill_bits(DisplayChannelClient > > *dcc, > > SpiceMarshaller *m, > > in order to prevent starvation in the client between > > pixmap_cache > > and > > global dictionary (in cases of multiple monitors) */ > > if (reds_stream_get_family(rcc->stream) == AF_UNIX || > > - !red_compress_image(dcc, &image, &simage->u.bitmap, > > + !dcc_compress_image(dcc, &image, &simage->u.bitmap, > > drawable, can_lossy, &comp_send_data)) { > > SpicePalette *palette; > > > > @@ -3053,7 +2393,7 @@ static FillBitsType fill_bits(DisplayChannelClient > > *dcc, > > SpiceMarshaller *m, > > bitmap->flags = bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN; > > > > palette = bitmap->palette; > > - fill_palette(dcc, palette, &bitmap->flags); > > + dcc_palette_cache_palette(dcc, palette, &bitmap->flags); > > spice_marshall_Image(m, &image, > > &bitmap_palette_out, &lzplt_palette_out); > > spice_assert(lzplt_palette_out == NULL); > > @@ -5021,11 +4361,11 @@ static void red_marshall_image(RedChannelClient > > *rcc, > > SpiceMarshaller *m, ImageI > > } > > > > if (lossy_comp) { > > - comp_succeeded = red_jpeg_compress_image(dcc, &red_image, > > + comp_succeeded = dcc_compress_image_jpeg(dcc, &red_image, > > &bitmap, &comp_send_data, > > worker > > ->mem_slots.internal_groupslot_id); > > } else if (quic_comp) { > > - comp_succeeded = red_quic_compress_image(dcc, &red_image, &bitmap, > > + comp_succeeded = dcc_compress_image_quic(dcc, &red_image, &bitmap, > > &comp_send_data, > > worker > > ->mem_slots.internal_groupslot_id); > > #ifdef USE_LZ4 > > @@ -5033,12 +4373,12 @@ static void red_marshall_image(RedChannelClient > > *rcc, > > SpiceMarshaller *m, ImageI > > bitmap_fmt_is_rgb(bitmap.format) && > > red_channel_client_test_remote_cap(&dcc->common.base, > > > > SPICE_DISPLAY_CAP_LZ4_COMPRESSION)) { > > - comp_succeeded = red_lz4_compress_image(dcc, &red_image, &bitmap, > > + comp_succeeded = dcc_compress_image_lz4(dcc, &red_image, &bitmap, > > &comp_send_data, > > worker > > ->mem_slots.internal_groupslot_id); > > #endif > > } else if (comp_mode != SPICE_IMAGE_COMPRESSION_OFF) { > > - comp_succeeded = red_lz_compress_image(dcc, &red_image, &bitmap, > > + comp_succeeded = dcc_compress_image_lz(dcc, &red_image, &bitmap, > > &comp_send_data, > > worker > > ->mem_slots.internal_groupslot_id); > > } > > @@ -5286,7 +4626,7 @@ static void > > display_channel_send_item(RedChannelClient > > *rcc, PipeItem *pipe_item > > display_channel_marshall_reset_cache(rcc, m); > > break; > > case PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE: > > - red_reset_palette_cache(dcc); > > + dcc_palette_cache_reset(dcc); > > red_channel_client_init_send_data(rcc, > > SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES, NULL); > > break; > > case PIPE_ITEM_TYPE_CREATE_SURFACE: { > > @@ -5355,7 +4695,7 @@ static void > > display_channel_client_on_disconnect(RedChannelClient *rcc) > > pixmap_cache_unref(dcc->pixmap_cache); > > dcc->pixmap_cache = NULL; > > red_release_glz(dcc); > > - red_reset_palette_cache(dcc); > > + dcc_palette_cache_reset(dcc); > > free(dcc->send_data.stream_outbuf); > > free(dcc->send_data.free_list.res); > > dcc_destroy_stream_agents(dcc); > > @@ -6944,7 +6284,7 @@ static void handle_dev_oom(void *opaque, void > > *payload) > > RedChannel *display_red_channel = > > &worker->display_channel->common.base; > > int ring_is_empty; > > > > - spice_assert(worker->running); > > + spice_return_if_fail(worker->running); > > // streams? but without streams also leak > > spice_debug("OOM1 #draw=%u, #red_draw=%u, #glz_draw=%u current %u > > pipes > > %u", > > display->drawable_count, > > > ACK > Merged Frediano _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel