[Spice-commits] 6 commits - server/dcc-encoders.c server/dcc-encoders.h server/dcc-send.c server/dcc.c server/dcc.h server/display-channel.c server/display-channel.h server/red-worker.c

Frediano Ziglio fziglio at kemper.freedesktop.org
Tue Jun 14 14:10:02 UTC 2016


 server/dcc-encoders.c    |  413 ++++++++++++++++++++++++++++++++++++-----------
 server/dcc-encoders.h    |   76 ++++++--
 server/dcc-send.c        |   10 -
 server/dcc.c             |  213 +++---------------------
 server/dcc.h             |    9 -
 server/display-channel.c |   89 +---------
 server/display-channel.h |   11 -
 server/red-worker.c      |    4 
 8 files changed, 424 insertions(+), 401 deletions(-)

New commits:
commit 81f3d44ee777ab143a2d1dde03565d2e31a6b45a
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Mon Jun 6 08:28:22 2016 +0100

    Move image_encoders_compress_glz to dcc-encoders.c
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/dcc-encoders.c b/server/dcc-encoders.c
index d33ddbd..4de780d 100644
--- a/server/dcc-encoders.c
+++ b/server/dcc-encoders.c
@@ -1051,6 +1051,139 @@ int image_encoders_compress_lz4(ImageEncoders *enc, SpiceImage *dest,
 }
 #endif
 
+/* 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(ImageEncoders *enc, 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->encoders == enc) {
+            return ret;
+        }
+    }
+
+    ret = spice_new(RedGlzDrawable, 1);
+
+    ret->encoders = enc;
+    ret->red_drawable = red_drawable_ref(drawable->red_drawable);
+    ret->drawable = drawable;
+    ret->instances_count = 0;
+    ring_init(&ret->instances);
+
+    ring_item_init(&ret->link);
+    ring_item_init(&ret->drawable_link);
+    ring_add_before(&ret->link, &enc->glz_drawables);
+    ring_add(&drawable->glz_ring, &ret->drawable_link);
+    enc->shared_data->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 image_encoders_compress_glz(ImageEncoders *enc,
+                                SpiceImage *dest, SpiceBitmap *src, Drawable *drawable,
+                                compress_send_data_t* o_comp_data,
+                                gboolean enable_zlib_glz_wrap)
+{
+    stat_start_time_t start_time;
+    stat_start_time_init(&start_time, &enc->shared_data->zlib_glz_stat);
+    spice_assert(bitmap_fmt_is_rgb(src->format));
+    GlzData *glz_data = &enc->glz_data;
+    ZlibData *zlib_data;
+    LzImageType type = bitmap_fmt_to_lz_image_type[src->format];
+    RedGlzDrawable *glz_drawable;
+    GlzDrawableInstanceItem *glz_drawable_instance;
+    int glz_size;
+    int zlib_size;
+
+#ifdef COMPRESS_DEBUG
+    spice_info("LZ global compress fmt=%d", src->format);
+#endif
+
+    encoder_data_init(&glz_data->data);
+
+    glz_drawable = get_glz_drawable(enc, 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(enc->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(&enc->shared_data->glz_stat, start_time, src->stride * src->y, glz_size);
+
+    if (!enable_zlib_glz_wrap || (glz_size < MIN_GLZ_SIZE_FOR_ZLIB)) {
+        goto glz;
+    }
+    stat_start_time_init(&start_time, &enc->shared_data->zlib_glz_stat);
+    zlib_data = &enc->zlib_data;
+
+    encoder_data_init(&zlib_data->data);
+
+    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(enc->zlib, enc->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) {
+        encoder_data_reset(&zlib_data->data);
+        goto glz;
+    } else {
+        encoder_data_reset(&glz_data->data);
+    }
+
+    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(&enc->shared_data->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;
+}
+
 void image_encoder_shared_init(ImageEncoderSharedData *shared_data)
 {
     clockid_t stat_clock = CLOCK_THREAD_CPUTIME_ID;
diff --git a/server/dcc-encoders.h b/server/dcc-encoders.h
index bea5cca..655c1b3 100644
--- a/server/dcc-encoders.h
+++ b/server/dcc-encoders.h
@@ -231,6 +231,10 @@ int image_encoders_compress_jpeg(ImageEncoders *enc, SpiceImage *dest,
                                  SpiceBitmap *src, compress_send_data_t* o_comp_data);
 int image_encoders_compress_lz4(ImageEncoders *enc, SpiceImage *dest,
                                 SpiceBitmap *src, compress_send_data_t* o_comp_data);
+int image_encoders_compress_glz(ImageEncoders *enc,
+                                SpiceImage *dest, SpiceBitmap *src, struct Drawable *drawable,
+                                compress_send_data_t* o_comp_data,
+                                gboolean enable_zlib_glz_wrap);
 
 #define RED_RELEASE_BUNCH_SIZE 64
 
diff --git a/server/dcc.c b/server/dcc.c
index 9007afb..6511ce5 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -632,153 +632,6 @@ void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t 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(ImageEncoders *enc, 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->encoders == enc) {
-            return ret;
-        }
-    }
-
-    ret = spice_new(RedGlzDrawable, 1);
-
-    ret->encoders = enc;
-    ret->red_drawable = red_drawable_ref(drawable->red_drawable);
-    ret->drawable = drawable;
-    ret->instances_count = 0;
-    ring_init(&ret->instances);
-
-    ring_item_init(&ret->link);
-    ring_item_init(&ret->drawable_link);
-    ring_add_before(&ret->link, &enc->glz_drawables);
-    ring_add(&drawable->glz_ring, &ret->drawable_link);
-    enc->shared_data->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;
-}
-
-static const LzImageType bitmap_fmt_to_lz_image_type[] = {
-    LZ_IMAGE_TYPE_INVALID,
-    LZ_IMAGE_TYPE_PLT1_LE,
-    LZ_IMAGE_TYPE_PLT1_BE,
-    LZ_IMAGE_TYPE_PLT4_LE,
-    LZ_IMAGE_TYPE_PLT4_BE,
-    LZ_IMAGE_TYPE_PLT8,
-    LZ_IMAGE_TYPE_RGB16,
-    LZ_IMAGE_TYPE_RGB24,
-    LZ_IMAGE_TYPE_RGB32,
-    LZ_IMAGE_TYPE_RGBA,
-    LZ_IMAGE_TYPE_A8
-};
-
-#define MIN_GLZ_SIZE_FOR_ZLIB 100
-
-static int image_encoders_compress_glz(ImageEncoders *enc,
-                                       SpiceImage *dest, SpiceBitmap *src, Drawable *drawable,
-                                       compress_send_data_t* o_comp_data,
-                                       gboolean enable_zlib_glz_wrap)
-{
-    stat_start_time_t start_time;
-    stat_start_time_init(&start_time, &enc->shared_data->zlib_glz_stat);
-    spice_assert(bitmap_fmt_is_rgb(src->format));
-    GlzData *glz_data = &enc->glz_data;
-    ZlibData *zlib_data;
-    LzImageType type = bitmap_fmt_to_lz_image_type[src->format];
-    RedGlzDrawable *glz_drawable;
-    GlzDrawableInstanceItem *glz_drawable_instance;
-    int glz_size;
-    int zlib_size;
-
-#ifdef COMPRESS_DEBUG
-    spice_info("LZ global compress fmt=%d", src->format);
-#endif
-
-    encoder_data_init(&glz_data->data);
-
-    glz_drawable = get_glz_drawable(enc, 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(enc->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(&enc->shared_data->glz_stat, start_time, src->stride * src->y, glz_size);
-
-    if (!enable_zlib_glz_wrap || (glz_size < MIN_GLZ_SIZE_FOR_ZLIB)) {
-        goto glz;
-    }
-    stat_start_time_init(&start_time, &enc->shared_data->zlib_glz_stat);
-    zlib_data = &enc->zlib_data;
-
-    encoder_data_init(&zlib_data->data);
-
-    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(enc->zlib, enc->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) {
-        encoder_data_reset(&zlib_data->data);
-        goto glz;
-    } else {
-        encoder_data_reset(&glz_data->data);
-    }
-
-    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(&enc->shared_data->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;
-}
-
 #define MIN_DIMENSION_TO_QUIC 3
 /**
  * quic doesn't handle:
commit cb8e832c87c28f4272855e350009930b020fb43a
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Mon Jun 6 08:22:45 2016 +0100

    Make dcc_compress_image_glz independent to DisplayChannelClient
    
    Also rename to image_encoders_compress_glz
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/dcc.c b/server/dcc.c
index 6060b7d..9007afb 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -698,15 +698,15 @@ static const LzImageType bitmap_fmt_to_lz_image_type[] = {
 
 #define MIN_GLZ_SIZE_FOR_ZLIB 100
 
-static int dcc_compress_image_glz(DisplayChannelClient *dcc,
-                                  SpiceImage *dest, SpiceBitmap *src, Drawable *drawable,
-                                  compress_send_data_t* o_comp_data)
+static int image_encoders_compress_glz(ImageEncoders *enc,
+                                       SpiceImage *dest, SpiceBitmap *src, Drawable *drawable,
+                                       compress_send_data_t* o_comp_data,
+                                       gboolean enable_zlib_glz_wrap)
 {
-    DisplayChannel *display_channel = DCC_TO_DC(dcc);
     stat_start_time_t start_time;
-    stat_start_time_init(&start_time, &display_channel->encoder_globals.zlib_glz_stat);
+    stat_start_time_init(&start_time, &enc->shared_data->zlib_glz_stat);
     spice_assert(bitmap_fmt_is_rgb(src->format));
-    GlzData *glz_data = &dcc->encoders.glz_data;
+    GlzData *glz_data = &enc->glz_data;
     ZlibData *zlib_data;
     LzImageType type = bitmap_fmt_to_lz_image_type[src->format];
     RedGlzDrawable *glz_drawable;
@@ -720,7 +720,7 @@ static int dcc_compress_image_glz(DisplayChannelClient *dcc,
 
     encoder_data_init(&glz_data->data);
 
-    glz_drawable = get_glz_drawable(&dcc->encoders, drawable);
+    glz_drawable = get_glz_drawable(enc, drawable);
     glz_drawable_instance = add_glz_drawable_instance(glz_drawable);
 
     glz_data->data.u.lines_data.chunks = src->data;
@@ -728,27 +728,27 @@ static int dcc_compress_image_glz(DisplayChannelClient *dcc,
     glz_data->data.u.lines_data.next = 0;
     glz_data->data.u.lines_data.reverse = 0;
 
-    glz_size = glz_encode(dcc->encoders.glz, type, src->x, src->y,
+    glz_size = glz_encode(enc->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->encoder_globals.glz_stat, start_time, src->stride * src->y, glz_size);
+    stat_compress_add(&enc->shared_data->glz_stat, start_time, src->stride * src->y, glz_size);
 
-    if (!display_channel->enable_zlib_glz_wrap || (glz_size < MIN_GLZ_SIZE_FOR_ZLIB)) {
+    if (!enable_zlib_glz_wrap || (glz_size < MIN_GLZ_SIZE_FOR_ZLIB)) {
         goto glz;
     }
-    stat_start_time_init(&start_time, &display_channel->encoder_globals.zlib_glz_stat);
-    zlib_data = &dcc->encoders.zlib_data;
+    stat_start_time_init(&start_time, &enc->shared_data->zlib_glz_stat);
+    zlib_data = &enc->zlib_data;
 
     encoder_data_init(&zlib_data->data);
 
     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->encoders.zlib, dcc->encoders.zlib_level,
+    zlib_size = zlib_encode(enc->zlib, enc->zlib_level,
                             glz_size, zlib_data->data.bufs_head->buf.bytes,
                             sizeof(zlib_data->data.bufs_head->buf));
 
@@ -767,7 +767,7 @@ static int dcc_compress_image_glz(DisplayChannelClient *dcc,
     o_comp_data->comp_buf = zlib_data->data.bufs_head;
     o_comp_data->comp_buf_size = zlib_size;
 
-    stat_compress_add(&display_channel->encoder_globals.zlib_glz_stat, start_time, glz_size, zlib_size);
+    stat_compress_add(&enc->shared_data->zlib_glz_stat, start_time, glz_size, zlib_size);
     return TRUE;
 glz:
     dest->descriptor.type = SPICE_IMAGE_TYPE_GLZ_RGB;
@@ -894,7 +894,8 @@ int dcc_compress_image(DisplayChannelClient *dcc,
             pthread_rwlock_rdlock(&dcc->encoders.glz_dict->encode_lock);
             frozen = dcc->encoders.glz_dict->migrate_freeze;
             if (!frozen) {
-                success = dcc_compress_image_glz(dcc, dest, src, drawable, o_comp_data);
+                success = image_encoders_compress_glz(&dcc->encoders, dest, src, drawable, o_comp_data,
+                                                      display_channel->enable_zlib_glz_wrap);
             }
             pthread_rwlock_unlock(&dcc->encoders.glz_dict->encode_lock);
             if (!frozen) {
commit 108d11f4aaabbabc42d80b2e7231db0f2ce823ce
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Tue Jun 7 10:35:23 2016 +0100

    Move others glz fields to dcc-encoders
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/dcc-encoders.c b/server/dcc-encoders.c
index 7497029..d33ddbd 100644
--- a/server/dcc-encoders.c
+++ b/server/dcc-encoders.c
@@ -26,8 +26,8 @@
 
 #define ZLIB_DEFAULT_COMPRESSION_LEVEL 3
 
-static void dcc_free_glz_drawable_instance(DisplayChannelClient *dcc,
-                                           GlzDrawableInstanceItem *item);
+static void image_encoders_free_glz_drawable_instance(ImageEncoders *enc,
+                                                      GlzDrawableInstanceItem *instance);
 
 static SPICE_GNUC_NORETURN SPICE_GNUC_PRINTF(2, 3) void
 quic_usr_error(QuicUsrContext *usr, const char *fmt, ...)
@@ -329,10 +329,10 @@ static void glz_usr_free_image(GlzEncoderUsrContext *usr, GlzUsrImageContext *im
 {
     GlzData *lz_data = (GlzData *)usr;
     GlzDrawableInstanceItem *glz_drawable_instance = (GlzDrawableInstanceItem *)image;
-    DisplayChannelClient *drawable_cc = glz_drawable_instance->glz_drawable->dcc;
-    DisplayChannelClient *this_cc = SPICE_CONTAINEROF(lz_data, DisplayChannelClient, encoders.glz_data);
-    if (this_cc == drawable_cc) {
-        dcc_free_glz_drawable_instance(drawable_cc, glz_drawable_instance);
+    ImageEncoders *drawable_enc = glz_drawable_instance->glz_drawable->encoders;
+    ImageEncoders *this_enc = SPICE_CONTAINEROF(lz_data, ImageEncoders, glz_data);
+    if (this_enc == drawable_enc) {
+        image_encoders_free_glz_drawable_instance(drawable_enc, glz_drawable_instance);
     } else {
         /* The glz dictionary is shared between all DisplayChannelClient
          * instances that belong to the same client, and glz_usr_free_image
@@ -341,10 +341,10 @@ static void glz_usr_free_image(GlzEncoderUsrContext *usr, GlzUsrImageContext *im
          * called from any DisplayChannelClient thread, hence the need for
          * this check.
          */
-        pthread_mutex_lock(&drawable_cc->glz_drawables_inst_to_free_lock);
+        pthread_mutex_lock(&drawable_enc->glz_drawables_inst_to_free_lock);
         ring_add_before(&glz_drawable_instance->free_link,
-                        &drawable_cc->glz_drawables_inst_to_free);
-        pthread_mutex_unlock(&drawable_cc->glz_drawables_inst_to_free_lock);
+                        &drawable_enc->glz_drawables_inst_to_free);
+        pthread_mutex_unlock(&drawable_enc->glz_drawables_inst_to_free_lock);
     }
 }
 
@@ -403,6 +403,10 @@ void image_encoders_init(ImageEncoders *enc, ImageEncoderSharedData *shared_data
     spice_assert(shared_data);
     enc->shared_data = shared_data;
 
+    ring_init(&enc->glz_drawables);
+    ring_init(&enc->glz_drawables_inst_to_free);
+    pthread_mutex_init(&enc->glz_drawables_inst_to_free_lock, NULL);
+
     image_encoders_init_glz_data(enc);
     image_encoders_init_quic(enc);
     image_encoders_init_lz(enc);
@@ -437,10 +441,9 @@ void image_encoders_free(ImageEncoders *enc)
    it is not used by Drawable).
    NOTE - 1) can be called only by the display channel that created the drawable
           2) it is assumed that the instance was already removed from the dictionary*/
-static void dcc_free_glz_drawable_instance(DisplayChannelClient *dcc,
-                                           GlzDrawableInstanceItem *instance)
+static void image_encoders_free_glz_drawable_instance(ImageEncoders *enc,
+                                                      GlzDrawableInstanceItem *instance)
 {
-    DisplayChannel *display_channel = DCC_TO_DC(dcc);
     RedGlzDrawable *glz_drawable;
 
     spice_assert(instance);
@@ -448,7 +451,7 @@ static void dcc_free_glz_drawable_instance(DisplayChannelClient *dcc,
 
     glz_drawable = instance->glz_drawable;
 
-    spice_assert(glz_drawable->dcc == dcc);
+    spice_assert(glz_drawable->encoders == enc);
     spice_assert(glz_drawable->instances_count > 0);
 
     ring_remove(&instance->glz_link);
@@ -469,7 +472,7 @@ static void dcc_free_glz_drawable_instance(DisplayChannelClient *dcc,
             ring_remove(&glz_drawable->drawable_link);
         }
         red_drawable_unref(glz_drawable->red_drawable);
-        display_channel->glz_drawable_count--;
+        enc->shared_data->glz_drawable_count--;
         if (ring_item_is_linked(&glz_drawable->link)) {
             ring_remove(&glz_drawable->link);
         }
@@ -483,14 +486,14 @@ static void dcc_free_glz_drawable_instance(DisplayChannelClient *dcc,
  * if possible.
  * NOTE - the caller should prevent encoding using the dictionary during this operation
  */
-void dcc_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable)
+void image_encoders_free_glz_drawable(ImageEncoders *enc, RedGlzDrawable *drawable)
 {
     RingItem *head_instance = ring_get_head(&drawable->instances);
     int cont = (head_instance != NULL);
 
     while (cont) {
         if (drawable->instances_count == 1) {
-            /* Last instance: dcc_free_glz_drawable_instance will free the drawable */
+            /* Last instance: image_encoders_free_glz_drawable_instance will free the drawable */
             cont = FALSE;
         }
         GlzDrawableInstanceItem *instance = SPICE_CONTAINEROF(head_instance,
@@ -498,11 +501,11 @@ void dcc_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable)
                                                         glz_link);
         if (!ring_item_is_linked(&instance->free_link)) {
             // the instance didn't get out from window yet
-            glz_enc_dictionary_remove_image(dcc->encoders.glz_dict->dict,
+            glz_enc_dictionary_remove_image(enc->glz_dict->dict,
                                             instance->context,
-                                            &dcc->encoders.glz_data.usr);
+                                            &enc->glz_data.usr);
         }
-        dcc_free_glz_drawable_instance(dcc, instance);
+        image_encoders_free_glz_drawable_instance(enc, instance);
 
         if (cont) {
             head_instance = ring_get_head(&drawable->instances);
@@ -515,49 +518,49 @@ void dcc_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable)
  * Drawable (their qxl drawables are released too).
  * NOTE - the caller should prevent encoding using the dictionary during the operation
  */
-int dcc_free_some_independent_glz_drawables(DisplayChannelClient *dcc)
+int image_encoders_free_some_independent_glz_drawables(ImageEncoders *enc)
 {
     RingItem *ring_link;
     int n = 0;
 
-    if (!dcc) {
+    if (!enc) {
         return 0;
     }
-    ring_link = ring_get_head(&dcc->glz_drawables);
+    ring_link = ring_get_head(&enc->glz_drawables);
     while ((n < RED_RELEASE_BUNCH_SIZE) && (ring_link != NULL)) {
         RedGlzDrawable *glz_drawable = SPICE_CONTAINEROF(ring_link, RedGlzDrawable, link);
-        ring_link = ring_next(&dcc->glz_drawables, ring_link);
+        ring_link = ring_next(&enc->glz_drawables, ring_link);
         if (!glz_drawable->drawable) {
-            dcc_free_glz_drawable(dcc, glz_drawable);
+            image_encoders_free_glz_drawable(enc, glz_drawable);
             n++;
         }
     }
     return n;
 }
 
-void dcc_free_glz_drawables_to_free(DisplayChannelClient* dcc)
+void image_encoders_free_glz_drawables_to_free(ImageEncoders* enc)
 {
     RingItem *ring_link;
 
-    if (!dcc->encoders.glz_dict) {
+    if (!enc->glz_dict) {
         return;
     }
-    pthread_mutex_lock(&dcc->glz_drawables_inst_to_free_lock);
-    while ((ring_link = ring_get_head(&dcc->glz_drawables_inst_to_free))) {
+    pthread_mutex_lock(&enc->glz_drawables_inst_to_free_lock);
+    while ((ring_link = ring_get_head(&enc->glz_drawables_inst_to_free))) {
         GlzDrawableInstanceItem *drawable_instance = SPICE_CONTAINEROF(ring_link,
                                                                  GlzDrawableInstanceItem,
                                                                  free_link);
-        dcc_free_glz_drawable_instance(dcc, drawable_instance);
+        image_encoders_free_glz_drawable_instance(enc, drawable_instance);
     }
-    pthread_mutex_unlock(&dcc->glz_drawables_inst_to_free_lock);
+    pthread_mutex_unlock(&enc->glz_drawables_inst_to_free_lock);
 }
 
 /* Clear all lz drawables - enforce their removal from the global dictionary.
    NOTE - prevents encoding using the dictionary during the operation*/
-void dcc_free_glz_drawables(DisplayChannelClient *dcc)
+void image_encoders_free_glz_drawables(ImageEncoders *enc)
 {
     RingItem *ring_link;
-    GlzSharedDictionary *glz_dict = dcc ? dcc->encoders.glz_dict : NULL;
+    GlzSharedDictionary *glz_dict = enc ? enc->glz_dict : NULL;
 
     if (!glz_dict) {
         return;
@@ -565,11 +568,11 @@ void dcc_free_glz_drawables(DisplayChannelClient *dcc)
 
     // assure no display channel is during global lz encoding
     pthread_rwlock_wrlock(&glz_dict->encode_lock);
-    while ((ring_link = ring_get_head(&dcc->glz_drawables))) {
+    while ((ring_link = ring_get_head(&enc->glz_drawables))) {
         RedGlzDrawable *drawable = SPICE_CONTAINEROF(ring_link, RedGlzDrawable, link);
         // no need to lock the to_free list, since we assured no other thread is encoding and
         // thus not other thread access the to_free list of the channel
-        dcc_free_glz_drawable(dcc, drawable);
+        image_encoders_free_glz_drawable(enc, drawable);
     }
     pthread_rwlock_unlock(&glz_dict->encode_lock);
 }
@@ -695,12 +698,11 @@ gboolean image_encoders_glz_create(ImageEncoders *enc, uint8_t id)
 }
 
 /* destroy encoder, and dictionary if no one uses it*/
-void dcc_release_glz(DisplayChannelClient *dcc)
+void image_encoders_release_glz(ImageEncoders *enc)
 {
-    ImageEncoders *enc = &dcc->encoders;
     GlzSharedDictionary *shared_dict;
 
-    dcc_free_glz_drawables(dcc);
+    image_encoders_free_glz_drawables(enc);
 
     glz_encoder_destroy(enc->glz);
     enc->glz = NULL;
diff --git a/server/dcc-encoders.h b/server/dcc-encoders.h
index 2b4d556..bea5cca 100644
--- a/server/dcc-encoders.h
+++ b/server/dcc-encoders.h
@@ -43,14 +43,13 @@ void image_encoder_shared_stat_print(const ImageEncoderSharedData *shared_data);
 
 void image_encoders_init(ImageEncoders *enc, ImageEncoderSharedData *shared_data);
 void image_encoders_free(ImageEncoders *enc);
-void             dcc_free_glz_drawable                       (DisplayChannelClient *dcc,
-                                                              RedGlzDrawable *drawable);
-int              dcc_free_some_independent_glz_drawables     (DisplayChannelClient *dcc);
-void             dcc_free_glz_drawables                      (DisplayChannelClient *dcc);
-void             dcc_free_glz_drawables_to_free              (DisplayChannelClient* dcc);
+void image_encoders_free_glz_drawable(ImageEncoders *enc, RedGlzDrawable *drawable);
+int image_encoders_free_some_independent_glz_drawables(ImageEncoders *enc);
+void image_encoders_free_glz_drawables(ImageEncoders *enc);
+void image_encoders_free_glz_drawables_to_free(ImageEncoders* enc);
 gboolean image_encoders_glz_create(ImageEncoders *enc, uint8_t id);
 void image_encoders_freeze_glz(ImageEncoders *enc);
-void             dcc_release_glz                             (DisplayChannelClient *dcc);
+void image_encoders_release_glz(ImageEncoders *enc);
 
 #define RED_COMPRESS_BUF_SIZE (1024 * 64)
 struct RedCompressBuf {
@@ -166,10 +165,12 @@ struct RedGlzDrawable {
     GlzDrawableInstanceItem instances_pool[MAX_GLZ_DRAWABLE_INSTANCES];
     Ring instances;
     uint8_t instances_count;
-    DisplayChannelClient *dcc;
+    ImageEncoders *encoders;
 };
 
 struct ImageEncoderSharedData {
+    uint32_t glz_drawable_count;
+
     stat_info_t off_stat;
     stat_info_t lz_stat;
     stat_info_t glz_stat;
@@ -208,6 +209,10 @@ struct ImageEncoders {
     GlzSharedDictionary *glz_dict;
     GlzEncoderContext *glz;
     GlzData glz_data;
+
+    Ring glz_drawables;               // all the living lz drawable, ordered by encoding time
+    Ring glz_drawables_inst_to_free;               // list of instances to be freed
+    pthread_mutex_t glz_drawables_inst_to_free_lock;
 };
 
 typedef struct compress_send_data_t {
diff --git a/server/dcc.c b/server/dcc.c
index 1cc85b5..6060b7d 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -392,10 +392,6 @@ DisplayChannelClient *dcc_new(DisplayChannel *display,
 
     dcc_init_stream_agents(dcc);
 
-    ring_init(&dcc->glz_drawables);
-    ring_init(&dcc->glz_drawables_inst_to_free);
-    pthread_mutex_init(&dcc->glz_drawables_inst_to_free_lock, NULL);
-
     image_encoders_init(&dcc->encoders, &display->encoder_globals);
 
     return dcc;
@@ -493,7 +489,7 @@ void dcc_stop(DisplayChannelClient *dcc)
 
     pixmap_cache_unref(dcc->pixmap_cache);
     dcc->pixmap_cache = NULL;
-    dcc_release_glz(dcc);
+    image_encoders_release_glz(&dcc->encoders);
     dcc_palette_cache_reset(dcc);
     free(dcc->send_data.stream_outbuf);
     free(dcc->send_data.free_list.res);
@@ -638,7 +634,7 @@ void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t surface_id)
 
 /* 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)
+static RedGlzDrawable *get_glz_drawable(ImageEncoders *enc, Drawable *drawable)
 {
     RedGlzDrawable *ret;
     RingItem *item, *next;
@@ -647,14 +643,14 @@ static RedGlzDrawable *get_glz_drawable(DisplayChannelClient *dcc, Drawable *dra
     // 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) {
+        if (ret->encoders == enc) {
             return ret;
         }
     }
 
     ret = spice_new(RedGlzDrawable, 1);
 
-    ret->dcc = dcc;
+    ret->encoders = enc;
     ret->red_drawable = red_drawable_ref(drawable->red_drawable);
     ret->drawable = drawable;
     ret->instances_count = 0;
@@ -662,9 +658,9 @@ static RedGlzDrawable *get_glz_drawable(DisplayChannelClient *dcc, Drawable *dra
 
     ring_item_init(&ret->link);
     ring_item_init(&ret->drawable_link);
-    ring_add_before(&ret->link, &dcc->glz_drawables);
+    ring_add_before(&ret->link, &enc->glz_drawables);
     ring_add(&drawable->glz_ring, &ret->drawable_link);
-    DCC_TO_DC(dcc)->glz_drawable_count++;
+    enc->shared_data->glz_drawable_count++;
     return ret;
 }
 
@@ -724,7 +720,7 @@ static int dcc_compress_image_glz(DisplayChannelClient *dcc,
 
     encoder_data_init(&glz_data->data);
 
-    glz_drawable = get_glz_drawable(dcc, drawable);
+    glz_drawable = get_glz_drawable(&dcc->encoders, drawable);
     glz_drawable_instance = add_glz_drawable_instance(glz_drawable);
 
     glz_data->data.u.lines_data.chunks = src->data;
diff --git a/server/dcc.h b/server/dcc.h
index ac6de84..e87f110 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -83,11 +83,6 @@ struct DisplayChannelClient {
         int num_pixmap_cache_items;
     } send_data;
 
-    /* global lz encoding entities */
-    Ring glz_drawables;               // all the living lz drawable, ordered by encoding time
-    Ring glz_drawables_inst_to_free;               // list of instances to be freed
-    pthread_mutex_t glz_drawables_inst_to_free_lock;
-
     uint8_t surface_client_created[NUM_SURFACES];
     QRegion surface_client_lossy_region[NUM_SURFACES];
 
diff --git a/server/display-channel.c b/server/display-channel.c
index 8c0c859..f1e8ba1 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1143,7 +1143,7 @@ void display_channel_free_glz_drawables_to_free(DisplayChannel *display)
     spice_return_if_fail(display);
 
     FOREACH_CLIENT(display, link, next, dcc) {
-        dcc_free_glz_drawables_to_free(dcc);
+        image_encoders_free_glz_drawables_to_free(&dcc->encoders);
     }
 }
 
@@ -1155,7 +1155,7 @@ void display_channel_free_glz_drawables(DisplayChannel *display)
     spice_return_if_fail(display);
 
     FOREACH_CLIENT(display, link, next, dcc) {
-        dcc_free_glz_drawables(dcc);
+        image_encoders_free_glz_drawables(&dcc->encoders);
     }
 }
 
@@ -1174,7 +1174,7 @@ static bool free_one_drawable(DisplayChannel *display, int force_glz_free)
         RingItem *glz_item, *next_item;
         RedGlzDrawable *glz;
         DRAWABLE_FOREACH_GLZ_SAFE(drawable, glz_item, next_item, glz) {
-            dcc_free_glz_drawable(glz->dcc, glz);
+            image_encoders_free_glz_drawable(glz->encoders, glz);
         }
     }
     drawable_draw(display, drawable);
@@ -1200,7 +1200,7 @@ void display_channel_free_some(DisplayChannel *display)
     GList *link, *next;
 
     spice_debug("#draw=%d, #glz_draw=%d", display->drawable_count,
-                display->glz_drawable_count);
+                display->encoder_globals.glz_drawable_count);
     FOREACH_CLIENT(display, link, next, dcc) {
         GlzSharedDictionary *glz_dict = dcc->encoders.glz_dict;
 
@@ -1208,7 +1208,7 @@ void display_channel_free_some(DisplayChannel *display)
             // encoding using the dictionary is prevented since the following operations might
             // change the dictionary
             pthread_rwlock_wrlock(&glz_dict->encode_lock);
-            n = dcc_free_some_independent_glz_drawables(dcc);
+            n = image_encoders_free_some_independent_glz_drawables(&dcc->encoders);
         }
     }
 
@@ -1853,7 +1853,7 @@ static void on_disconnect(RedChannelClient *rcc)
     // this was the last channel client
     spice_debug("#draw=%d, #glz_draw=%d",
                 display->drawable_count,
-                display->glz_drawable_count);
+                display->encoder_globals.glz_drawable_count);
 }
 
 static int handle_migrate_flush_mark(RedChannelClient *rcc)
diff --git a/server/display-channel.h b/server/display-channel.h
index db1cdba..8588583 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -183,8 +183,6 @@ struct DisplayChannel {
     _Drawable drawables[NUM_DRAWABLES];
     _Drawable *free_drawables;
 
-    uint32_t glz_drawable_count;
-
     int stream_video;
     uint32_t stream_count;
     Stream streams_buf[NUM_STREAMS];
diff --git a/server/red-worker.c b/server/red-worker.c
index c53bc15..aba3e6f 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -823,7 +823,7 @@ static void handle_dev_oom(void *opaque, void *payload)
     // streams? but without streams also leak
     spice_debug("OOM1 #draw=%u, #glz_draw=%u current %u pipes %u",
                 display->drawable_count,
-                display->glz_drawable_count,
+                display->encoder_globals.glz_drawable_count,
                 display->current_size,
                 red_channel_sum_pipes_size(display_red_channel));
     while (red_process_display(worker, &ring_is_empty)) {
@@ -835,7 +835,7 @@ static void handle_dev_oom(void *opaque, void *payload)
     }
     spice_debug("OOM2 #draw=%u, #glz_draw=%u current %u pipes %u",
                 display->drawable_count,
-                display->glz_drawable_count,
+                display->encoder_globals.glz_drawable_count,
                 display->current_size,
                 red_channel_sum_pipes_size(display_red_channel));
     red_qxl_clear_pending(worker->qxl->st, RED_DISPATCHER_PENDING_OOM);
commit 41231aa4f8edb12aabc2bba5daddf4b9fa398437
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Tue Jun 14 09:16:28 2016 +0100

    Change dcc_encoders_init to take ImageEncoders instead of DisplayChannelClient
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/dcc-encoders.c b/server/dcc-encoders.c
index c03409c..7497029 100644
--- a/server/dcc-encoders.c
+++ b/server/dcc-encoders.c
@@ -398,10 +398,8 @@ static void image_encoders_init_zlib(ImageEncoders *enc)
     }
 }
 
-void dcc_encoders_init(DisplayChannelClient *dcc, ImageEncoderSharedData *shared_data)
+void image_encoders_init(ImageEncoders *enc, ImageEncoderSharedData *shared_data)
 {
-    ImageEncoders *enc = &dcc->encoders;
-
     spice_assert(shared_data);
     enc->shared_data = shared_data;
 
diff --git a/server/dcc-encoders.h b/server/dcc-encoders.h
index 596429c..2b4d556 100644
--- a/server/dcc-encoders.h
+++ b/server/dcc-encoders.h
@@ -41,7 +41,7 @@ void image_encoder_shared_init(ImageEncoderSharedData *shared_data);
 void image_encoder_shared_stat_reset(ImageEncoderSharedData *shared_data);
 void image_encoder_shared_stat_print(const ImageEncoderSharedData *shared_data);
 
-void dcc_encoders_init(DisplayChannelClient *dcc, ImageEncoderSharedData *shared_data);
+void image_encoders_init(ImageEncoders *enc, ImageEncoderSharedData *shared_data);
 void image_encoders_free(ImageEncoders *enc);
 void             dcc_free_glz_drawable                       (DisplayChannelClient *dcc,
                                                               RedGlzDrawable *drawable);
diff --git a/server/dcc.c b/server/dcc.c
index d73b742..1cc85b5 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -396,7 +396,7 @@ DisplayChannelClient *dcc_new(DisplayChannel *display,
     ring_init(&dcc->glz_drawables_inst_to_free);
     pthread_mutex_init(&dcc->glz_drawables_inst_to_free_lock, NULL);
 
-    dcc_encoders_init(dcc, &display->encoder_globals);
+    image_encoders_init(&dcc->encoders, &display->encoder_globals);
 
     return dcc;
 }
commit b46984ed30e69965448a6e98304f703cf80b44e1
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Tue Jun 14 09:15:47 2016 +0100

    Move some glz fields to ImageEncoders
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/dcc-encoders.c b/server/dcc-encoders.c
index c79cf58..c03409c 100644
--- a/server/dcc-encoders.c
+++ b/server/dcc-encoders.c
@@ -330,7 +330,7 @@ static void glz_usr_free_image(GlzEncoderUsrContext *usr, GlzUsrImageContext *im
     GlzData *lz_data = (GlzData *)usr;
     GlzDrawableInstanceItem *glz_drawable_instance = (GlzDrawableInstanceItem *)image;
     DisplayChannelClient *drawable_cc = glz_drawable_instance->glz_drawable->dcc;
-    DisplayChannelClient *this_cc = SPICE_CONTAINEROF(lz_data, DisplayChannelClient, glz_data);
+    DisplayChannelClient *this_cc = SPICE_CONTAINEROF(lz_data, DisplayChannelClient, encoders.glz_data);
     if (this_cc == drawable_cc) {
         dcc_free_glz_drawable_instance(drawable_cc, glz_drawable_instance);
     } else {
@@ -348,16 +348,16 @@ static void glz_usr_free_image(GlzEncoderUsrContext *usr, GlzUsrImageContext *im
     }
 }
 
-static void dcc_init_glz_data(DisplayChannelClient *dcc)
+static void image_encoders_init_glz_data(ImageEncoders *enc)
 {
-    dcc->glz_data.usr.error = glz_usr_error;
-    dcc->glz_data.usr.warn = glz_usr_warn;
-    dcc->glz_data.usr.info = glz_usr_warn;
-    dcc->glz_data.usr.malloc = glz_usr_malloc;
-    dcc->glz_data.usr.free = glz_usr_free;
-    dcc->glz_data.usr.more_space = glz_usr_more_space;
-    dcc->glz_data.usr.more_lines = glz_usr_more_lines;
-    dcc->glz_data.usr.free_image = glz_usr_free_image;
+    enc->glz_data.usr.error = glz_usr_error;
+    enc->glz_data.usr.warn = glz_usr_warn;
+    enc->glz_data.usr.info = glz_usr_warn;
+    enc->glz_data.usr.malloc = glz_usr_malloc;
+    enc->glz_data.usr.free = glz_usr_free;
+    enc->glz_data.usr.more_space = glz_usr_more_space;
+    enc->glz_data.usr.more_lines = glz_usr_more_lines;
+    enc->glz_data.usr.free_image = glz_usr_free_image;
 }
 
 static void image_encoders_init_jpeg(ImageEncoders *enc)
@@ -405,7 +405,7 @@ void dcc_encoders_init(DisplayChannelClient *dcc, ImageEncoderSharedData *shared
     spice_assert(shared_data);
     enc->shared_data = shared_data;
 
-    dcc_init_glz_data(dcc);
+    image_encoders_init_glz_data(enc);
     image_encoders_init_quic(enc);
     image_encoders_init_lz(enc);
     image_encoders_init_jpeg(enc);
@@ -500,9 +500,9 @@ void dcc_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable)
                                                         glz_link);
         if (!ring_item_is_linked(&instance->free_link)) {
             // the instance didn't get out from window yet
-            glz_enc_dictionary_remove_image(dcc->glz_dict->dict,
+            glz_enc_dictionary_remove_image(dcc->encoders.glz_dict->dict,
                                             instance->context,
-                                            &dcc->glz_data.usr);
+                                            &dcc->encoders.glz_data.usr);
         }
         dcc_free_glz_drawable_instance(dcc, instance);
 
@@ -541,7 +541,7 @@ void dcc_free_glz_drawables_to_free(DisplayChannelClient* dcc)
 {
     RingItem *ring_link;
 
-    if (!dcc->glz_dict) {
+    if (!dcc->encoders.glz_dict) {
         return;
     }
     pthread_mutex_lock(&dcc->glz_drawables_inst_to_free_lock);
@@ -559,7 +559,7 @@ void dcc_free_glz_drawables_to_free(DisplayChannelClient* dcc)
 void dcc_free_glz_drawables(DisplayChannelClient *dcc)
 {
     RingItem *ring_link;
-    GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
+    GlzSharedDictionary *glz_dict = dcc ? dcc->encoders.glz_dict : NULL;
 
     if (!glz_dict) {
         return;
@@ -576,11 +576,11 @@ void dcc_free_glz_drawables(DisplayChannelClient *dcc)
     pthread_rwlock_unlock(&glz_dict->encode_lock);
 }
 
-void dcc_freeze_glz(DisplayChannelClient *dcc)
+void image_encoders_freeze_glz(ImageEncoders *enc)
 {
-    pthread_rwlock_wrlock(&dcc->glz_dict->encode_lock);
-    dcc->glz_dict->migrate_freeze = TRUE;
-    pthread_rwlock_unlock(&dcc->glz_dict->encode_lock);
+    pthread_rwlock_wrlock(&enc->glz_dict->encode_lock);
+    enc->glz_dict->migrate_freeze = TRUE;
+    pthread_rwlock_unlock(&enc->glz_dict->encode_lock);
 }
 
 static GlzSharedDictionary *glz_shared_dictionary_new(RedClient *client, uint8_t id,
@@ -623,82 +623,95 @@ static GlzSharedDictionary *find_glz_dictionary(RedClient *client, uint8_t dict_
 
 #define MAX_LZ_ENCODERS MAX_CACHE_CLIENTS
 
-static GlzSharedDictionary *create_glz_dictionary(DisplayChannelClient *dcc,
+static GlzSharedDictionary *create_glz_dictionary(ImageEncoders *enc,
+                                                  RedClient *client,
                                                   uint8_t id, int window_size)
 {
     spice_info("Lz Window %d Size=%d", id, window_size);
 
     GlzEncDictContext *glz_dict =
-        glz_enc_dictionary_create(window_size, MAX_LZ_ENCODERS, &dcc->glz_data.usr);
+        glz_enc_dictionary_create(window_size, MAX_LZ_ENCODERS, &enc->glz_data.usr);
 
-    return glz_shared_dictionary_new(RED_CHANNEL_CLIENT(dcc)->client, id, glz_dict);
+    return glz_shared_dictionary_new(client, id, glz_dict);
 }
 
-GlzSharedDictionary *dcc_get_glz_dictionary(DisplayChannelClient *dcc,
-                                            uint8_t id, int window_size)
+gboolean image_encoders_get_glz_dictionary(ImageEncoders *enc,
+                                           RedClient *client,
+                                           uint8_t id, int window_size)
 {
     GlzSharedDictionary *shared_dict;
 
     pthread_mutex_lock(&glz_dictionary_list_lock);
 
-    shared_dict = find_glz_dictionary(RED_CHANNEL_CLIENT(dcc)->client, id);
+    shared_dict = find_glz_dictionary(client, id);
     if (shared_dict) {
         shared_dict->refs++;
     } else {
-        shared_dict = create_glz_dictionary(dcc, id, window_size);
+        shared_dict = create_glz_dictionary(enc, client, id, window_size);
         ring_add(&glz_dictionary_list, &shared_dict->base);
     }
 
     pthread_mutex_unlock(&glz_dictionary_list_lock);
-    return shared_dict;
+    enc->glz_dict = shared_dict;
+    return shared_dict != NULL;
 }
 
-static GlzSharedDictionary *restore_glz_dictionary(DisplayChannelClient *dcc,
+static GlzSharedDictionary *restore_glz_dictionary(ImageEncoders *enc,
+                                                   RedClient *client,
                                                    uint8_t id,
                                                    GlzEncDictRestoreData *restore_data)
 {
     GlzEncDictContext *glz_dict =
-        glz_enc_dictionary_restore(restore_data, &dcc->glz_data.usr);
+        glz_enc_dictionary_restore(restore_data, &enc->glz_data.usr);
 
-    return glz_shared_dictionary_new(RED_CHANNEL_CLIENT(dcc)->client, id, glz_dict);
+    return glz_shared_dictionary_new(client, id, glz_dict);
 }
 
-GlzSharedDictionary *dcc_restore_glz_dictionary(DisplayChannelClient *dcc,
-                                                uint8_t id,
-                                                GlzEncDictRestoreData *restore_data)
+gboolean image_encoders_restore_glz_dictionary(ImageEncoders *enc,
+                                               RedClient *client,
+                                               uint8_t id,
+                                               GlzEncDictRestoreData *restore_data)
 {
     GlzSharedDictionary *shared_dict = NULL;
 
     pthread_mutex_lock(&glz_dictionary_list_lock);
 
-    shared_dict = find_glz_dictionary(RED_CHANNEL_CLIENT(dcc)->client, id);
+    shared_dict = find_glz_dictionary(client, id);
 
     if (shared_dict) {
         shared_dict->refs++;
     } else {
-        shared_dict = restore_glz_dictionary(dcc, id, restore_data);
+        shared_dict = restore_glz_dictionary(enc, client, id, restore_data);
         ring_add(&glz_dictionary_list, &shared_dict->base);
     }
 
     pthread_mutex_unlock(&glz_dictionary_list_lock);
-    return shared_dict;
+    enc->glz_dict = shared_dict;
+    return shared_dict != NULL;
+}
+
+gboolean image_encoders_glz_create(ImageEncoders *enc, uint8_t id)
+{
+    enc->glz = glz_encoder_create(id, enc->glz_dict->dict, &enc->glz_data.usr);
+    return enc->glz != NULL;
 }
 
 /* destroy encoder, and dictionary if no one uses it*/
 void dcc_release_glz(DisplayChannelClient *dcc)
 {
+    ImageEncoders *enc = &dcc->encoders;
     GlzSharedDictionary *shared_dict;
 
     dcc_free_glz_drawables(dcc);
 
-    glz_encoder_destroy(dcc->glz);
-    dcc->glz = NULL;
+    glz_encoder_destroy(enc->glz);
+    enc->glz = NULL;
 
-    if (!(shared_dict = dcc->glz_dict)) {
+    if (!(shared_dict = enc->glz_dict)) {
         return;
     }
 
-    dcc->glz_dict = NULL;
+    enc->glz_dict = NULL;
     pthread_mutex_lock(&glz_dictionary_list_lock);
     if (--shared_dict->refs != 0) {
         pthread_mutex_unlock(&glz_dictionary_list_lock);
@@ -706,7 +719,7 @@ void dcc_release_glz(DisplayChannelClient *dcc)
     }
     ring_remove(&shared_dict->base);
     pthread_mutex_unlock(&glz_dictionary_list_lock);
-    glz_enc_dictionary_destroy(shared_dict->dict, &dcc->glz_data.usr);
+    glz_enc_dictionary_destroy(shared_dict->dict, &enc->glz_data.usr);
     free(shared_dict);
 }
 
diff --git a/server/dcc-encoders.h b/server/dcc-encoders.h
index 4b89cc9..596429c 100644
--- a/server/dcc-encoders.h
+++ b/server/dcc-encoders.h
@@ -48,7 +48,8 @@ void             dcc_free_glz_drawable                       (DisplayChannelClie
 int              dcc_free_some_independent_glz_drawables     (DisplayChannelClient *dcc);
 void             dcc_free_glz_drawables                      (DisplayChannelClient *dcc);
 void             dcc_free_glz_drawables_to_free              (DisplayChannelClient* dcc);
-void             dcc_freeze_glz                              (DisplayChannelClient *dcc);
+gboolean image_encoders_glz_create(ImageEncoders *enc, uint8_t id);
+void image_encoders_freeze_glz(ImageEncoders *enc);
 void             dcc_release_glz                             (DisplayChannelClient *dcc);
 
 #define RED_COMPRESS_BUF_SIZE (1024 * 64)
@@ -79,11 +80,13 @@ typedef struct GlzSharedDictionary {
     RedClient *client; // channel clients of the same client share the dict
 } GlzSharedDictionary;
 
-GlzSharedDictionary* dcc_get_glz_dictionary                  (DisplayChannelClient *dcc,
-                                                              uint8_t id, int window_size);
-GlzSharedDictionary* dcc_restore_glz_dictionary              (DisplayChannelClient *dcc,
-                                                              uint8_t id,
-                                                              GlzEncDictRestoreData *restore_data);
+gboolean image_encoders_get_glz_dictionary(ImageEncoders *enc,
+                                           struct RedClient *client,
+                                           uint8_t id, int window_size);
+gboolean image_encoders_restore_glz_dictionary(ImageEncoders *enc,
+                                               struct RedClient *client,
+                                               uint8_t id,
+                                               GlzEncDictRestoreData *restore_data);
 
 typedef struct  {
     RedCompressBuf *bufs_head;
@@ -200,6 +203,11 @@ struct ImageEncoders {
 
     ZlibData zlib_data;
     ZlibEncoder *zlib;
+
+    /* global lz encoding entities */
+    GlzSharedDictionary *glz_dict;
+    GlzEncoderContext *glz;
+    GlzData glz_data;
 };
 
 typedef struct compress_send_data_t {
diff --git a/server/dcc-send.c b/server/dcc-send.c
index 6c10565..c0c7573 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -1859,12 +1859,12 @@ static void display_channel_marshall_migrate_data(RedChannelClient *rcc,
     memcpy(display_data.pixmap_cache_clients, dcc->pixmap_cache->sync,
            sizeof(display_data.pixmap_cache_clients));
 
-    spice_assert(dcc->glz_dict);
-    dcc_freeze_glz(dcc);
-    display_data.glz_dict_id = dcc->glz_dict->id;
-    glz_enc_dictionary_get_restore_data(dcc->glz_dict->dict,
+    spice_assert(dcc->encoders.glz_dict);
+    image_encoders_freeze_glz(&dcc->encoders);
+    display_data.glz_dict_id = dcc->encoders.glz_dict->id;
+    glz_enc_dictionary_get_restore_data(dcc->encoders.glz_dict->dict,
                                         &display_data.glz_dict_data,
-                                        &dcc->glz_data.usr);
+                                        &dcc->encoders.glz_data.usr);
 
     /* all data besided the surfaces ref */
     spice_marshaller_add(base_marshaller,
diff --git a/server/dcc.c b/server/dcc.c
index 8f44e64..d73b742 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -422,12 +422,11 @@ static int display_channel_client_wait_for_init(DisplayChannelClient *dcc)
         if (!red_channel_client_is_connected(RED_CHANNEL_CLIENT(dcc))) {
             break;
         }
-        if (dcc->pixmap_cache && dcc->glz_dict) {
+        if (dcc->pixmap_cache && dcc->encoders.glz_dict) {
             dcc->pixmap_cache_generation = dcc->pixmap_cache->generation;
             /* TODO: move common.id? if it's used for a per client structure.. */
             spice_info("creating encoder with id == %d", dcc->id);
-            dcc->glz = glz_encoder_create(dcc->id, dcc->glz_dict->dict, &dcc->glz_data.usr);
-            if (!dcc->glz) {
+            if (!image_encoders_glz_create(&dcc->encoders, dcc->id)) {
                 spice_critical("create global lz failed");
             }
             return TRUE;
@@ -711,7 +710,7 @@ static int dcc_compress_image_glz(DisplayChannelClient *dcc,
     stat_start_time_t start_time;
     stat_start_time_init(&start_time, &display_channel->encoder_globals.zlib_glz_stat);
     spice_assert(bitmap_fmt_is_rgb(src->format));
-    GlzData *glz_data = &dcc->glz_data;
+    GlzData *glz_data = &dcc->encoders.glz_data;
     ZlibData *zlib_data;
     LzImageType type = bitmap_fmt_to_lz_image_type[src->format];
     RedGlzDrawable *glz_drawable;
@@ -733,7 +732,7 @@ static int dcc_compress_image_glz(DisplayChannelClient *dcc,
     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,
+    glz_size = glz_encode(dcc->encoders.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),
@@ -893,15 +892,15 @@ int dcc_compress_image(DisplayChannelClient *dcc,
         success = image_encoders_compress_quic(&dcc->encoders, dest, src, o_comp_data);
         break;
     case SPICE_IMAGE_COMPRESSION_GLZ:
-        if ((src->x * src->y) < glz_enc_dictionary_get_size(dcc->glz_dict->dict)) {
+        if ((src->x * src->y) < glz_enc_dictionary_get_size(dcc->encoders.glz_dict->dict)) {
             int frozen;
             /* using the global dictionary only if it is not frozen */
-            pthread_rwlock_rdlock(&dcc->glz_dict->encode_lock);
-            frozen = dcc->glz_dict->migrate_freeze;
+            pthread_rwlock_rdlock(&dcc->encoders.glz_dict->encode_lock);
+            frozen = dcc->encoders.glz_dict->migrate_freeze;
             if (!frozen) {
                 success = dcc_compress_image_glz(dcc, dest, src, drawable, o_comp_data);
             }
-            pthread_rwlock_unlock(&dcc->glz_dict->encode_lock);
+            pthread_rwlock_unlock(&dcc->encoders.glz_dict->encode_lock);
             if (!frozen) {
                 break;
             }
@@ -1053,6 +1052,8 @@ int dcc_pixmap_cache_unlocked_add(DisplayChannelClient *dcc, uint64_t id,
 
 static int dcc_handle_init(DisplayChannelClient *dcc, SpiceMsgcDisplayInit *init)
 {
+    gboolean success;
+
     spice_return_val_if_fail(dcc->expect_init, FALSE);
     dcc->expect_init = FALSE;
 
@@ -1062,11 +1063,12 @@ static int dcc_handle_init(DisplayChannelClient *dcc, SpiceMsgcDisplayInit *init
                                          init->pixmap_cache_size);
     spice_return_val_if_fail(dcc->pixmap_cache, FALSE);
 
-    spice_return_val_if_fail(!dcc->glz_dict, FALSE);
-    dcc->glz_dict = dcc_get_glz_dictionary(dcc,
-                                           init->glz_dictionary_id,
-                                           init->glz_dictionary_window_size);
-    spice_return_val_if_fail(dcc->glz_dict, FALSE);
+    spice_return_val_if_fail(!dcc->encoders.glz_dict, FALSE);
+    success = image_encoders_get_glz_dictionary(&dcc->encoders,
+                                                RED_CHANNEL_CLIENT(dcc)->client,
+                                                init->glz_dictionary_id,
+                                                init->glz_dictionary_window_size);
+    spice_return_val_if_fail(success, FALSE);
 
     return TRUE;
 }
@@ -1166,12 +1168,12 @@ int dcc_handle_message(RedChannelClient *rcc, uint32_t size, uint16_t type, void
 static int dcc_handle_migrate_glz_dictionary(DisplayChannelClient *dcc,
                                              SpiceMigrateDataDisplay *migrate)
 {
-    spice_return_val_if_fail(!dcc->glz_dict, FALSE);
+    spice_return_val_if_fail(!dcc->encoders.glz_dict, FALSE);
 
-    dcc->glz_dict = dcc_restore_glz_dictionary(dcc,
-                                               migrate->glz_dict_id,
-                                               &migrate->glz_dict_data);
-    return dcc->glz_dict != NULL;
+    return image_encoders_restore_glz_dictionary(&dcc->encoders,
+                                                 RED_CHANNEL_CLIENT(dcc)->client,
+                                                 migrate->glz_dict_id,
+                                                 &migrate->glz_dict_data);
 }
 
 static int restore_surface(DisplayChannelClient *dcc, uint32_t surface_id)
@@ -1264,8 +1266,7 @@ int dcc_handle_migrate_data(DisplayChannelClient *dcc, uint32_t size, void *mess
     }
 
     if (dcc_handle_migrate_glz_dictionary(dcc, migrate_data)) {
-        dcc->glz =
-            glz_encoder_create(dcc->id, dcc->glz_dict->dict, &dcc->glz_data.usr);
+        image_encoders_glz_create(&dcc->encoders, dcc->id);
     } else {
         spice_critical("restoring global lz dictionary failed");
     }
diff --git a/server/dcc.h b/server/dcc.h
index 20f41e2..ac6de84 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -84,10 +84,6 @@ struct DisplayChannelClient {
     } send_data;
 
     /* global lz encoding entities */
-    GlzSharedDictionary *glz_dict;
-    GlzEncoderContext   *glz;
-    GlzData glz_data;
-
     Ring glz_drawables;               // all the living lz drawable, ordered by encoding time
     Ring glz_drawables_inst_to_free;               // list of instances to be freed
     pthread_mutex_t glz_drawables_inst_to_free_lock;
diff --git a/server/display-channel.c b/server/display-channel.c
index 6ec8692..8c0c859 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1202,7 +1202,7 @@ void display_channel_free_some(DisplayChannel *display)
     spice_debug("#draw=%d, #glz_draw=%d", display->drawable_count,
                 display->glz_drawable_count);
     FOREACH_CLIENT(display, link, next, dcc) {
-        GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
+        GlzSharedDictionary *glz_dict = dcc->encoders.glz_dict;
 
         if (glz_dict) {
             // encoding using the dictionary is prevented since the following operations might
@@ -1217,7 +1217,7 @@ void display_channel_free_some(DisplayChannel *display)
     }
 
     FOREACH_CLIENT(display, link, next, dcc) {
-        GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
+        GlzSharedDictionary *glz_dict = dcc->encoders.glz_dict;
 
         if (glz_dict) {
             pthread_rwlock_unlock(&glz_dict->encode_lock);
commit 86b702a7d007c6c7d4b1f58bd01681bac920abcf
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Fri Jun 10 05:39:25 2016 +0100

    Add a structure to hold ImageEncoders shared data
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/dcc-encoders.c b/server/dcc-encoders.c
index 6aaf954..c79cf58 100644
--- a/server/dcc-encoders.c
+++ b/server/dcc-encoders.c
@@ -398,10 +398,13 @@ static void image_encoders_init_zlib(ImageEncoders *enc)
     }
 }
 
-void dcc_encoders_init(DisplayChannelClient *dcc)
+void dcc_encoders_init(DisplayChannelClient *dcc, ImageEncoderSharedData *shared_data)
 {
     ImageEncoders *enc = &dcc->encoders;
 
+    spice_assert(shared_data);
+    enc->shared_data = shared_data;
+
     dcc_init_glz_data(dcc);
     image_encoders_init_quic(enc);
     image_encoders_init_lz(enc);
@@ -708,15 +711,14 @@ void dcc_release_glz(DisplayChannelClient *dcc)
 }
 
 int image_encoders_compress_quic(ImageEncoders *enc, SpiceImage *dest,
-                                 SpiceBitmap *src, compress_send_data_t* o_comp_data,
-                                 stat_info_t *stats)
+                                 SpiceBitmap *src, compress_send_data_t* o_comp_data)
 {
     QuicData *quic_data = &enc->quic_data;
     QuicContext *quic = enc->quic;
     volatile QuicImageType type;
     int size, stride;
     stat_start_time_t start_time;
-    stat_start_time_init(&start_time, stats);
+    stat_start_time_init(&start_time, &enc->shared_data->quic_stat);
 
 #ifdef COMPRESS_DEBUG
     spice_info("QUIC compress");
@@ -776,7 +778,7 @@ int image_encoders_compress_quic(ImageEncoders *enc, SpiceImage *dest,
     o_comp_data->comp_buf = quic_data->data.bufs_head;
     o_comp_data->comp_buf_size = size << 2;
 
-    stat_compress_add(stats, start_time, src->stride * src->y,
+    stat_compress_add(&enc->shared_data->quic_stat, start_time, src->stride * src->y,
                       o_comp_data->comp_buf_size);
     return TRUE;
 }
@@ -797,8 +799,7 @@ static const LzImageType bitmap_fmt_to_lz_image_type[] = {
 
 int image_encoders_compress_lz(ImageEncoders *enc,
                                SpiceImage *dest, SpiceBitmap *src,
-                               compress_send_data_t* o_comp_data,
-                               stat_info_t *stats)
+                               compress_send_data_t* o_comp_data)
 {
     LzData *lz_data = &enc->lz_data;
     LzContext *lz = enc->lz;
@@ -806,7 +807,7 @@ int image_encoders_compress_lz(ImageEncoders *enc,
     int size;            // size of the compressed data
 
     stat_start_time_t start_time;
-    stat_start_time_init(&start_time, stats);
+    stat_start_time_init(&start_time, &enc->shared_data->lz_stat);
 
 #ifdef COMPRESS_DEBUG
     spice_info("LZ LOCAL compress");
@@ -856,15 +857,13 @@ int image_encoders_compress_lz(ImageEncoders *enc,
         o_comp_data->lzplt_palette = dest->u.lz_plt.palette;
     }
 
-    stat_compress_add(stats, start_time, src->stride * src->y,
+    stat_compress_add(&enc->shared_data->lz_stat, start_time, src->stride * src->y,
                       o_comp_data->comp_buf_size);
     return TRUE;
 }
 
 int image_encoders_compress_jpeg(ImageEncoders *enc, SpiceImage *dest,
-                                 SpiceBitmap *src, compress_send_data_t* o_comp_data,
-                                 stat_info_t *jpeg_stats, // FIXME put all stats in a structure
-                                 stat_info_t *jpeg_alpha_stats)
+                                 SpiceBitmap *src, compress_send_data_t* o_comp_data)
 {
     JpegData *jpeg_data = &enc->jpeg_data;
     LzData *lz_data = &enc->lz_data;
@@ -879,7 +878,7 @@ int image_encoders_compress_jpeg(ImageEncoders *enc, SpiceImage *dest,
     int stride;
     uint8_t *lz_out_start_byte;
     stat_start_time_t start_time;
-    stat_start_time_init(&start_time, jpeg_alpha_stats);
+    stat_start_time_init(&start_time, &enc->shared_data->jpeg_alpha_stat);
 
 #ifdef COMPRESS_DEBUG
     spice_info("JPEG compress");
@@ -943,7 +942,7 @@ int image_encoders_compress_jpeg(ImageEncoders *enc, SpiceImage *dest,
         o_comp_data->comp_buf_size = jpeg_size;
         o_comp_data->is_lossy = TRUE;
 
-        stat_compress_add(jpeg_stats, start_time, src->stride * src->y,
+        stat_compress_add(&enc->shared_data->jpeg_stat, start_time, src->stride * src->y,
                           o_comp_data->comp_buf_size);
         return TRUE;
     }
@@ -983,21 +982,20 @@ int image_encoders_compress_jpeg(ImageEncoders *enc, SpiceImage *dest,
     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(jpeg_alpha_stats, start_time, src->stride * src->y,
+    stat_compress_add(&enc->shared_data->jpeg_alpha_stat, start_time, src->stride * src->y,
                       o_comp_data->comp_buf_size);
     return TRUE;
 }
 
 #ifdef USE_LZ4
 int image_encoders_compress_lz4(ImageEncoders *enc, SpiceImage *dest,
-                                SpiceBitmap *src, compress_send_data_t* o_comp_data,
-                                stat_info_t *stats)
+                                SpiceBitmap *src, compress_send_data_t* o_comp_data)
 {
     Lz4Data *lz4_data = &enc->lz4_data;
     Lz4EncoderContext *lz4 = enc->lz4;
     int lz4_size = 0;
     stat_start_time_t start_time;
-    stat_start_time_init(&start_time, stats);
+    stat_start_time_init(&start_time, &enc->shared_data->lz4_stat);
 
 #ifdef COMPRESS_DEBUG
     spice_info("LZ4 compress");
@@ -1034,8 +1032,93 @@ int image_encoders_compress_lz4(ImageEncoders *enc, SpiceImage *dest,
     o_comp_data->comp_buf = lz4_data->data.bufs_head;
     o_comp_data->comp_buf_size = lz4_size;
 
-    stat_compress_add(stats, start_time, src->stride * src->y,
+    stat_compress_add(&enc->shared_data->lz4_stat, start_time, src->stride * src->y,
                       o_comp_data->comp_buf_size);
     return TRUE;
 }
 #endif
+
+void image_encoder_shared_init(ImageEncoderSharedData *shared_data)
+{
+    clockid_t stat_clock = CLOCK_THREAD_CPUTIME_ID;
+
+    stat_compress_init(&shared_data->off_stat, "off", stat_clock);
+    stat_compress_init(&shared_data->lz_stat, "lz", stat_clock);
+    stat_compress_init(&shared_data->glz_stat, "glz", stat_clock);
+    stat_compress_init(&shared_data->quic_stat, "quic", stat_clock);
+    stat_compress_init(&shared_data->jpeg_stat, "jpeg", stat_clock);
+    stat_compress_init(&shared_data->zlib_glz_stat, "zlib", stat_clock);
+    stat_compress_init(&shared_data->jpeg_alpha_stat, "jpeg_alpha", stat_clock);
+    stat_compress_init(&shared_data->lz4_stat, "lz4", stat_clock);
+}
+
+void image_encoder_shared_stat_reset(ImageEncoderSharedData *shared_data)
+{
+    stat_reset(&shared_data->off_stat);
+    stat_reset(&shared_data->quic_stat);
+    stat_reset(&shared_data->lz_stat);
+    stat_reset(&shared_data->glz_stat);
+    stat_reset(&shared_data->jpeg_stat);
+    stat_reset(&shared_data->zlib_glz_stat);
+    stat_reset(&shared_data->jpeg_alpha_stat);
+    stat_reset(&shared_data->lz4_stat);
+}
+
+#define STAT_FMT "%s\t%8u\t%13.8g\t%12.8g\t%12.8g"
+
+#ifdef COMPRESS_STAT
+static void stat_print_one(const char *name, const stat_info_t *stat)
+{
+    spice_info(STAT_FMT, name, stat->count,
+               stat_byte_to_mega(stat->orig_size),
+               stat_byte_to_mega(stat->comp_size),
+               stat_cpu_time_to_sec(stat->total));
+}
+
+static void stat_sum(stat_info_t *total, const stat_info_t *stat)
+{
+    total->count += stat->count;
+    total->orig_size += stat->orig_size;
+    total->comp_size += stat->comp_size;
+    total->total += stat->total;
+}
+#endif
+
+void image_encoder_shared_stat_print(const ImageEncoderSharedData *shared_data)
+{
+#ifdef COMPRESS_STAT
+    /* sum all statistics */
+    stat_info_t total = {
+        .count = 0,
+        .orig_size = 0,
+        .comp_size = 0,
+        .total = 0
+    };
+    stat_sum(&total, &shared_data->off_stat);
+    stat_sum(&total, &shared_data->quic_stat);
+    stat_sum(&total, &shared_data->glz_stat);
+    stat_sum(&total, &shared_data->lz_stat);
+    stat_sum(&total, &shared_data->jpeg_stat);
+    stat_sum(&total, &shared_data->jpeg_alpha_stat);
+    stat_sum(&total, &shared_data->lz4_stat);
+
+    /* fix for zlib glz */
+    total.total += shared_data->zlib_glz_stat.total;
+    if (shared_data->zlib_glz_stat.count) {
+        total.comp_size = total.comp_size - shared_data->glz_stat.comp_size +
+                          shared_data->zlib_glz_stat.comp_size;
+    }
+
+    spice_info("Method   \t  count  \torig_size(MB)\tenc_size(MB)\tenc_time(s)");
+    stat_print_one("OFF      ", &shared_data->off_stat);
+    stat_print_one("QUIC     ", &shared_data->quic_stat);
+    stat_print_one("GLZ      ", &shared_data->glz_stat);
+    stat_print_one("ZLIB GLZ ", &shared_data->zlib_glz_stat);
+    stat_print_one("LZ       ", &shared_data->lz_stat);
+    stat_print_one("JPEG     ", &shared_data->jpeg_stat);
+    stat_print_one("JPEG-RGBA", &shared_data->jpeg_alpha_stat);
+    stat_print_one("LZ4      ", &shared_data->lz4_stat);
+    spice_info("-------------------------------------------------------------------");
+    stat_print_one("Total    ", &total);
+#endif
+}
diff --git a/server/dcc-encoders.h b/server/dcc-encoders.h
index 23355f7..4b89cc9 100644
--- a/server/dcc-encoders.h
+++ b/server/dcc-encoders.h
@@ -35,8 +35,13 @@ typedef struct RedCompressBuf RedCompressBuf;
 typedef struct GlzDrawableInstanceItem GlzDrawableInstanceItem;
 typedef struct RedGlzDrawable RedGlzDrawable;
 typedef struct ImageEncoders ImageEncoders;
+typedef struct ImageEncoderSharedData ImageEncoderSharedData;
 
-void             dcc_encoders_init                           (DisplayChannelClient *dcc);
+void image_encoder_shared_init(ImageEncoderSharedData *shared_data);
+void image_encoder_shared_stat_reset(ImageEncoderSharedData *shared_data);
+void image_encoder_shared_stat_print(const ImageEncoderSharedData *shared_data);
+
+void dcc_encoders_init(DisplayChannelClient *dcc, ImageEncoderSharedData *shared_data);
 void image_encoders_free(ImageEncoders *enc);
 void             dcc_free_glz_drawable                       (DisplayChannelClient *dcc,
                                                               RedGlzDrawable *drawable);
@@ -161,7 +166,20 @@ struct RedGlzDrawable {
     DisplayChannelClient *dcc;
 };
 
+struct ImageEncoderSharedData {
+    stat_info_t off_stat;
+    stat_info_t lz_stat;
+    stat_info_t glz_stat;
+    stat_info_t quic_stat;
+    stat_info_t jpeg_stat;
+    stat_info_t zlib_glz_stat;
+    stat_info_t jpeg_alpha_stat;
+    stat_info_t lz4_stat;
+};
+
 struct ImageEncoders {
+    ImageEncoderSharedData *shared_data;
+
     QuicData quic_data;
     QuicContext *quic;
 
@@ -192,19 +210,14 @@ typedef struct compress_send_data_t {
 } compress_send_data_t;
 
 int image_encoders_compress_quic(ImageEncoders *enc, SpiceImage *dest,
-                                 SpiceBitmap *src, compress_send_data_t* o_comp_data,
-                                 stat_info_t *stats);
+                                 SpiceBitmap *src, compress_send_data_t* o_comp_data);
 int image_encoders_compress_lz(ImageEncoders *enc,
                                SpiceImage *dest, SpiceBitmap *src,
-                               compress_send_data_t* o_comp_data,
-                               stat_info_t *stats);
+                               compress_send_data_t* o_comp_data);
 int image_encoders_compress_jpeg(ImageEncoders *enc, SpiceImage *dest,
-                                 SpiceBitmap *src, compress_send_data_t* o_comp_data,
-                                 stat_info_t *jpeg_stats,
-                                 stat_info_t *jpeg_alpha_stats);
+                                 SpiceBitmap *src, compress_send_data_t* o_comp_data);
 int image_encoders_compress_lz4(ImageEncoders *enc, SpiceImage *dest,
-                                SpiceBitmap *src, compress_send_data_t* o_comp_data,
-                                stat_info_t *stats);
+                                SpiceBitmap *src, compress_send_data_t* o_comp_data);
 
 #define RED_RELEASE_BUNCH_SIZE 64
 
diff --git a/server/dcc.c b/server/dcc.c
index 7724e11..8f44e64 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -396,7 +396,7 @@ DisplayChannelClient *dcc_new(DisplayChannel *display,
     ring_init(&dcc->glz_drawables_inst_to_free);
     pthread_mutex_init(&dcc->glz_drawables_inst_to_free_lock, NULL);
 
-    dcc_encoders_init(dcc);
+    dcc_encoders_init(dcc, &display->encoder_globals);
 
     return dcc;
 }
@@ -709,7 +709,7 @@ static int dcc_compress_image_glz(DisplayChannelClient *dcc,
 {
     DisplayChannel *display_channel = DCC_TO_DC(dcc);
     stat_start_time_t start_time;
-    stat_start_time_init(&start_time, &display_channel->zlib_glz_stat);
+    stat_start_time_init(&start_time, &display_channel->encoder_globals.zlib_glz_stat);
     spice_assert(bitmap_fmt_is_rgb(src->format));
     GlzData *glz_data = &dcc->glz_data;
     ZlibData *zlib_data;
@@ -740,12 +740,12 @@ static int dcc_compress_image_glz(DisplayChannelClient *dcc,
                           glz_drawable_instance,
                           &glz_drawable_instance->context);
 
-    stat_compress_add(&display_channel->glz_stat, start_time, src->stride * src->y, glz_size);
+    stat_compress_add(&display_channel->encoder_globals.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;
     }
-    stat_start_time_init(&start_time, &display_channel->zlib_glz_stat);
+    stat_start_time_init(&start_time, &display_channel->encoder_globals.zlib_glz_stat);
     zlib_data = &dcc->encoders.zlib_data;
 
     encoder_data_init(&zlib_data->data);
@@ -772,7 +772,7 @@ static int dcc_compress_image_glz(DisplayChannelClient *dcc,
     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);
+    stat_compress_add(&display_channel->encoder_globals.zlib_glz_stat, start_time, glz_size, zlib_size);
     return TRUE;
 glz:
     dest->descriptor.type = SPICE_IMAGE_TYPE_GLZ_RGB;
@@ -878,7 +878,7 @@ int dcc_compress_image(DisplayChannelClient *dcc,
     stat_start_time_t start_time;
     int success = FALSE;
 
-    stat_start_time_init(&start_time, &display_channel->off_stat);
+    stat_start_time_init(&start_time, &display_channel->encoder_globals.off_stat);
 
     image_compression = get_compression_for_bitmap(src, dcc->image_compression, drawable);
     switch (image_compression) {
@@ -887,13 +887,10 @@ int dcc_compress_image(DisplayChannelClient *dcc,
     case SPICE_IMAGE_COMPRESSION_QUIC:
         if (can_lossy && display_channel->enable_jpeg &&
             (src->format != SPICE_BITMAP_FMT_RGBA || !bitmap_has_extra_stride(src))) {
-            success = image_encoders_compress_jpeg(&dcc->encoders, dest, src, o_comp_data,
-                                                   &display_channel->jpeg_stat,
-                                                   &display_channel->jpeg_alpha_stat);
+            success = image_encoders_compress_jpeg(&dcc->encoders, dest, src, o_comp_data);
             break;
         }
-        success = image_encoders_compress_quic(&dcc->encoders, dest, src, o_comp_data,
-                                               &display_channel->quic_stat);
+        success = image_encoders_compress_quic(&dcc->encoders, dest, src, o_comp_data);
         break;
     case SPICE_IMAGE_COMPRESSION_GLZ:
         if ((src->x * src->y) < glz_enc_dictionary_get_size(dcc->glz_dict->dict)) {
@@ -914,14 +911,13 @@ int dcc_compress_image(DisplayChannelClient *dcc,
     case SPICE_IMAGE_COMPRESSION_LZ4:
         if (red_channel_client_test_remote_cap(&dcc->common.base,
                                                SPICE_DISPLAY_CAP_LZ4_COMPRESSION)) {
-            success = image_encoders_compress_lz4(&dcc->encoders, dest, src, o_comp_data,
-                                                  &display_channel->lz4_stat);
+            success = image_encoders_compress_lz4(&dcc->encoders, dest, src, o_comp_data);
             break;
         }
 #endif
 lz_compress:
     case SPICE_IMAGE_COMPRESSION_LZ:
-        success = image_encoders_compress_lz(&dcc->encoders, dest, src, o_comp_data, &display_channel->lz_stat);
+        success = image_encoders_compress_lz(&dcc->encoders, dest, src, o_comp_data);
         if (success && !bitmap_fmt_is_rgb(src->format)) {
             dcc_palette_cache_palette(dcc, dest->u.lz_plt.palette, &(dest->u.lz_plt.flags));
         }
@@ -932,7 +928,7 @@ lz_compress:
 
     if (!success) {
         uint64_t image_size = src->stride * src->y;
-        stat_compress_add(&display_channel->off_stat, start_time, image_size, image_size);
+        stat_compress_add(&display_channel->encoder_globals.off_stat, start_time, image_size, image_size);
     }
 
     return success;
diff --git a/server/display-channel.c b/server/display-channel.c
index 2888cad..6ec8692 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -38,75 +38,16 @@ void display_channel_compress_stats_reset(DisplayChannel *display)
 {
     spice_return_if_fail(display);
 
-    stat_reset(&display->off_stat);
-    stat_reset(&display->quic_stat);
-    stat_reset(&display->lz_stat);
-    stat_reset(&display->glz_stat);
-    stat_reset(&display->jpeg_stat);
-    stat_reset(&display->zlib_glz_stat);
-    stat_reset(&display->jpeg_alpha_stat);
-    stat_reset(&display->lz4_stat);
+    image_encoder_shared_stat_reset(&display->encoder_globals);
 }
 
-#define STAT_FMT "%s\t%8u\t%13.8g\t%12.8g\t%12.8g"
-
-#ifdef COMPRESS_STAT
-static void stat_print_one(const char *name, const stat_info_t *stat)
-{
-    spice_info(STAT_FMT, name, stat->count,
-               stat_byte_to_mega(stat->orig_size),
-               stat_byte_to_mega(stat->comp_size),
-               stat_cpu_time_to_sec(stat->total));
-}
-
-static void stat_sum(stat_info_t *total, const stat_info_t *stat)
-{
-    total->count += stat->count;
-    total->orig_size += stat->orig_size;
-    total->comp_size += stat->comp_size;
-    total->total += stat->total;
-}
-#endif
-
 void display_channel_compress_stats_print(const DisplayChannel *display_channel)
 {
-    spice_return_if_fail(display_channel);
-
 #ifdef COMPRESS_STAT
-    /* sum all statistics */
-    stat_info_t total = {
-        .count = 0,
-        .orig_size = 0,
-        .comp_size = 0,
-        .total = 0
-    };
-    stat_sum(&total, &display_channel->off_stat);
-    stat_sum(&total, &display_channel->quic_stat);
-    stat_sum(&total, &display_channel->glz_stat);
-    stat_sum(&total, &display_channel->lz_stat);
-    stat_sum(&total, &display_channel->jpeg_stat);
-    stat_sum(&total, &display_channel->jpeg_alpha_stat);
-    stat_sum(&total, &display_channel->lz4_stat);
-
-    /* fix for zlib glz */
-    total.total += display_channel->zlib_glz_stat.total;
-    if (display_channel->enable_zlib_glz_wrap) {
-        total.comp_size = total.comp_size - display_channel->glz_stat.comp_size +
-                          display_channel->zlib_glz_stat.comp_size;
-    }
+    spice_return_if_fail(display_channel);
 
     spice_info("==> Compression stats for display %u", display_channel->common.base.id);
-    spice_info("Method   \t  count  \torig_size(MB)\tenc_size(MB)\tenc_time(s)");
-    stat_print_one("OFF      ", &display_channel->off_stat);
-    stat_print_one("QUIC     ", &display_channel->quic_stat);
-    stat_print_one("GLZ      ", &display_channel->glz_stat);
-    stat_print_one("ZLIB GLZ ", &display_channel->zlib_glz_stat);
-    stat_print_one("LZ       ", &display_channel->lz_stat);
-    stat_print_one("JPEG     ", &display_channel->jpeg_stat);
-    stat_print_one("JPEG-RGBA", &display_channel->jpeg_alpha_stat);
-    stat_print_one("LZ4      ", &display_channel->lz4_stat);
-    spice_info("-------------------------------------------------------------------");
-    stat_print_one("Total    ", &total);
+    image_encoder_shared_stat_print(&display_channel->encoder_globals);
 #endif
 }
 
@@ -1984,13 +1925,7 @@ DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker,
     display->non_cache_counter = stat_add_counter(reds, channel->stat,
                                                   "non_cache", TRUE);
 #endif
-    stat_compress_init(&display->lz_stat, "lz", stat_clock);
-    stat_compress_init(&display->glz_stat, "glz", stat_clock);
-    stat_compress_init(&display->quic_stat, "quic", stat_clock);
-    stat_compress_init(&display->jpeg_stat, "jpeg", stat_clock);
-    stat_compress_init(&display->zlib_glz_stat, "zlib", stat_clock);
-    stat_compress_init(&display->jpeg_alpha_stat, "jpeg_alpha", stat_clock);
-    stat_compress_init(&display->lz4_stat, "lz4", stat_clock);
+    image_encoder_shared_init(&display->encoder_globals);
 
     display->n_surfaces = n_surfaces;
     display->renderer = RED_RENDERER_INVALID;
diff --git a/server/display-channel.h b/server/display-channel.h
index 16ea709..db1cdba 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -216,14 +216,7 @@ struct DisplayChannel {
     uint64_t *add_to_cache_counter;
     uint64_t *non_cache_counter;
 #endif
-    stat_info_t off_stat;
-    stat_info_t lz_stat;
-    stat_info_t glz_stat;
-    stat_info_t quic_stat;
-    stat_info_t jpeg_stat;
-    stat_info_t zlib_glz_stat;
-    stat_info_t jpeg_alpha_stat;
-    stat_info_t lz4_stat;
+    ImageEncoderSharedData encoder_globals;
 };
 
 static inline int get_stream_id(DisplayChannel *display, Stream *stream)


More information about the Spice-commits mailing list