> > On Wed, Nov 18, 2015 at 10:42 PM, Jonathon Jongsma <jjongsma@xxxxxxxxxx> > wrote: > > From: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> > > > > Author: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> > > Signed-off-by: Jonathon Jongsma <jjongsma@xxxxxxxxxx> > > --- > > > > Changes since v1 > > > > - Remove extra space in "# define" > > - remove commented-out "fixme: remove?" lines > > > > server/Makefile.am | 2 + > > server/dcc-encoders.c | 428 ++++++++++++++++++++++++++++++++++++ > > server/dcc-encoders.h | 153 +++++++++++++ > > server/display-channel.c | 6 +- > > server/display-channel.h | 74 ++----- > > server/red_worker.c | 548 > > ++--------------------------------------------- > > 6 files changed, 620 insertions(+), 591 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..45db96f > > --- /dev/null > > +++ b/server/dcc-encoders.c > > @@ -0,0 +1,428 @@ > > +/* -*- 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/>. > > +*/ > > +#ifdef HAVE_CONFIG_H > > +#include <config.h> > > +#endif > > + > > +#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 > > +} > > These 3 functions have pretty much the same code, which could be > easily replaced by a macro. > > > + > > +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); > > +} > > + > > Same here ... > > > +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); > > +} > > + > > +/* Allocate more space for compressed buffer. > > + * The pointer returned in io_ptr is garanteed to be aligned to 4 bytes. > > + */ > > +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.bytes; > > + 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, io_ptr); > > +} > > +#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); > > +} > > > A macro could be used for pretty much all these _more_space functions as > well. > > > + > > +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 > > + > > Same for _more_lines ... > > > +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 = usr_data->u.compressed_data.next->buf.bytes; > > + 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); > > + > > + if (!dcc->quic) { > > + spice_critical("create quic failed"); > > + } > > +} > > + > > +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); > > + > > + if (!dcc->lz) { > > + spice_critical("create lz failed"); > > + } > > +} > > + > > +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); > > + > > + if (!dcc->jpeg) { > > + spice_critical("create jpeg encoder failed"); > > + } > > +} > > + > > +#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); > > + > > + if (!dcc->lz4) { > > + spice_critical("create lz4 encoder failed"); > > + } > > +} > > +#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); > > + > > + if (!dcc->zlib) { > > + spice_critical("create zlib encoder failed"); > > + } > > +} > > + > > +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; > > +} > > + > > +static void marshaller_compress_buf_free(uint8_t *data, void *opaque) > > +{ > > + compress_buf_free((RedCompressBuf *) opaque); > > +} > > + > > +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, comp_buf->buf.bytes, now, > > + marshaller_compress_buf_free, > > comp_buf); > > + 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..c9e06e7 > > --- /dev/null > > +++ b/server/dcc-encoders.h > > @@ -0,0 +1,153 @@ > > +/* -*- 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); > > + > > +#define RED_COMPRESS_BUF_SIZE (1024 * 64) > > +struct RedCompressBuf { > > + /* This buffer provide space for compression algorithms. > > + * Some algorithms access the buffer as an array of 32 bit words > > + * so is defined to make sure is always aligned that way. > > + */ > > + union { > > + uint8_t bytes[RED_COMPRESS_BUF_SIZE]; > > + uint32_t words[RED_COMPRESS_BUF_SIZE / 4]; > > + } buf; > > + 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 c26b5dd..d4fcc7e 100644 > > --- a/server/display-channel.c > > +++ b/server/display-channel.c > > @@ -159,6 +159,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 > > s/todo/TODO/ > > > + dcc->jpeg_quality = 85; > > + > > + dcc_encoders_init(dcc); > > > > return dcc; > > } > > @@ -236,7 +240,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 8deb71c..90f8455 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,20 +64,6 @@ > > #define NUM_STREAMS 50 > > #define NUM_SURFACES 10000 > > > > -#define RED_COMPRESS_BUF_SIZE (1024 * 64) > > -typedef struct RedCompressBuf RedCompressBuf; > > -struct RedCompressBuf { > > - /* This buffer provide space for compression algorithms. > > - * Some algorithms access the buffer as an array of 32 bit words > > - * so is defined to make sure is always aligned that way. > > - */ > > - union { > > - uint8_t bytes[RED_COMPRESS_BUF_SIZE]; > > - uint32_t words[RED_COMPRESS_BUF_SIZE / 4]; > > - } buf; > > - RedCompressBuf *send_next; > > -}; > > - > > typedef struct WaitForChannels { > > SpiceMsgWaitForChannels header; > > SpiceWaitForChannel buf[MAX_CACHE_CLIENTS]; > > @@ -96,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; > > @@ -175,6 +120,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; > > > > @@ -333,9 +293,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 16677fc..5609b47 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" > > @@ -79,7 +78,6 @@ > > > > #define DISPLAY_FREE_LIST_DEFAULT_SIZE 128 > > > > -#define ZLIB_DEFAULT_COMPRESSION_LEVEL 3 > > #define MIN_GLZ_SIZE_FOR_ZLIB 100 > > > > #define VALIDATE_SURFACE_RET(worker, surface_id) \ > > @@ -136,66 +134,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}; > > > > @@ -232,23 +170,6 @@ 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_STATISTICS > > StatNodeRef stat; > > @@ -2175,37 +2096,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 inline void compress_buf_free(RedCompressBuf *buf) > > -{ > > - g_slice_free(RedCompressBuf, buf); > > -} > > - > > -static void marshaller_compress_buf_free(uint8_t *data, void *opaque) > > -{ > > - compress_buf_free((RedCompressBuf *) opaque); > > -} > > - > > -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, comp_buf->buf.bytes, now, > > - marshaller_compress_buf_free, > > comp_buf); > > - comp_buf = comp_buf->send_next; > > - } while (max); > > -} > > - > > - > > static void fill_base(SpiceMarshaller *base_marshaller, Drawable > > *drawable) > > { > > SpiceMsgDisplayBase base; > > @@ -2446,357 +2336,6 @@ static int > > red_display_free_some_independent_glz_drawables(DisplayChannelClient > > 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); > > -} > > - > > -/* Allocate more space for compressed buffer. > > - * The pointer returned in io_ptr is garanteed to be aligned to 4 bytes. > > - */ > > -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.bytes; > > - 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, io_ptr); > > -} > > -#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 = usr_data->u.compressed_data.next->buf.bytes; > > - 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) { > > - 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 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; > > @@ -2809,7 +2348,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(display_channel->zlib_glz_stat.clock); > > #endif > > @@ -2824,12 +2362,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); > > @@ -2839,7 +2371,6 @@ 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; > > > > glz_size = glz_encode(dcc->glz, type, src->x, src->y, > > (src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN), > > NULL, 0, > > @@ -2856,23 +2387,16 @@ static inline int > > red_glz_compress_image(DisplayChannelClient *dcc, > > #ifdef COMPRESS_STAT > > start_time = stat_now(display_channel->zlib_glz_stat.clock); > > #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, > > + zlib_size = zlib_encode(dcc->zlib, dcc->zlib_level, > > glz_size, > > zlib_data->data.bufs_head->buf.bytes, > > sizeof(zlib_data->data.bufs_head->buf)); > > > > @@ -2909,10 +2433,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 > > > > @@ -2922,12 +2444,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)) { > > @@ -2943,7 +2459,6 @@ 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; > > > > size = lz_encode(lz, type, src->x, src->y, > > !!(src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN), > > @@ -2987,12 +2502,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; > > @@ -3025,13 +2538,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)) { > > @@ -3049,7 +2555,6 @@ 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; > > if ((src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { > > jpeg_data->data.u.lines_data.next = 0; > > jpeg_data->data.u.lines_data.reverse = 0; > > @@ -3059,7 +2564,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.bytes, > > sizeof(jpeg_data->data.bufs_head->buf)); > > @@ -3095,7 +2600,6 @@ 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; > > > > alpha_lz_size = lz_encode(lz, LZ_IMAGE_TYPE_XXXA, src->x, src->y, > > !!(src->flags & > > SPICE_BITMAP_FLAGS_TOP_DOWN), > > @@ -3130,14 +2634,12 @@ static int > > red_lz4_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; > > - Lz4Data *lz4_data = &worker->lz4_data; > > - Lz4EncoderContext *lz4 = worker->lz4; > > + Lz4Data *lz4_data = &dcc->lz4_data; > > + Lz4EncoderContext *lz4 = dcc->lz4; > > int lz4_size = 0; > > > > #ifdef COMPRESS_STAT > > - stat_time_t start_time = stat_now(worker->clockid); > > + stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->lz4_stat.clock); > > #endif > > > > lz4_data->data.bufs_tail = compress_buf_new(); > > @@ -3168,7 +2670,7 @@ static int > > red_lz4_compress_image(DisplayChannelClient *dcc, SpiceImage *dest, > > lz4_data->data.u.lines_data.stride = src->stride; > > lz4_data->data.u.lines_data.next = 0; > > lz4_data->data.u.lines_data.reverse = 0; > > - lz4_data->usr.more_lines = lz4_usr_more_lines; > > + /* fixme remove? lz4_data->usr.more_lines = lz4_usr_more_lines; */ > > > > lz4_size = lz4_encode(lz4, src->y, src->stride, > > lz4_data->data.bufs_head->buf.bytes, > > sizeof(lz4_data->data.bufs_head->buf), > > @@ -3185,7 +2687,7 @@ static int > > red_lz4_compress_image(DisplayChannelClient *dcc, SpiceImage *dest, > > o_comp_data->comp_buf = lz4_data->data.bufs_head; > > o_comp_data->comp_buf_size = lz4_size; > > > > - stat_compress_add(&display_channel->lz4_stat, start_time, src->stride > > * src->y, > > + stat_compress_add(&DCC_TO_DC(dcc)->lz4_stat, start_time, src->stride * > > src->y, > > o_comp_data->comp_buf_size); > > return TRUE; > > } > > @@ -3195,10 +2697,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; > > > > @@ -3225,7 +2725,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)) { > > @@ -3243,7 +2742,6 @@ 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; > > if ((src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { > > quic_data->data.u.lines_data.next = 0; > > quic_data->data.u.lines_data.reverse = 0; > > @@ -7227,8 +6725,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)); > > @@ -7240,9 +6736,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 { > > @@ -7255,8 +6748,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); > > } > > @@ -8279,13 +7770,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 > > > > _______________________________________________ > > Spice-devel mailing list > > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > > http://lists.freedesktop.org/mailman/listinfo/spice-devel > > Seems okay. ACK. > Note: The comments about using macros are a suggestion not a must be > ... feel free to ignore them. > I think the additional macro would be better in another patch as this is just supposed to move stuff. Merged. Frediano _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel