[Spice-devel] [PATCH 16/16] worker: move encoders to dcc-encoders

Frediano Ziglio fziglio at redhat.com
Tue Nov 10 06:16:29 PST 2015


From: Marc-André Lureau <marcandre.lureau at gmail.com>

Author:    Marc-André Lureau <marcandre.lureau at gmail.com>
---
 server/Makefile.am       |   2 +
 server/dcc-encoders.c    | 402 ++++++++++++++++++++++++++++++++++
 server/dcc-encoders.h    | 145 +++++++++++++
 server/display-channel.c |   6 +-
 server/display-channel.h |  66 ++----
 server/red_worker.c      | 555 +++--------------------------------------------
 6 files changed, 597 insertions(+), 579 deletions(-)
 create mode 100644 server/dcc-encoders.c
 create mode 100644 server/dcc-encoders.h

diff --git a/server/Makefile.am b/server/Makefile.am
index 52703c9..5907dd2 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -138,6 +138,8 @@ libspice_server_la_SOURCES =			\
 	utils.h					\
 	stream.c					\
 	stream.h					\
+	dcc-encoders.c					\
+	dcc-encoders.h					\
 	$(NULL)
 
 if HAVE_GL
diff --git a/server/dcc-encoders.c b/server/dcc-encoders.c
new file mode 100644
index 0000000..9094f99
--- /dev/null
+++ b/server/dcc-encoders.c
@@ -0,0 +1,402 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009-2015 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#include <glib.h>
+#include <setjmp.h>
+
+#include "dcc-encoders.h"
+#include "display-channel.h"
+
+#define ZLIB_DEFAULT_COMPRESSION_LEVEL 3
+
+static SPICE_GNUC_NORETURN SPICE_GNUC_PRINTF(2, 3) void
+quic_usr_error(QuicUsrContext *usr, const char *fmt, ...)
+{
+    EncoderData *usr_data = &(((QuicData *)usr)->data);
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
+    va_end(ap);
+    spice_critical("%s", usr_data->message_buf);
+
+    longjmp(usr_data->jmp_env, 1);
+}
+
+static SPICE_GNUC_NORETURN SPICE_GNUC_PRINTF(2, 3) void
+lz_usr_error(LzUsrContext *usr, const char *fmt, ...)
+{
+    EncoderData *usr_data = &(((LzData *)usr)->data);
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
+    va_end(ap);
+    spice_critical("%s", usr_data->message_buf);
+
+    longjmp(usr_data->jmp_env, 1);
+}
+
+static SPICE_GNUC_PRINTF(2, 3) void
+glz_usr_error(GlzEncoderUsrContext *usr, const char *fmt, ...)
+{
+    EncoderData *usr_data = &(((GlzData *)usr)->data);
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
+    va_end(ap);
+
+    spice_critical("%s", usr_data->message_buf); // if global lz fails in the middle
+                                        // the consequences are not predictable since the window
+                                        // can turn to be unsynchronized between the server and
+                                        // and the client
+}
+
+static SPICE_GNUC_PRINTF(2, 3) void
+quic_usr_warn(QuicUsrContext *usr, const char *fmt, ...)
+{
+    EncoderData *usr_data = &(((QuicData *)usr)->data);
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
+    va_end(ap);
+    spice_warning("%s", usr_data->message_buf);
+}
+
+static SPICE_GNUC_PRINTF(2, 3) void
+lz_usr_warn(LzUsrContext *usr, const char *fmt, ...)
+{
+    EncoderData *usr_data = &(((LzData *)usr)->data);
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
+    va_end(ap);
+    spice_warning("%s", usr_data->message_buf);
+}
+
+static SPICE_GNUC_PRINTF(2, 3) void
+glz_usr_warn(GlzEncoderUsrContext *usr, const char *fmt, ...)
+{
+    EncoderData *usr_data = &(((GlzData *)usr)->data);
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
+    va_end(ap);
+    spice_warning("%s", usr_data->message_buf);
+}
+
+static void *quic_usr_malloc(QuicUsrContext *usr, int size)
+{
+    return spice_malloc(size);
+}
+
+static void *lz_usr_malloc(LzUsrContext *usr, int size)
+{
+    return spice_malloc(size);
+}
+
+static void *glz_usr_malloc(GlzEncoderUsrContext *usr, int size)
+{
+    return spice_malloc(size);
+}
+
+static void quic_usr_free(QuicUsrContext *usr, void *ptr)
+{
+    free(ptr);
+}
+
+static void lz_usr_free(LzUsrContext *usr, void *ptr)
+{
+    free(ptr);
+}
+
+static void glz_usr_free(GlzEncoderUsrContext *usr, void *ptr)
+{
+    free(ptr);
+}
+
+RedCompressBuf* compress_buf_new(void)
+{
+    RedCompressBuf *buf = g_slice_new(RedCompressBuf);
+
+    buf->send_next = NULL;
+
+    return buf;
+}
+
+void compress_buf_free(RedCompressBuf *buf)
+{
+    g_slice_free(RedCompressBuf, buf);
+}
+
+static int encoder_usr_more_space(EncoderData *enc_data, uint8_t **io_ptr)
+{
+    RedCompressBuf *buf;
+
+    buf = compress_buf_new();
+    enc_data->bufs_tail->send_next = buf;
+    enc_data->bufs_tail = buf;
+    buf->send_next = NULL;
+    *io_ptr = buf->buf;
+    return sizeof(buf->buf);
+}
+
+static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed)
+{
+    EncoderData *usr_data = &(((QuicData *)usr)->data);
+    return encoder_usr_more_space(usr_data, (uint8_t **)io_ptr) / sizeof(uint32_t);
+}
+
+static int lz_usr_more_space(LzUsrContext *usr, uint8_t **io_ptr)
+{
+    EncoderData *usr_data = &(((LzData *)usr)->data);
+    return encoder_usr_more_space(usr_data, io_ptr);
+}
+
+static int glz_usr_more_space(GlzEncoderUsrContext *usr, uint8_t **io_ptr)
+{
+    EncoderData *usr_data = &(((GlzData *)usr)->data);
+    return encoder_usr_more_space(usr_data, io_ptr);
+}
+
+static int jpeg_usr_more_space(JpegEncoderUsrContext *usr, uint8_t **io_ptr)
+{
+    EncoderData *usr_data = &(((JpegData *)usr)->data);
+    return encoder_usr_more_space(usr_data, io_ptr);
+}
+
+#ifdef USE_LZ4
+static int lz4_usr_more_space(Lz4EncoderUsrContext *usr, uint8_t **io_ptr)
+{
+    EncoderData *usr_data = &(((Lz4Data *)usr)->data);
+    return (encoder_usr_more_space(usr_data, (uint32_t **)io_ptr) << 2);
+}
+#endif
+
+static int zlib_usr_more_space(ZlibEncoderUsrContext *usr, uint8_t **io_ptr)
+{
+    EncoderData *usr_data = &(((ZlibData *)usr)->data);
+    return encoder_usr_more_space(usr_data, io_ptr);
+}
+
+static inline int encoder_usr_more_lines(EncoderData *enc_data, uint8_t **lines)
+{
+    struct SpiceChunk *chunk;
+
+    if (enc_data->u.lines_data.reverse) {
+        if (!(enc_data->u.lines_data.next >= 0)) {
+            return 0;
+        }
+    } else {
+        if (!(enc_data->u.lines_data.next < enc_data->u.lines_data.chunks->num_chunks)) {
+            return 0;
+        }
+    }
+
+    chunk = &enc_data->u.lines_data.chunks->chunk[enc_data->u.lines_data.next];
+    if (chunk->len % enc_data->u.lines_data.stride) {
+        return 0;
+    }
+
+    if (enc_data->u.lines_data.reverse) {
+        enc_data->u.lines_data.next--;
+        *lines = chunk->data + chunk->len - enc_data->u.lines_data.stride;
+    } else {
+        enc_data->u.lines_data.next++;
+        *lines = chunk->data;
+    }
+
+    return chunk->len / enc_data->u.lines_data.stride;
+}
+
+static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines)
+{
+    EncoderData *usr_data = &(((QuicData *)usr)->data);
+    return encoder_usr_more_lines(usr_data, lines);
+}
+
+static int lz_usr_more_lines(LzUsrContext *usr, uint8_t **lines)
+{
+    EncoderData *usr_data = &(((LzData *)usr)->data);
+    return encoder_usr_more_lines(usr_data, lines);
+}
+
+static int glz_usr_more_lines(GlzEncoderUsrContext *usr, uint8_t **lines)
+{
+    EncoderData *usr_data = &(((GlzData *)usr)->data);
+    return encoder_usr_more_lines(usr_data, lines);
+}
+
+static int jpeg_usr_more_lines(JpegEncoderUsrContext *usr, uint8_t **lines)
+{
+    EncoderData *usr_data = &(((JpegData *)usr)->data);
+    return encoder_usr_more_lines(usr_data, lines);
+}
+
+#ifdef USE_LZ4
+static int lz4_usr_more_lines(Lz4EncoderUsrContext *usr, uint8_t **lines)
+{
+    EncoderData *usr_data = &(((Lz4Data *)usr)->data);
+    return encoder_usr_more_lines(usr_data, lines);
+}
+#endif
+
+static int zlib_usr_more_input(ZlibEncoderUsrContext *usr, uint8_t** input)
+{
+    EncoderData *usr_data = &(((ZlibData *)usr)->data);
+    int buf_size;
+
+    if (!usr_data->u.compressed_data.next) {
+        spice_assert(usr_data->u.compressed_data.size_left == 0);
+        return 0;
+    }
+
+    *input = (uint8_t*)usr_data->u.compressed_data.next->buf;
+    buf_size = MIN(sizeof(usr_data->u.compressed_data.next->buf),
+                   usr_data->u.compressed_data.size_left);
+
+    usr_data->u.compressed_data.next = usr_data->u.compressed_data.next->send_next;
+    usr_data->u.compressed_data.size_left -= buf_size;
+    return buf_size;
+}
+
+static void dcc_init_quic(DisplayChannelClient *dcc)
+{
+    dcc->quic_data.usr.error = quic_usr_error;
+    dcc->quic_data.usr.warn = quic_usr_warn;
+    dcc->quic_data.usr.info = quic_usr_warn;
+    dcc->quic_data.usr.malloc = quic_usr_malloc;
+    dcc->quic_data.usr.free = quic_usr_free;
+    dcc->quic_data.usr.more_space = quic_usr_more_space;
+    dcc->quic_data.usr.more_lines = quic_usr_more_lines;
+
+    dcc->quic = quic_create(&dcc->quic_data.usr);
+    spice_warn_if_fail(dcc->quic);
+}
+
+static void dcc_init_lz(DisplayChannelClient *dcc)
+{
+    dcc->lz_data.usr.error = lz_usr_error;
+    dcc->lz_data.usr.warn = lz_usr_warn;
+    dcc->lz_data.usr.info = lz_usr_warn;
+    dcc->lz_data.usr.malloc = lz_usr_malloc;
+    dcc->lz_data.usr.free = lz_usr_free;
+    dcc->lz_data.usr.more_space = lz_usr_more_space;
+    dcc->lz_data.usr.more_lines = lz_usr_more_lines;
+
+    dcc->lz = lz_create(&dcc->lz_data.usr);
+    spice_warn_if_fail(dcc->lz);
+}
+
+static void glz_usr_free_image(GlzEncoderUsrContext *usr, GlzUsrImageContext *image)
+{
+    GlzData *lz_data = (GlzData *)usr;
+    GlzDrawableInstanceItem *glz_drawable_instance = (GlzDrawableInstanceItem *)image;
+    DisplayChannelClient *drawable_cc = glz_drawable_instance->red_glz_drawable->dcc;
+    DisplayChannelClient *this_cc = SPICE_CONTAINEROF(lz_data, DisplayChannelClient, glz_data);
+    if (this_cc == drawable_cc) {
+        dcc_free_glz_drawable_instance(drawable_cc, glz_drawable_instance);
+    } else {
+        /* The glz dictionary is shared between all DisplayChannelClient
+         * instances that belong to the same client, and glz_usr_free_image
+         * can be called by the dictionary code
+         * (glz_dictionary_window_remove_head). Thus this function can be
+         * called from any DisplayChannelClient thread, hence the need for
+         * this check.
+         */
+        pthread_mutex_lock(&drawable_cc->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);
+    }
+}
+
+static void dcc_init_glz_data(DisplayChannelClient *dcc)
+{
+    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;
+}
+
+static void dcc_init_jpeg(DisplayChannelClient *dcc)
+{
+    dcc->jpeg_data.usr.more_space = jpeg_usr_more_space;
+    dcc->jpeg_data.usr.more_lines = jpeg_usr_more_lines;
+
+    dcc->jpeg = jpeg_encoder_create(&dcc->jpeg_data.usr);
+    spice_warn_if_fail(dcc->jpeg);
+}
+
+#ifdef USE_LZ4
+static inline void dcc_init_lz4(DisplayChannelClient *dcc)
+{
+    dcc->lz4_data.usr.more_space = lz4_usr_more_space;
+    dcc->lz4_data.usr.more_lines = lz4_usr_more_lines;
+
+    dcc->lz4 = lz4_encoder_create(&dcc->lz4_data.usr);
+
+    spice_warn_if_fail(dcc->lz4) {
+}
+#endif
+
+static void dcc_init_zlib(DisplayChannelClient *dcc)
+{
+    dcc->zlib_data.usr.more_space = zlib_usr_more_space;
+    dcc->zlib_data.usr.more_input = zlib_usr_more_input;
+
+    dcc->zlib = zlib_encoder_create(&dcc->zlib_data.usr, ZLIB_DEFAULT_COMPRESSION_LEVEL);
+    spice_warn_if_fail(dcc->zlib);
+}
+
+void dcc_encoders_init(DisplayChannelClient *dcc)
+{
+    dcc_init_glz_data(dcc);
+    dcc_init_quic(dcc);
+    dcc_init_lz(dcc);
+    dcc_init_jpeg(dcc);
+#ifdef USE_LZ4
+    dcc_init_lz4(dcc);
+#endif
+    dcc_init_zlib(dcc);
+
+    // todo: tune level according to bandwidth
+    dcc->zlib_level = ZLIB_DEFAULT_COMPRESSION_LEVEL;
+}
+
+void marshaller_add_compressed(SpiceMarshaller *m,
+                               RedCompressBuf *comp_buf, size_t size)
+{
+    size_t max = size;
+    size_t now;
+    do {
+        spice_return_if_fail(comp_buf);
+        now = MIN(sizeof(comp_buf->buf), max);
+        max -= now;
+        spice_marshaller_add_ref_full(m, (uint8_t*)comp_buf->buf, now,
+                                      (spice_marshaller_item_free_func)compress_buf_free, NULL);
+        comp_buf = comp_buf->send_next;
+    } while (max);
+}
diff --git a/server/dcc-encoders.h b/server/dcc-encoders.h
new file mode 100644
index 0000000..7785b2f
--- /dev/null
+++ b/server/dcc-encoders.h
@@ -0,0 +1,145 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009-2015 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef DCC_ENCODERS_H_
+# define DCC_ENCODERS_H_
+
+#include "common/marshaller.h"
+#include "common/quic.h"
+#include "red_channel.h"
+#include "red_parse_qxl.h"
+#include "spice_image_cache.h"
+#include "glz_encoder_dictionary.h"
+#include "glz_encoder.h"
+#include "jpeg_encoder.h"
+#ifdef USE_LZ4
+#include "lz4_encoder.h"
+#endif
+#include "zlib_encoder.h"
+
+typedef struct RedCompressBuf RedCompressBuf;
+typedef struct GlzDrawableInstanceItem GlzDrawableInstanceItem;
+
+void             dcc_encoders_init                           (DisplayChannelClient *dcc);
+void             dcc_free_glz_drawable_instance              (DisplayChannelClient *dcc,
+                                                              GlzDrawableInstanceItem *item);
+void             marshaller_add_compressed                   (SpiceMarshaller *m,
+                                                              RedCompressBuf *comp_buf,
+                                                              size_t size);
+
+RedCompressBuf*  compress_buf_new                            (void);
+void             compress_buf_free                           (RedCompressBuf *buf);
+
+struct RedCompressBuf {
+    uint8_t buf[64 * 1024];
+    RedCompressBuf *send_next;
+};
+
+typedef struct GlzSharedDictionary {
+    RingItem base;
+    GlzEncDictContext *dict;
+    uint32_t refs;
+    uint8_t id;
+    pthread_rwlock_t encode_lock;
+    int migrate_freeze;
+    RedClient *client; // channel clients of the same client share the dict
+} GlzSharedDictionary;
+
+typedef struct  {
+    DisplayChannelClient *dcc;
+    RedCompressBuf *bufs_head;
+    RedCompressBuf *bufs_tail;
+    jmp_buf jmp_env;
+    union {
+        struct {
+            SpiceChunks *chunks;
+            int next;
+            int stride;
+            int reverse;
+        } lines_data;
+        struct {
+            RedCompressBuf* next;
+            int size_left;
+        } compressed_data; // for encoding data that was already compressed by another method
+    } u;
+    char message_buf[512];
+} EncoderData;
+
+typedef struct {
+    QuicUsrContext usr;
+    EncoderData data;
+} QuicData;
+
+typedef struct {
+    LzUsrContext usr;
+    EncoderData data;
+} LzData;
+
+typedef struct {
+    JpegEncoderUsrContext usr;
+    EncoderData data;
+} JpegData;
+
+#ifdef USE_LZ4
+typedef struct {
+    Lz4EncoderUsrContext usr;
+    EncoderData data;
+} Lz4Data;
+#endif
+
+typedef struct {
+    ZlibEncoderUsrContext usr;
+    EncoderData data;
+} ZlibData;
+
+typedef struct {
+    GlzEncoderUsrContext usr;
+    EncoderData data;
+} GlzData;
+
+#define MAX_GLZ_DRAWABLE_INSTANCES 2
+
+typedef struct RedGlzDrawable RedGlzDrawable;
+
+/* for each qxl drawable, there may be several instances of lz drawables */
+/* TODO - reuse this stuff for the top level. I just added a second level of multiplicity
+ * at the Drawable by keeping a ring, so:
+ * Drawable -> (ring of) RedGlzDrawable -> (up to 2) GlzDrawableInstanceItem
+ * and it should probably (but need to be sure...) be
+ * Drawable -> ring of GlzDrawableInstanceItem.
+ */
+struct GlzDrawableInstanceItem {
+    RingItem glz_link;
+    RingItem free_link;
+    GlzEncDictImageContext *glz_instance;
+    RedGlzDrawable         *red_glz_drawable;
+};
+
+struct RedGlzDrawable {
+    RingItem link;    // ordered by the time it was encoded
+    RingItem drawable_link;
+    RedDrawable *red_drawable;
+    Drawable    *drawable;
+    uint32_t     group_id;
+    GlzDrawableInstanceItem instances_pool[MAX_GLZ_DRAWABLE_INSTANCES];
+    Ring instances;
+    uint8_t instances_count;
+    DisplayChannelClient *dcc;
+};
+
+
+#endif /* DCC_ENCODERS_H_ */
diff --git a/server/display-channel.c b/server/display-channel.c
index 163f6b7..3598878 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -144,6 +144,10 @@ DisplayChannelClient *dcc_new(DisplayChannel *display,
     dcc->image_compression = image_compression;
     dcc->jpeg_state = jpeg_state;
     dcc->zlib_glz_state = zlib_glz_state;
+    // todo: tune quality according to bandwidth
+    dcc->jpeg_quality = 85;
+
+    dcc_encoders_init(dcc);
 
     return dcc;
 }
@@ -206,7 +210,7 @@ static MonitorsConfigItem *monitors_config_item_new(RedChannel* channel,
     return mci;
 }
 
-static inline void red_monitors_config_item_add(DisplayChannelClient *dcc)
+static void red_monitors_config_item_add(DisplayChannelClient *dcc)
 {
     DisplayChannel *dc = DCC_TO_DC(dcc);
     MonitorsConfigItem *mci;
diff --git a/server/display-channel.h b/server/display-channel.h
index f45860c..9b16718 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -30,20 +30,13 @@
 #include "reds_gl_canvas.h"
 #endif /* USE_OPENGL */
 #include "reds_sw_canvas.h"
-#include "glz_encoder_dictionary.h"
-#include "glz_encoder.h"
 #include "stat.h"
 #include "reds.h"
 #include "mjpeg_encoder.h"
 #include "red_memslots.h"
 #include "red_parse_qxl.h"
 #include "red_record_qxl.h"
-#include "jpeg_encoder.h"
-#ifdef USE_LZ4
-#include "lz4_encoder.h"
-#endif
 #include "demarshallers.h"
-#include "zlib_encoder.h"
 #include "red_channel.h"
 #include "red_dispatcher.h"
 #include "dispatcher.h"
@@ -56,6 +49,7 @@
 #include "utils.h"
 #include "tree.h"
 #include "stream.h"
+#include "dcc-encoders.h"
 
 #define PALETTE_CACHE_HASH_SHIFT 8
 #define PALETTE_CACHE_HASH_SIZE (1 << PALETTE_CACHE_HASH_SHIFT)
@@ -70,12 +64,6 @@
 #define NUM_STREAMS 50
 #define NUM_SURFACES 10000
 
-typedef struct RedCompressBuf RedCompressBuf;
-struct RedCompressBuf {
-    uint8_t buf[64 * 1024];
-    RedCompressBuf *send_next;
-};
-
 typedef struct WaitForChannels {
     SpiceMsgWaitForChannels header;
     SpiceWaitForChannel buf[MAX_CACHE_CLIENTS];
@@ -88,41 +76,6 @@ typedef struct FreeList {
     WaitForChannels wait;
 } FreeList;
 
-typedef struct GlzSharedDictionary {
-    RingItem base;
-    GlzEncDictContext *dict;
-    uint32_t refs;
-    uint8_t id;
-    pthread_rwlock_t encode_lock;
-    int migrate_freeze;
-    RedClient *client; // channel clients of the same client share the dict
-} GlzSharedDictionary;
-
-typedef struct  {
-    DisplayChannelClient *dcc;
-    RedCompressBuf *bufs_head;
-    RedCompressBuf *bufs_tail;
-    jmp_buf jmp_env;
-    union {
-        struct {
-            SpiceChunks *chunks;
-            int next;
-            int stride;
-            int reverse;
-        } lines_data;
-        struct {
-            RedCompressBuf* next;
-            int size_left;
-        } compressed_data; // for encoding data that was already compressed by another method
-    } u;
-    char message_buf[512];
-} EncoderData;
-
-typedef struct {
-    GlzEncoderUsrContext usr;
-    EncoderData data;
-} GlzData;
-
 typedef struct DependItem {
     Drawable *drawable;
     RingItem ring_item;
@@ -162,6 +115,21 @@ struct DisplayChannelClient {
     SpiceImageCompression image_compression;
     spice_wan_compression_t jpeg_state;
     spice_wan_compression_t zlib_glz_state;
+    int jpeg_quality;
+    int zlib_level;
+
+    QuicData quic_data;
+    QuicContext *quic;
+    LzData lz_data;
+    LzContext  *lz;
+    JpegData jpeg_data;
+    JpegEncoderContext *jpeg;
+#ifdef USE_LZ4
+    Lz4Data lz4_data;
+    Lz4EncoderContext *lz4;
+#endif
+    ZlibData zlib_data;
+    ZlibEncoder *zlib;
 
     int expect_init;
 
@@ -316,9 +284,7 @@ struct DisplayChannel {
     uint32_t renderers[RED_RENDERER_LAST];
     uint32_t renderer;
     int enable_jpeg;
-    int jpeg_quality;
     int enable_zlib_glz_wrap;
-    int zlib_level;
 
     Ring current_list; // of TreeItem
     uint32_t current_size;
diff --git a/server/red_worker.c b/server/red_worker.c
index e0d9593..b40b547 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -51,7 +51,6 @@
 #include <spice/qxl_dev.h>
 #include "common/lz.h"
 #include "common/marshaller.h"
-#include "common/quic.h"
 #include "common/rect.h"
 #include "common/region.h"
 #include "common/ring.h"
@@ -83,7 +82,6 @@
 #define FPS_TEST_INTERVAL 1
 #define MAX_FPS 30
 
-#define ZLIB_DEFAULT_COMPRESSION_LEVEL 3
 #define MIN_GLZ_SIZE_FOR_ZLIB 100
 
 #define VALIDATE_SURFACE_RET(worker, surface_id) \
@@ -238,66 +236,6 @@ typedef struct ImageItem {
     uint8_t data[0];
 } ImageItem;
 
-typedef struct {
-    QuicUsrContext usr;
-    EncoderData data;
-} QuicData;
-
-typedef struct {
-    LzUsrContext usr;
-    EncoderData data;
-} LzData;
-
-typedef struct {
-    JpegEncoderUsrContext usr;
-    EncoderData data;
-} JpegData;
-
-#ifdef USE_LZ4
-typedef struct {
-    Lz4EncoderUsrContext usr;
-    EncoderData data;
-} Lz4Data;
-#endif
-
-typedef struct {
-    ZlibEncoderUsrContext usr;
-    EncoderData data;
-} ZlibData;
-
-/**********************************/
-/* LZ dictionary related entities */
-/**********************************/
-#define MAX_GLZ_DRAWABLE_INSTANCES 2
-
-typedef struct RedGlzDrawable RedGlzDrawable;
-
-/* for each qxl drawable, there may be several instances of lz drawables */
-/* TODO - reuse this stuff for the top level. I just added a second level of multiplicity
- * at the Drawable by keeping a ring, so:
- * Drawable -> (ring of) RedGlzDrawable -> (up to 2) GlzDrawableInstanceItem
- * and it should probably (but need to be sure...) be
- * Drawable -> ring of GlzDrawableInstanceItem.
- */
-typedef struct GlzDrawableInstanceItem {
-    RingItem glz_link;
-    RingItem free_link;
-    GlzEncDictImageContext *glz_instance;
-    RedGlzDrawable         *red_glz_drawable;
-} GlzDrawableInstanceItem;
-
-struct RedGlzDrawable {
-    RingItem link;    // ordered by the time it was encoded
-    RingItem drawable_link;
-    RedDrawable *red_drawable;
-    Drawable    *drawable;
-    uint32_t     group_id;
-    GlzDrawableInstanceItem instances_pool[MAX_GLZ_DRAWABLE_INSTANCES];
-    Ring instances;
-    uint8_t instances_count;
-    DisplayChannelClient *dcc;
-};
-
 pthread_mutex_t glz_dictionary_list_lock = PTHREAD_MUTEX_INITIALIZER;
 Ring glz_dictionary_list = {&glz_dictionary_list, &glz_dictionary_list};
 
@@ -327,23 +265,6 @@ typedef struct RedWorker {
     spice_wan_compression_t jpeg_state;
     spice_wan_compression_t zlib_glz_state;
 
-    QuicData quic_data;
-    QuicContext *quic;
-
-    LzData lz_data;
-    LzContext  *lz;
-
-    JpegData jpeg_data;
-    JpegEncoderContext *jpeg;
-
-#ifdef USE_LZ4
-    Lz4Data lz4_data;
-    Lz4EncoderContext *lz4;
-#endif
-
-    ZlibData zlib_data;
-    ZlibEncoder *zlib;
-
     uint32_t process_commands_generation;
 #ifdef RED_WORKER_STAT
     stat_info_t add_stat;
@@ -402,7 +323,7 @@ static void red_freeze_glz(DisplayChannelClient *dcc);
 static void display_channel_push_release(DisplayChannelClient *dcc, uint8_t type, uint64_t id,
                                          uint64_t* sync_data);
 static int red_display_free_some_independent_glz_drawables(DisplayChannelClient *dcc);
-static void red_display_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable);
+static void dcc_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable);
 static ImageItem *red_add_surface_area_image(DisplayChannelClient *dcc, int surface_id,
                                              SpiceRect *area, PipeItem *pos, int can_lossy);
 static void display_channel_client_release_item_before_push(DisplayChannelClient *dcc,
@@ -2599,7 +2520,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) {
-            red_display_free_glz_drawable(glz->dcc, glz);
+            dcc_free_glz_drawable(glz->dcc, glz);
         }
     }
     red_draw_drawable(display, drawable);
@@ -3462,32 +3383,6 @@ static void red_push_surface_image(DisplayChannelClient *dcc, int surface_id)
     red_channel_client_push(RED_CHANNEL_CLIENT(dcc));
 }
 
-static RedCompressBuf *compress_buf_new(void)
-{
-    return g_slice_new(RedCompressBuf);
-}
-
-static void compress_buf_free(RedCompressBuf *buf)
-{
-    g_slice_free(RedCompressBuf, buf);
-}
-
-static void marshaller_add_compressed(SpiceMarshaller *m,
-                                      RedCompressBuf *comp_buf, size_t size)
-{
-    size_t max = size;
-    size_t now;
-    do {
-        spice_return_if_fail(comp_buf);
-        now = MIN(sizeof(comp_buf->buf), max);
-        max -= now;
-        spice_marshaller_add_ref_full(m, (uint8_t*)comp_buf->buf, now,
-                                      (spice_marshaller_item_free_func)compress_buf_free, NULL);
-        comp_buf = comp_buf->send_next;
-    } while (max);
-}
-
-
 static void fill_base(SpiceMarshaller *base_marshaller, Drawable *drawable)
 {
     SpiceMsgDisplayBase base;
@@ -3577,8 +3472,8 @@ static GlzDrawableInstanceItem *red_display_add_glz_drawable_instance(RedGlzDraw
    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 red_display_free_glz_drawable_instance(DisplayChannelClient *dcc,
-                                                   GlzDrawableInstanceItem *glz_drawable_instance)
+void dcc_free_glz_drawable_instance(DisplayChannelClient *dcc,
+                                    GlzDrawableInstanceItem *glz_drawable_instance)
 {
     DisplayChannel *display_channel = DCC_TO_DC(dcc);
     RedWorker *worker = display_channel->common.worker;
@@ -3630,7 +3525,7 @@ static void red_display_handle_glz_drawables_to_free(DisplayChannelClient* dcc)
         GlzDrawableInstanceItem *drawable_instance = SPICE_CONTAINEROF(ring_link,
                                                                  GlzDrawableInstanceItem,
                                                                  free_link);
-        red_display_free_glz_drawable_instance(dcc, drawable_instance);
+        dcc_free_glz_drawable_instance(dcc, drawable_instance);
     }
     pthread_mutex_unlock(&dcc->glz_drawables_inst_to_free_lock);
 }
@@ -3641,14 +3536,14 @@ static void red_display_handle_glz_drawables_to_free(DisplayChannelClient* dcc)
  * if possible.
  * NOTE - the caller should prevent encoding using the dictionary during this operation
  */
-static void red_display_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable)
+static void dcc_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable)
 {
     RingItem *head_instance = ring_get_head(&drawable->instances);
     int cont = (head_instance != NULL);
 
     while (cont) {
         if (drawable->instances_count == 1) {
-            /* Last instance: red_display_free_glz_drawable_instance will free the drawable */
+            /* Last instance: dcc_free_glz_drawable_instance will free the drawable */
             cont = FALSE;
         }
         GlzDrawableInstanceItem *instance = SPICE_CONTAINEROF(head_instance,
@@ -3660,7 +3555,7 @@ static void red_display_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawa
                                             instance->glz_instance,
                                             &dcc->glz_data.usr);
         }
-        red_display_free_glz_drawable_instance(dcc, instance);
+        dcc_free_glz_drawable_instance(dcc, instance);
 
         if (cont) {
             head_instance = ring_get_head(&drawable->instances);
@@ -3685,7 +3580,7 @@ static void red_display_client_clear_glz_drawables(DisplayChannelClient *dcc)
         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
-        red_display_free_glz_drawable(dcc, drawable);
+        dcc_free_glz_drawable(dcc, drawable);
     }
     pthread_rwlock_unlock(&glz_dict->encode_lock);
 }
@@ -3721,361 +3616,13 @@ static int red_display_free_some_independent_glz_drawables(DisplayChannelClient
         RedGlzDrawable *glz_drawable = SPICE_CONTAINEROF(ring_link, RedGlzDrawable, link);
         ring_link = ring_next(&dcc->glz_drawables, ring_link);
         if (!glz_drawable->drawable) {
-            red_display_free_glz_drawable(dcc, glz_drawable);
+            dcc_free_glz_drawable(dcc, glz_drawable);
             n++;
         }
     }
     return n;
 }
 
-/******************************************************
- *              Encoders callbacks
-*******************************************************/
-static SPICE_GNUC_NORETURN SPICE_GNUC_PRINTF(2, 3) void
-quic_usr_error(QuicUsrContext *usr, const char *fmt, ...)
-{
-    EncoderData *usr_data = &(((QuicData *)usr)->data);
-    va_list ap;
-
-    va_start(ap, fmt);
-    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
-    va_end(ap);
-    spice_critical("%s", usr_data->message_buf);
-
-    longjmp(usr_data->jmp_env, 1);
-}
-
-static SPICE_GNUC_NORETURN SPICE_GNUC_PRINTF(2, 3) void
-lz_usr_error(LzUsrContext *usr, const char *fmt, ...)
-{
-    EncoderData *usr_data = &(((LzData *)usr)->data);
-    va_list ap;
-
-    va_start(ap, fmt);
-    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
-    va_end(ap);
-    spice_critical("%s", usr_data->message_buf);
-
-    longjmp(usr_data->jmp_env, 1);
-}
-
-static SPICE_GNUC_PRINTF(2, 3) void glz_usr_error(GlzEncoderUsrContext *usr, const char *fmt, ...)
-{
-    EncoderData *usr_data = &(((GlzData *)usr)->data);
-    va_list ap;
-
-    va_start(ap, fmt);
-    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
-    va_end(ap);
-
-    spice_critical("%s", usr_data->message_buf); // if global lz fails in the middle
-                                        // the consequences are not predictable since the window
-                                        // can turn to be unsynchronized between the server and
-                                        // and the client
-}
-
-static SPICE_GNUC_PRINTF(2, 3) void quic_usr_warn(QuicUsrContext *usr, const char *fmt, ...)
-{
-    EncoderData *usr_data = &(((QuicData *)usr)->data);
-    va_list ap;
-
-    va_start(ap, fmt);
-    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
-    va_end(ap);
-    spice_warning("%s", usr_data->message_buf);
-}
-
-static SPICE_GNUC_PRINTF(2, 3) void lz_usr_warn(LzUsrContext *usr, const char *fmt, ...)
-{
-    EncoderData *usr_data = &(((LzData *)usr)->data);
-    va_list ap;
-
-    va_start(ap, fmt);
-    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
-    va_end(ap);
-    spice_warning("%s", usr_data->message_buf);
-}
-
-static SPICE_GNUC_PRINTF(2, 3) void glz_usr_warn(GlzEncoderUsrContext *usr, const char *fmt, ...)
-{
-    EncoderData *usr_data = &(((GlzData *)usr)->data);
-    va_list ap;
-
-    va_start(ap, fmt);
-    vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap);
-    va_end(ap);
-    spice_warning("%s", usr_data->message_buf);
-}
-
-static void *quic_usr_malloc(QuicUsrContext *usr, int size)
-{
-    return spice_malloc(size);
-}
-
-static void *lz_usr_malloc(LzUsrContext *usr, int size)
-{
-    return spice_malloc(size);
-}
-
-static void *glz_usr_malloc(GlzEncoderUsrContext *usr, int size)
-{
-    return spice_malloc(size);
-}
-
-static void quic_usr_free(QuicUsrContext *usr, void *ptr)
-{
-    free(ptr);
-}
-
-static void lz_usr_free(LzUsrContext *usr, void *ptr)
-{
-    free(ptr);
-}
-
-static void glz_usr_free(GlzEncoderUsrContext *usr, void *ptr)
-{
-    free(ptr);
-}
-
-static int encoder_usr_more_space(EncoderData *enc_data, uint8_t **io_ptr)
-{
-    RedCompressBuf *buf;
-
-    buf = compress_buf_new();
-    enc_data->bufs_tail->send_next = buf;
-    enc_data->bufs_tail = buf;
-    buf->send_next = NULL;
-    *io_ptr = buf->buf;
-    return sizeof(buf->buf);
-}
-
-static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed)
-{
-    EncoderData *usr_data = &(((QuicData *)usr)->data);
-    return encoder_usr_more_space(usr_data, (uint8_t **)io_ptr) / sizeof(uint32_t);
-}
-
-static int lz_usr_more_space(LzUsrContext *usr, uint8_t **io_ptr)
-{
-    EncoderData *usr_data = &(((LzData *)usr)->data);
-    return encoder_usr_more_space(usr_data, io_ptr);
-}
-
-static int glz_usr_more_space(GlzEncoderUsrContext *usr, uint8_t **io_ptr)
-{
-    EncoderData *usr_data = &(((GlzData *)usr)->data);
-    return encoder_usr_more_space(usr_data, io_ptr);
-}
-
-static int jpeg_usr_more_space(JpegEncoderUsrContext *usr, uint8_t **io_ptr)
-{
-    EncoderData *usr_data = &(((JpegData *)usr)->data);
-    return encoder_usr_more_space(usr_data, io_ptr);
-}
-
-#ifdef USE_LZ4
-static int lz4_usr_more_space(Lz4EncoderUsrContext *usr, uint8_t **io_ptr)
-{
-    EncoderData *usr_data = &(((Lz4Data *)usr)->data);
-    return (encoder_usr_more_space(usr_data, (uint32_t **)io_ptr) << 2);
-}
-#endif
-
-static int zlib_usr_more_space(ZlibEncoderUsrContext *usr, uint8_t **io_ptr)
-{
-    EncoderData *usr_data = &(((ZlibData *)usr)->data);
-    return encoder_usr_more_space(usr_data, io_ptr);
-}
-
-static inline int encoder_usr_more_lines(EncoderData *enc_data, uint8_t **lines)
-{
-    struct SpiceChunk *chunk;
-
-    if (enc_data->u.lines_data.reverse) {
-        if (!(enc_data->u.lines_data.next >= 0)) {
-            return 0;
-        }
-    } else {
-        if (!(enc_data->u.lines_data.next < enc_data->u.lines_data.chunks->num_chunks)) {
-            return 0;
-        }
-    }
-
-    chunk = &enc_data->u.lines_data.chunks->chunk[enc_data->u.lines_data.next];
-    if (chunk->len % enc_data->u.lines_data.stride) {
-        return 0;
-    }
-
-    if (enc_data->u.lines_data.reverse) {
-        enc_data->u.lines_data.next--;
-        *lines = chunk->data + chunk->len - enc_data->u.lines_data.stride;
-    } else {
-        enc_data->u.lines_data.next++;
-        *lines = chunk->data;
-    }
-
-    return chunk->len / enc_data->u.lines_data.stride;
-}
-
-static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines)
-{
-    EncoderData *usr_data = &(((QuicData *)usr)->data);
-    return encoder_usr_more_lines(usr_data, lines);
-}
-
-static int lz_usr_more_lines(LzUsrContext *usr, uint8_t **lines)
-{
-    EncoderData *usr_data = &(((LzData *)usr)->data);
-    return encoder_usr_more_lines(usr_data, lines);
-}
-
-static int glz_usr_more_lines(GlzEncoderUsrContext *usr, uint8_t **lines)
-{
-    EncoderData *usr_data = &(((GlzData *)usr)->data);
-    return encoder_usr_more_lines(usr_data, lines);
-}
-
-static int jpeg_usr_more_lines(JpegEncoderUsrContext *usr, uint8_t **lines)
-{
-    EncoderData *usr_data = &(((JpegData *)usr)->data);
-    return encoder_usr_more_lines(usr_data, lines);
-}
-
-#ifdef USE_LZ4
-static int lz4_usr_more_lines(Lz4EncoderUsrContext *usr, uint8_t **lines)
-{
-    EncoderData *usr_data = &(((Lz4Data *)usr)->data);
-    return encoder_usr_more_lines(usr_data, lines);
-}
-#endif
-
-static int zlib_usr_more_input(ZlibEncoderUsrContext *usr, uint8_t** input)
-{
-    EncoderData *usr_data = &(((ZlibData *)usr)->data);
-    int buf_size;
-
-    if (!usr_data->u.compressed_data.next) {
-        spice_assert(usr_data->u.compressed_data.size_left == 0);
-        return 0;
-    }
-
-    *input = (uint8_t*)usr_data->u.compressed_data.next->buf;
-    buf_size = MIN(sizeof(usr_data->u.compressed_data.next->buf),
-                   usr_data->u.compressed_data.size_left);
-
-    usr_data->u.compressed_data.next = usr_data->u.compressed_data.next->send_next;
-    usr_data->u.compressed_data.size_left -= buf_size;
-    return buf_size;
-}
-
-static void glz_usr_free_image(GlzEncoderUsrContext *usr, GlzUsrImageContext *image)
-{
-    GlzData *lz_data = (GlzData *)usr;
-    GlzDrawableInstanceItem *glz_drawable_instance = (GlzDrawableInstanceItem *)image;
-    DisplayChannelClient *drawable_cc = glz_drawable_instance->red_glz_drawable->dcc;
-    DisplayChannelClient *this_cc = SPICE_CONTAINEROF(lz_data, DisplayChannelClient, glz_data);
-    if (this_cc == drawable_cc) {
-        red_display_free_glz_drawable_instance(drawable_cc, glz_drawable_instance);
-    } else {
-        /* The glz dictionary is shared between all DisplayChannelClient
-         * instances that belong to the same client, and glz_usr_free_image
-         * can be called by the dictionary code
-         * (glz_dictionary_window_remove_head). Thus this function can be
-         * called from any DisplayChannelClient thread, hence the need for
-         * this check.
-         */
-        pthread_mutex_lock(&drawable_cc->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);
-    }
-}
-
-static inline void red_init_quic(RedWorker *worker)
-{
-    worker->quic_data.usr.error = quic_usr_error;
-    worker->quic_data.usr.warn = quic_usr_warn;
-    worker->quic_data.usr.info = quic_usr_warn;
-    worker->quic_data.usr.malloc = quic_usr_malloc;
-    worker->quic_data.usr.free = quic_usr_free;
-    worker->quic_data.usr.more_space = quic_usr_more_space;
-    worker->quic_data.usr.more_lines = quic_usr_more_lines;
-
-    worker->quic = quic_create(&worker->quic_data.usr);
-
-    if (!worker->quic) {
-        spice_critical("create quic failed");
-    }
-}
-
-static inline void red_init_lz(RedWorker *worker)
-{
-    worker->lz_data.usr.error = lz_usr_error;
-    worker->lz_data.usr.warn = lz_usr_warn;
-    worker->lz_data.usr.info = lz_usr_warn;
-    worker->lz_data.usr.malloc = lz_usr_malloc;
-    worker->lz_data.usr.free = lz_usr_free;
-    worker->lz_data.usr.more_space = lz_usr_more_space;
-    worker->lz_data.usr.more_lines = lz_usr_more_lines;
-
-    worker->lz = lz_create(&worker->lz_data.usr);
-
-    if (!worker->lz) {
-        spice_critical("create lz failed");
-    }
-}
-
-/* TODO: split off to DisplayChannel? avoid just copying those cb pointers */
-static inline void red_display_init_glz_data(DisplayChannelClient *dcc)
-{
-    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;
-}
-
-static inline void red_init_jpeg(RedWorker *worker)
-{
-    worker->jpeg_data.usr.more_space = jpeg_usr_more_space;
-    worker->jpeg_data.usr.more_lines = jpeg_usr_more_lines;
-
-    worker->jpeg = jpeg_encoder_create(&worker->jpeg_data.usr);
-
-    if (!worker->jpeg) {
-        spice_critical("create jpeg encoder failed");
-    }
-}
-
-#ifdef USE_LZ4
-static inline void red_init_lz4(RedWorker *worker)
-{
-    worker->lz4_data.usr.more_space = lz4_usr_more_space;
-    worker->lz4_data.usr.more_lines = lz4_usr_more_lines;
-
-    worker->lz4 = lz4_encoder_create(&worker->lz4_data.usr);
-
-    if (!worker->lz4) {
-        spice_critical("create lz4 encoder failed");
-    }
-}
-#endif
-
-static inline void red_init_zlib(RedWorker *worker)
-{
-    worker->zlib_data.usr.more_space = zlib_usr_more_space;
-    worker->zlib_data.usr.more_input = zlib_usr_more_input;
-
-    worker->zlib = zlib_encoder_create(&worker->zlib_data.usr, ZLIB_DEFAULT_COMPRESSION_LEVEL);
-
-    if (!worker->zlib) {
-        spice_critical("create zlib encoder failed");
-    }
-}
-
 typedef struct compress_send_data_t {
     void*    comp_buf;
     uint32_t comp_buf_size;
@@ -4088,7 +3635,6 @@ static inline int red_glz_compress_image(DisplayChannelClient *dcc,
                                          compress_send_data_t* o_comp_data)
 {
     DisplayChannel *display_channel = DCC_TO_DC(dcc);
-    RedWorker *worker = display_channel->common.worker;
 #ifdef COMPRESS_STAT
     stat_time_t start_time = stat_now(worker);
 #endif
@@ -4103,12 +3649,6 @@ static inline int red_glz_compress_image(DisplayChannelClient *dcc,
 
     glz_data->data.bufs_tail = compress_buf_new();
     glz_data->data.bufs_head = glz_data->data.bufs_tail;
-
-    if (!glz_data->data.bufs_head) {
-        return FALSE;
-    }
-
-    glz_data->data.bufs_head->send_next = NULL;
     glz_data->data.dcc = dcc;
 
     glz_drawable = red_display_get_glz_drawable(dcc, drawable);
@@ -4118,7 +3658,7 @@ static inline int red_glz_compress_image(DisplayChannelClient *dcc,
     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_data->usr.more_lines = glz_usr_more_lines;
+    /* fixme: remove? glz_data->usr.more_lines = glz_usr_more_lines; */
 
     glz_size = glz_encode(dcc->glz, type, src->x, src->y,
                           (src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN), NULL, 0,
@@ -4135,24 +3675,17 @@ static inline int red_glz_compress_image(DisplayChannelClient *dcc,
 #ifdef COMPRESS_STAT
     start_time = stat_now(worker);
 #endif
-    zlib_data = &worker->zlib_data;
+    zlib_data = &dcc->zlib_data;
 
     zlib_data->data.bufs_tail = compress_buf_new();
     zlib_data->data.bufs_head = zlib_data->data.bufs_tail;
-
-    if (!zlib_data->data.bufs_head) {
-        spice_warning("failed to allocate zlib compress buffer");
-        goto glz;
-    }
-
-    zlib_data->data.bufs_head->send_next = NULL;
     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(worker->zlib, display_channel->zlib_level,
-                            glz_size, zlib_data->data.bufs_head->buf,
+    zlib_size = zlib_encode(dcc->zlib, dcc->zlib_level,
+                            glz_size, (uint8_t*)zlib_data->data.bufs_head->buf,
                             sizeof(zlib_data->data.bufs_head->buf));
 
     // the compressed buffer is bigger than the original data
@@ -4188,10 +3721,8 @@ static inline int red_lz_compress_image(DisplayChannelClient *dcc,
                                         SpiceImage *dest, SpiceBitmap *src,
                                         compress_send_data_t* o_comp_data, uint32_t group_id)
 {
-    DisplayChannel *display_channel = DCC_TO_DC(dcc);
-    RedWorker *worker = display_channel->common.worker;
-    LzData *lz_data = &worker->lz_data;
-    LzContext *lz = worker->lz;
+    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
 
@@ -4201,12 +3732,6 @@ static inline int red_lz_compress_image(DisplayChannelClient *dcc,
 
     lz_data->data.bufs_tail = compress_buf_new();
     lz_data->data.bufs_head = lz_data->data.bufs_tail;
-
-    if (!lz_data->data.bufs_head) {
-        return FALSE;
-    }
-
-    lz_data->data.bufs_head->send_next = NULL;
     lz_data->data.dcc = dcc;
 
     if (setjmp(lz_data->data.jmp_env)) {
@@ -4222,7 +3747,7 @@ static inline int red_lz_compress_image(DisplayChannelClient *dcc,
     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;
-    lz_data->usr.more_lines = lz_usr_more_lines;
+    /* fixme: remove? lz_data->usr.more_lines = lz_usr_more_lines; */
 
     size = lz_encode(lz, type, src->x, src->y,
                      !!(src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN),
@@ -4266,12 +3791,10 @@ static int red_jpeg_compress_image(DisplayChannelClient *dcc, SpiceImage *dest,
                                    SpiceBitmap *src, compress_send_data_t* o_comp_data,
                                    uint32_t group_id)
 {
-    DisplayChannel *display_channel = DCC_TO_DC(dcc);
-    RedWorker *worker = display_channel->common.worker;
-    JpegData *jpeg_data = &worker->jpeg_data;
-    LzData *lz_data = &worker->lz_data;
-    JpegEncoderContext *jpeg = worker->jpeg;
-    LzContext *lz = worker->lz;
+    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;
@@ -4304,13 +3827,6 @@ static int red_jpeg_compress_image(DisplayChannelClient *dcc, SpiceImage *dest,
 
     jpeg_data->data.bufs_tail = compress_buf_new();
     jpeg_data->data.bufs_head = jpeg_data->data.bufs_tail;
-
-    if (!jpeg_data->data.bufs_head) {
-        spice_warning("failed to allocate compress buffer");
-        return FALSE;
-    }
-
-    jpeg_data->data.bufs_head->send_next = NULL;
     jpeg_data->data.dcc = dcc;
 
     if (setjmp(jpeg_data->data.jmp_env)) {
@@ -4328,7 +3844,7 @@ static int red_jpeg_compress_image(DisplayChannelClient *dcc, SpiceImage *dest,
 
     jpeg_data->data.u.lines_data.chunks = src->data;
     jpeg_data->data.u.lines_data.stride = src->stride;
-    jpeg_data->usr.more_lines = jpeg_usr_more_lines;
+    /* fixme: remove? jpeg_data->usr.more_lines = jpeg_usr_more_lines; */
     if ((src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) {
         jpeg_data->data.u.lines_data.next = 0;
         jpeg_data->data.u.lines_data.reverse = 0;
@@ -4338,7 +3854,7 @@ static int red_jpeg_compress_image(DisplayChannelClient *dcc, SpiceImage *dest,
         jpeg_data->data.u.lines_data.reverse = 1;
         stride = -src->stride;
     }
-    jpeg_size = jpeg_encode(jpeg, display_channel->jpeg_quality, jpeg_in_type,
+    jpeg_size = jpeg_encode(jpeg, dcc->jpeg_quality, jpeg_in_type,
                             src->x, src->y, NULL,
                             0, stride, jpeg_data->data.bufs_head->buf,
                             sizeof(jpeg_data->data.bufs_head->buf));
@@ -4374,7 +3890,7 @@ static int red_jpeg_compress_image(DisplayChannelClient *dcc, SpiceImage *dest,
     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;
-    lz_data->usr.more_lines = lz_usr_more_lines;
+    /* fixme: remove? lz_data->usr.more_lines = lz_usr_more_lines; */
 
     alpha_lz_size = lz_encode(lz, LZ_IMAGE_TYPE_XXXA, src->x, src->y,
                                !!(src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN),
@@ -4474,10 +3990,8 @@ static inline int red_quic_compress_image(DisplayChannelClient *dcc, SpiceImage
                                           SpiceBitmap *src, compress_send_data_t* o_comp_data,
                                           uint32_t group_id)
 {
-    DisplayChannel *display_channel = DCC_TO_DC(dcc);
-    RedWorker *worker = display_channel->common.worker;
-    QuicData *quic_data = &worker->quic_data;
-    QuicContext *quic = worker->quic;
+    QuicData *quic_data = &dcc->quic_data;
+    QuicContext *quic = dcc->quic;
     volatile QuicImageType type;
     int size, stride;
 
@@ -4504,7 +4018,6 @@ static inline int red_quic_compress_image(DisplayChannelClient *dcc, SpiceImage
 
     quic_data->data.bufs_tail = compress_buf_new();
     quic_data->data.bufs_head = quic_data->data.bufs_tail;
-    quic_data->data.bufs_head->send_next = NULL;
     quic_data->data.dcc = dcc;
 
     if (setjmp(quic_data->data.jmp_env)) {
@@ -4522,7 +4035,7 @@ static inline int red_quic_compress_image(DisplayChannelClient *dcc, SpiceImage
 
     quic_data->data.u.lines_data.chunks = src->data;
     quic_data->data.u.lines_data.stride = src->stride;
-    quic_data->usr.more_lines = quic_usr_more_lines;
+    /* fixme: remove? quic_data->usr.more_lines = quic_usr_more_lines; */
     if ((src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) {
         quic_data->data.u.lines_data.next = 0;
         quic_data->data.u.lines_data.reverse = 0;
@@ -8497,8 +8010,6 @@ static void handle_new_display_channel(RedWorker *worker, RedClient *client, Red
     stream_buf_size = 32*1024;
     dcc->send_data.stream_outbuf = spice_malloc(stream_buf_size);
     dcc->send_data.stream_outbuf_size = stream_buf_size;
-    red_display_init_glz_data(dcc);
-
     dcc->send_data.free_list.res =
         spice_malloc(sizeof(SpiceResourceList) +
                      DISPLAY_FREE_LIST_DEFAULT_SIZE * sizeof(SpiceResourceID));
@@ -8510,9 +8021,6 @@ static void handle_new_display_channel(RedWorker *worker, RedClient *client, Red
         display_channel->enable_jpeg = (dcc->jpeg_state == SPICE_WAN_COMPRESSION_ALWAYS);
     }
 
-    // todo: tune quality according to bandwidth
-    display_channel->jpeg_quality = 85;
-
     if (dcc->zlib_glz_state == SPICE_WAN_COMPRESSION_AUTO) {
         display_channel->enable_zlib_glz_wrap = dcc->common.is_low_bandwidth;
     } else {
@@ -8525,8 +8033,6 @@ static void handle_new_display_channel(RedWorker *worker, RedClient *client, Red
 
     guest_set_client_capabilities(worker);
 
-    // todo: tune level according to bandwidth
-    display_channel->zlib_level = ZLIB_DEFAULT_COMPRESSION_LEVEL;
     dcc_init_stream_agents(dcc);
     on_new_display_channel_client(dcc);
 }
@@ -9552,13 +9058,6 @@ RedWorker* red_worker_new(QXLInstance *qxl, RedDispatcher *red_dispatcher)
 
     spice_warn_if(init_info.n_surfaces > NUM_SURFACES);
 
-    red_init_quic(worker);
-    red_init_lz(worker);
-    red_init_jpeg(worker);
-#ifdef USE_LZ4
-    red_init_lz4(worker);
-#endif
-    red_init_zlib(worker);
     worker->event_timeout = INF_EVENT_WAIT;
 
     worker->cursor_channel = cursor_channel_new(worker);
-- 
2.4.3



More information about the Spice-devel mailing list