[Spice-devel] [PATCH v2 07/18] worker: move compress to dcc_compress_image()
Frediano Ziglio
fziglio at redhat.com
Thu Nov 19 06:46:20 PST 2015
>
> This is a reduced diff (removed the move)
>
> --- before.c 2015-11-19 13:04:55.376919069 +0000
> +++ after.c 2015-11-19 12:53:18.732173333 +0000
> @@ -305,21 +305,21 @@
> return;
> }
>
> dcc->surface_client_created[surface_id] = FALSE;
> destroy = surface_destroy_item_new(channel, surface_id);
> red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc),
> &destroy->pipe_item);
> }
>
> /* if already exists, returns it. Otherwise allocates and adds it (1) to the
> ring tail
> in the channel (2) to the Drawable*/
> -static RedGlzDrawable *red_display_get_glz_drawable(DisplayChannelClient
> *dcc, Drawable *drawable)
> +static RedGlzDrawable *get_glz_drawable(DisplayChannelClient *dcc, Drawable
> *drawable)
> {
> RedGlzDrawable *ret;
> RingItem *item, *next;
>
> // TODO - I don't really understand what's going on here, so doing the
> technical equivalent
> // now that we have multiple glz_dicts, so the only way to go from dcc
> to drawable glz is to go
> // over the glz_ring (unless adding some better data structure then a
> ring)
> DRAWABLE_FOREACH_GLZ_SAFE(drawable, item, next, ret) {
> if (ret->dcc == dcc) {
> return ret;
> @@ -332,67 +332,67 @@
> ret->red_drawable = red_drawable_ref(drawable->red_drawable);
> ret->drawable = drawable;
> ret->group_id = drawable->group_id;
> ret->instances_count = 0;
> ring_init(&ret->instances);
>
> ring_item_init(&ret->link);
> ring_item_init(&ret->drawable_link);
> ring_add_before(&ret->link, &dcc->glz_drawables);
> ring_add(&drawable->glz_ring, &ret->drawable_link);
> - DCC_TO_WORKER(dcc)->glz_drawable_count++;
> + dcc->glz_drawable_count++;
> return ret;
> }
>
> /* allocates new instance and adds it to instances in the given drawable.
> NOTE - the caller should set the glz_instance returned by the encoder by
> itself.*/
> -static GlzDrawableInstanceItem
> *red_display_add_glz_drawable_instance(RedGlzDrawable *glz_drawable)
> +static GlzDrawableInstanceItem *add_glz_drawable_instance(RedGlzDrawable
> *glz_drawable)
> {
> spice_assert(glz_drawable->instances_count <
> MAX_GLZ_DRAWABLE_INSTANCES);
> // NOTE: We assume the additions are performed consecutively, without
> removals in the middle
> GlzDrawableInstanceItem *ret = glz_drawable->instances_pool +
> glz_drawable->instances_count;
> glz_drawable->instances_count++;
>
> ring_item_init(&ret->free_link);
> ring_item_init(&ret->glz_link);
> ring_add(&glz_drawable->instances, &ret->glz_link);
> ret->context = NULL;
> ret->glz_drawable = glz_drawable;
>
> return ret;
> }
>
> #define MIN_GLZ_SIZE_FOR_ZLIB 100
>
> -static inline int red_glz_compress_image(DisplayChannelClient *dcc,
> +int dcc_compress_image_glz(DisplayChannelClient *dcc,
> SpiceImage *dest, SpiceBitmap *src,
> Drawable *drawable,
> compress_send_data_t* o_comp_data)
> {
> DisplayChannel *display_channel = DCC_TO_DC(dcc);
> #ifdef COMPRESS_STAT
> - stat_time_t start_time = stat_now(display_channel->zlib_glz_stat.clock);
> + stat_time_t start_time = stat_now(display_channel->glz_stat.clock);
> #endif
> spice_assert(bitmap_fmt_is_rgb(src->format));
> GlzData *glz_data = &dcc->glz_data;
> ZlibData *zlib_data;
> LzImageType type = MAP_BITMAP_FMT_TO_LZ_IMAGE_TYPE[src->format];
> RedGlzDrawable *glz_drawable;
> GlzDrawableInstanceItem *glz_drawable_instance;
> int glz_size;
> int zlib_size;
>
> glz_data->data.bufs_tail = compress_buf_new();
> glz_data->data.bufs_head = glz_data->data.bufs_tail;
> glz_data->data.dcc = dcc;
>
> - glz_drawable = red_display_get_glz_drawable(dcc, drawable);
> - glz_drawable_instance =
> red_display_add_glz_drawable_instance(glz_drawable);
> + glz_drawable = get_glz_drawable(dcc, drawable);
> + glz_drawable_instance = add_glz_drawable_instance(glz_drawable);
>
> glz_data->data.u.lines_data.chunks = src->data;
> glz_data->data.u.lines_data.stride = src->stride;
> glz_data->data.u.lines_data.next = 0;
> glz_data->data.u.lines_data.reverse = 0;
>
> glz_size = glz_encode(dcc->glz, type, src->x, src->y,
> (src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN), NULL,
> 0,
> src->stride, glz_data->data.bufs_head->buf.bytes,
> sizeof(glz_data->data.bufs_head->buf),
> @@ -442,21 +442,21 @@
> glz:
> dest->descriptor.type = SPICE_IMAGE_TYPE_GLZ_RGB;
> dest->u.lz_rgb.data_size = glz_size;
>
> o_comp_data->comp_buf = glz_data->data.bufs_head;
> o_comp_data->comp_buf_size = glz_size;
>
> return TRUE;
> }
>
> -static inline int red_lz_compress_image(DisplayChannelClient *dcc,
> +int dcc_compress_image_lz(DisplayChannelClient *dcc,
> SpiceImage *dest, SpiceBitmap *src,
> compress_send_data_t* o_comp_data,
> uint32_t group_id)
> {
> LzData *lz_data = &dcc->lz_data;
> LzContext *lz = dcc->lz;
> LzImageType type = MAP_BITMAP_FMT_TO_LZ_IMAGE_TYPE[src->format];
> int size; // size of the compressed data
>
> #ifdef COMPRESS_STAT
> stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->lz_stat.clock);
> @@ -502,48 +502,48 @@
> * (see fill_mask) */
> spice_assert(src->palette);
> dest->descriptor.type = SPICE_IMAGE_TYPE_LZ_PLT;
> dest->u.lz_plt.data_size = size;
> dest->u.lz_plt.flags = src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN;
> dest->u.lz_plt.palette = src->palette;
> dest->u.lz_plt.palette_id = src->palette->unique;
> o_comp_data->comp_buf = lz_data->data.bufs_head;
> o_comp_data->comp_buf_size = size;
>
> - fill_palette(dcc, dest->u.lz_plt.palette, &(dest->u.lz_plt.flags));
> + dcc_palette_cache_palette(dcc, dest->u.lz_plt.palette,
> &(dest->u.lz_plt.flags));
> o_comp_data->lzplt_palette = dest->u.lz_plt.palette;
> }
>
> stat_compress_add(&DCC_TO_DC(dcc)->lz_stat, start_time, src->stride *
> src->y,
> o_comp_data->comp_buf_size);
> return TRUE;
> }
>
> -static int red_jpeg_compress_image(DisplayChannelClient *dcc, SpiceImage
> *dest,
> +int dcc_compress_image_jpeg(DisplayChannelClient *dcc, SpiceImage *dest,
> SpiceBitmap *src, compress_send_data_t*
> o_comp_data,
> uint32_t group_id)
> {
> JpegData *jpeg_data = &dcc->jpeg_data;
> LzData *lz_data = &dcc->lz_data;
> JpegEncoderContext *jpeg = dcc->jpeg;
> LzContext *lz = dcc->lz;
> volatile JpegEncoderImageType jpeg_in_type;
> int jpeg_size = 0;
> volatile int has_alpha = FALSE;
> int alpha_lz_size = 0;
> int comp_head_filled;
> int comp_head_left;
> int stride;
> uint8_t *lz_out_start_byte;
>
> #ifdef COMPRESS_STAT
> - stat_time_t start_time =
> stat_now(DCC_TO_DC(dcc)->jpeg_alpha_stat.clock);
> + stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->jpeg_stat.clock);
> #endif
> switch (src->format) {
> case SPICE_BITMAP_FMT_16BIT:
> jpeg_in_type = JPEG_IMAGE_TYPE_RGB16;
> break;
> case SPICE_BITMAP_FMT_24BIT:
> jpeg_in_type = JPEG_IMAGE_TYPE_BGR24;
> break;
> case SPICE_BITMAP_FMT_32BIT:
> jpeg_in_type = JPEG_IMAGE_TYPE_BGRX32;
> @@ -643,30 +643,31 @@
>
> o_comp_data->comp_buf = jpeg_data->data.bufs_head;
> o_comp_data->comp_buf_size = jpeg_size + alpha_lz_size;
> o_comp_data->is_lossy = TRUE;
> stat_compress_add(&DCC_TO_DC(dcc)->jpeg_alpha_stat, start_time,
> src->stride * src->y,
> o_comp_data->comp_buf_size);
> return TRUE;
> }
>
> #ifdef USE_LZ4
> -static int red_lz4_compress_image(DisplayChannelClient *dcc, SpiceImage
> *dest,
> +int dcc_compress_image_lz4(DisplayChannelClient *dcc, SpiceImage *dest,
> SpiceBitmap *src, compress_send_data_t*
> o_comp_data,
> uint32_t group_id)
> {
> + DisplayChannel *display_channel = DCC_TO_DC(dcc);
> Lz4Data *lz4_data = &dcc->lz4_data;
> Lz4EncoderContext *lz4 = dcc->lz4;
> int lz4_size = 0;
>
> #ifdef COMPRESS_STAT
> - stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->lz4_stat.clock);
> + stat_time_t start_time = stat_now(display_channel->lz4_stat.clock);
> #endif
>
> lz4_data->data.bufs_tail = compress_buf_new();
> lz4_data->data.bufs_head = lz4_data->data.bufs_tail;
>
> if (!lz4_data->data.bufs_head) {
> spice_warning("failed to allocate compress buffer");
> return FALSE;
> }
>
> @@ -683,44 +684,43 @@
> }
>
> if (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE) {
> spice_chunks_linearize(src->data);
> }
>
> lz4_data->data.u.lines_data.chunks = src->data;
> lz4_data->data.u.lines_data.stride = src->stride;
> lz4_data->data.u.lines_data.next = 0;
> lz4_data->data.u.lines_data.reverse = 0;
> - /* fixme remove? lz4_data->usr.more_lines = lz4_usr_more_lines; */
>
> lz4_size = lz4_encode(lz4, src->y, src->stride,
> lz4_data->data.bufs_head->buf.bytes,
> sizeof(lz4_data->data.bufs_head->buf),
> src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN,
> src->format);
>
> // the compressed buffer is bigger than the original data
> if (lz4_size > (src->y * src->stride)) {
> longjmp(lz4_data->data.jmp_env, 1);
> }
>
> dest->descriptor.type = SPICE_IMAGE_TYPE_LZ4;
> dest->u.lz4.data_size = lz4_size;
>
> o_comp_data->comp_buf = lz4_data->data.bufs_head;
> o_comp_data->comp_buf_size = lz4_size;
>
> - stat_compress_add(&DCC_TO_DC(dcc)->lz4_stat, start_time, src->stride *
> src->y,
> + stat_compress_add(&display_channel->lz4_stat, start_time, src->stride *
> src->y,
> o_comp_data->comp_buf_size);
> return TRUE;
> }
> #endif
>
> -static inline int red_quic_compress_image(DisplayChannelClient *dcc,
> SpiceImage *dest,
> +int dcc_compress_image_quic(DisplayChannelClient *dcc, SpiceImage *dest,
> SpiceBitmap *src,
> compress_send_data_t*
> o_comp_data,
> uint32_t group_id)
> {
> QuicData *quic_data = &dcc->quic_data;
> QuicContext *quic = dcc->quic;
> volatile QuicImageType type;
> int size, stride;
>
> #ifdef COMPRESS_STAT
> stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->quic_stat.clock);
> @@ -786,21 +786,21 @@
> o_comp_data->comp_buf = quic_data->data.bufs_head;
> o_comp_data->comp_buf_size = size << 2;
>
> stat_compress_add(&DCC_TO_DC(dcc)->quic_stat, start_time, src->stride *
> src->y,
> o_comp_data->comp_buf_size);
> return TRUE;
> }
>
> #define MIN_SIZE_TO_COMPRESS 54
> #define MIN_DIMENSION_TO_QUIC 3
> -static inline int red_compress_image(DisplayChannelClient *dcc,
> +int dcc_compress_image(DisplayChannelClient *dcc,
> SpiceImage *dest, SpiceBitmap *src,
> Drawable *drawable,
> int can_lossy,
> compress_send_data_t* o_comp_data)
> {
> DisplayChannel *display_channel = DCC_TO_DC(dcc);
> SpiceImageCompression image_compression = dcc->image_compression;
> int quic_compress = FALSE;
>
> if ((image_compression == SPICE_IMAGE_COMPRESSION_OFF) ||
> ((src->y * src->stride) < MIN_SIZE_TO_COMPRESS)) { // TODO: change
> the size cond
> @@ -847,25 +847,25 @@
> if (quic_compress) {
> #ifdef COMPRESS_DEBUG
> spice_info("QUIC compress");
> #endif
> // if bitmaps is picture-like, compress it using jpeg
> if (can_lossy && display_channel->enable_jpeg &&
> ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) ||
> (image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ))) {
> // if we use lz for alpha, the stride can't be extra
> if (src->format != SPICE_BITMAP_FMT_RGBA ||
> !bitmap_has_extra_stride(src)) {
> - return red_jpeg_compress_image(dcc, dest,
> + return dcc_compress_image_jpeg(dcc, dest,
> src, o_comp_data,
> drawable->group_id);
> }
> }
> - return red_quic_compress_image(dcc, dest,
> + return dcc_compress_image_quic(dcc, dest,
> src, o_comp_data,
> drawable->group_id);
> } else {
> int glz;
> int ret;
> if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ) ||
> (image_compression == SPICE_IMAGE_COMPRESSION_GLZ)) {
> glz = bitmap_fmt_has_graduality(src->format) && (
> (src->x * src->y) < glz_enc_dictionary_get_size(
> dcc->glz_dict->dict));
> } else if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) ||
> @@ -874,77 +874,76 @@
> glz = FALSE;
> } else {
> spice_error("invalid image compression type %u",
> image_compression);
> return FALSE;
> }
>
> if (glz) {
> /* using the global dictionary only if it is not frozen */
> pthread_rwlock_rdlock(&dcc->glz_dict->encode_lock);
> if (!dcc->glz_dict->migrate_freeze) {
> - ret = red_glz_compress_image(dcc,
> + ret = dcc_compress_image_glz(dcc,
> dest, src,
> drawable, o_comp_data);
> } else {
> glz = FALSE;
> }
> pthread_rwlock_unlock(&dcc->glz_dict->encode_lock);
> }
>
> if (!glz) {
> #ifdef USE_LZ4
> if (image_compression == SPICE_IMAGE_COMPRESSION_LZ4 &&
> bitmap_fmt_is_rgb(src->format) &&
> red_channel_client_test_remote_cap(&dcc->common.base,
> SPICE_DISPLAY_CAP_LZ4_COMPRESSION)) {
> - ret = red_lz4_compress_image(dcc, dest, src, o_comp_data,
> + ret = dcc_compress_image_lz4(dcc, dest, src, o_comp_data,
> drawable->group_id);
> } else
> #endif
> - ret = red_lz_compress_image(dcc, dest, src, o_comp_data,
> + ret = dcc_compress_image_lz(dcc, dest, src, o_comp_data,
> drawable->group_id);
> #ifdef COMPRESS_DEBUG
> spice_info("LZ LOCAL compress");
> #endif
> }
> #ifdef COMPRESS_DEBUG
> else {
> spice_info("LZ global compress fmt=%d", src->format);
> }
> #endif
> return ret;
> }
> }
>
> #define CLIENT_PALETTE_CACHE
> #include "cache_item.tmpl.c"
> #undef CLIENT_PALETTE_CACHE
>
> -static inline void fill_palette(DisplayChannelClient *dcc,
> - SpicePalette *palette,
> +void dcc_palette_cache_palette(DisplayChannelClient *dcc, SpicePalette
> *palette,
> uint8_t *flags)
> {
> if (palette == NULL) {
> return;
> }
> if (palette->unique) {
> if (red_palette_cache_find(dcc, palette->unique)) {
> *flags |= SPICE_BITMAP_FLAGS_PAL_FROM_CACHE;
> return;
> }
> if (red_palette_cache_add(dcc, palette->unique, 1)) {
> *flags |= SPICE_BITMAP_FLAGS_PAL_CACHE_ME;
> }
> }
> }
>
> -static void red_reset_palette_cache(DisplayChannelClient *dcc)
> +void dcc_palette_cache_reset(DisplayChannelClient *dcc)
> {
> red_palette_cache_reset(dcc, CLIENT_PALETTE_CACHE_SIZE);
> }
> /* -*- 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
> @@ -1043,20 +1042,22 @@
> Ring glz_drawables_inst_to_free; // list of instances to
> be freed
> pthread_mutex_t glz_drawables_inst_to_free_lock;
>
> uint8_t surface_client_created[NUM_SURFACES];
> QRegion surface_client_lossy_region[NUM_SURFACES];
>
> StreamAgent stream_agents[NUM_STREAMS];
> int use_mjpeg_encoder_rate_control;
> uint32_t streams_max_latency;
> uint64_t streams_max_bit_rate;
> +
> + uint32_t glz_drawable_count;
> };
>
> #define DCC_TO_WORKER(dcc) \
> (SPICE_CONTAINEROF((dcc)->common.base.channel, CommonChannel,
> base)->worker)
> #define DCC_TO_DC(dcc) \
> SPICE_CONTAINEROF((dcc)->common.base.channel, DisplayChannel,
> common.base)
> #define RCC_TO_DCC(rcc) SPICE_CONTAINEROF((rcc), DisplayChannelClient,
> common.base)
>
> typedef struct SurfaceCreateItem {
> SpiceMsgSurfaceCreate surface_create;
> @@ -1099,27 +1100,51 @@
> Stream
> *stream);
> void dcc_create_surface
> (DisplayChannelClient *dcc,
> int
> surface_id);
> void dcc_push_surface_image
> (DisplayChannelClient *dcc,
> int
> surface_id);
> ImageItem * dcc_add_surface_area_image
> (DisplayChannelClient *dcc,
> int
> surface_id,
> SpiceRect
> *area,
> PipeItem
> *pos,
> int
> can_lossy);
> +void dcc_palette_cache_reset
> (DisplayChannelClient *dcc);
> +void dcc_palette_cache_palette
> (DisplayChannelClient *dcc,
> +
> SpicePalette
> *palette,
> +
> uint8_t
> *flags);
> +
> typedef struct compress_send_data_t {
> void* comp_buf;
> uint32_t comp_buf_size;
> SpicePalette *lzplt_palette;
> int is_lossy;
> } compress_send_data_t;
>
> +int dcc_compress_image
> (DisplayChannelClient *dcc,
> +
> SpiceImage
> *dest, SpiceBitmap *src, Drawable *drawable,
> + int
> can_lossy,
> +
> compress_send_data_t*
> o_comp_data);
> +int dcc_compress_image_glz
> (DisplayChannelClient *dcc,
> +
> SpiceImage
> *dest, SpiceBitmap *src, Drawable *drawable,
> +
> compress_send_data_t*
> o_comp_data);
> +int dcc_compress_image_lz
> (DisplayChannelClient *dcc,
> +
> SpiceImage
> *dest, SpiceBitmap *src,
> +
> compress_send_data_t*
> o_comp_data, uint32_t group_id);
> +int dcc_compress_image_jpeg
> (DisplayChannelClient *dcc, SpiceImage *dest,
> +
> SpiceBitmap
> *src, compress_send_data_t* o_comp_data,
> +
> uint32_t
> group_id);
> +int dcc_compress_image_quic
> (DisplayChannelClient *dcc, SpiceImage *dest,
> +
> SpiceBitmap
> *src, compress_send_data_t* o_comp_data,
> +
> uint32_t
> group_id);
> +int dcc_compress_image_lz4
> (DisplayChannelClient *dcc, SpiceImage *dest,
> +
> SpiceBitmap
> *src, compress_send_data_t* o_comp_data,
> +
> uint32_t
> group_id);
>
> #endif /* DCC_H_ */
> /* -*- 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.
> @@ -1568,21 +1593,21 @@
> SpiceRop3 rop3;
> SpiceStroke stroke;
> SpiceText text;
> SpiceBlackness blackness;
> SpiceInvers invers;
> SpiceWhiteness whiteness;
> SpiceComposite composite;
> } u;
> } RedDrawable;
>
> -static RedDrawable *red_drawable_ref(RedDrawable *drawable)
> +static inline RedDrawable *red_drawable_ref(RedDrawable *drawable)
> {
> drawable->refs++;
> return drawable;
> }
>
> typedef struct RedUpdateCmd {
> QXLReleaseInfo *release_info;
> SpiceRect area;
> uint32_t update_id;
> uint32_t surface_id;
> @@ -1729,24 +1754,20 @@
> #include "tree.h"
>
> //#define COMPRESS_STAT
> //#define DUMP_BITMAP
> //#define COMPRESS_DEBUG
>
> #define CMD_RING_POLL_TIMEOUT 10 //milli
> #define CMD_RING_POLL_RETRIES 200
>
> #define DISPLAY_CLIENT_SHORT_TIMEOUT 15000000000ULL //nano
> -#define DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT 10000000000ULL //nano, 10 sec
> -#define DISPLAY_CLIENT_RETRY_INTERVAL 10000 //micro
> -
> -#define DISPLAY_FREE_LIST_DEFAULT_SIZE 128
>
Apparently these lines disappeared... must be also defined somewhere else.
(copy of diff at http://pastebin.com/pPK2dizq).
Frediano
More information about the Spice-devel
mailing list