diff options
-rw-r--r-- | server/Makefile.am | 6 | ||||
-rw-r--r-- | server/glz_encode_match_tmpl.c | 154 | ||||
-rw-r--r-- | server/glz_encode_tmpl.c | 574 | ||||
-rw-r--r-- | server/glz_encoder.c | 310 | ||||
-rw-r--r-- | server/glz_encoder.h | 55 | ||||
-rw-r--r-- | server/glz_encoder_config.h | 61 | ||||
-rw-r--r-- | server/glz_encoder_dictionary.c | 633 | ||||
-rw-r--r-- | server/glz_encoder_dictionary.h | 69 | ||||
-rw-r--r-- | server/glz_encoder_dictionary_protected.h | 186 | ||||
-rw-r--r-- | server/migration_protocol.h | 2 | ||||
-rw-r--r-- | server/red_memslots.c | 12 | ||||
-rw-r--r-- | server/red_worker.c | 4 | ||||
m--------- | spice-common | 0 |
13 files changed, 15 insertions, 2051 deletions
diff --git a/server/Makefile.am b/server/Makefile.am index 34219c80..b7175584 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -50,12 +50,6 @@ libspice_server_la_SOURCES = \ char_device.c \ char_device.h \ demarshallers.h \ - glz_encoder.c \ - glz_encoder.h \ - glz_encoder_config.h \ - glz_encoder_dictionary.c \ - glz_encoder_dictionary.h \ - glz_encoder_dictionary_protected.h \ inputs_channel.c \ inputs_channel.h \ jpeg_encoder.c \ diff --git a/server/glz_encode_match_tmpl.c b/server/glz_encode_match_tmpl.c deleted file mode 100644 index b793e7f0..00000000 --- a/server/glz_encode_match_tmpl.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - Copyright (C) 2009 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 - -#define SHORT_PIX_IMAGE_DIST_LEVEL_1 64 //(1 << 6) -#define SHORT_PIX_IMAGE_DIST_LEVEL_2 16384 // (1 << 14) -#define SHORT_PIX_IMAGE_DIST_LEVEL_3 4194304 // (1 << 22) -#define FAR_PIX_IMAGE_DIST_LEVEL_1 256 // (1 << 8) -#define FAR_PIX_IMAGE_DIST_LEVEL_2 65536 // (1 << 16) -#define FAR_PIX_IMAGE_DIST_LEVEL_3 16777216 // (1 << 24) - -/* if image_distance = 0, pixel_distance is the distance between the matching pixels. - Otherwise, it is the offset from the beginning of the referred image */ -#if defined(GLZ_ENCODE_MATCH) /* actually performing the encoding */ -static INLINE void encode_match(Encoder *encoder, uint32_t image_distance, - size_t pixel_distance, size_t len) -#elif defined(GLZ_ENCODE_SIZE) /* compute the size of the encoding except for the match length*/ -static INLINE int get_encode_ref_size(uint32_t image_distance, size_t pixel_distance) -#endif -{ -#if defined(GLZ_ENCODE_SIZE) - int encode_size; -#endif - -#if defined(GLZ_ENCODE_MATCH) - /* encoding the match length + Long/Short dist bit + 12 LSB pixels of pixel_distance*/ - if (len < 7) { - if (pixel_distance < MAX_PIXEL_SHORT_DISTANCE) { - encode(encoder, (uint8_t)((len << 5) + (pixel_distance & 0x0f))); - } else { - encode(encoder, (uint8_t)((len << 5) + 16 + (pixel_distance & 0x0f))); - } - encode(encoder, (uint8_t)((pixel_distance >> 4) & 255)); - } else { - if (pixel_distance < MAX_PIXEL_SHORT_DISTANCE) { - encode(encoder, (uint8_t)((7 << 5) + (pixel_distance & 0x0f))); - } else { - encode(encoder, (uint8_t)((7 << 5) + 16 + (pixel_distance & 0x0f))); - } - for (len -= 7; len >= 255; len -= 255) { - encode(encoder, 255); - } - encode(encoder, (uint8_t)len); - encode(encoder, (uint8_t)((pixel_distance >> 4) & 255)); - } -#endif - - - /* encoding the rest of the pixel distance and the image_dist and its 2 control bits */ - - /* The first 2 MSB bits indicate how many more bytes should be read for image dist */ - if (pixel_distance < MAX_PIXEL_SHORT_DISTANCE) { - if (image_distance < SHORT_PIX_IMAGE_DIST_LEVEL_1) { -#if defined(GLZ_ENCODE_MATCH) - encode(encoder, (uint8_t)(image_distance & 0x3f)); -#elif defined(GLZ_ENCODE_SIZE) - encode_size = 3; -#endif - } else if (image_distance < SHORT_PIX_IMAGE_DIST_LEVEL_2) { -#if defined(GLZ_ENCODE_MATCH) - encode(encoder, (uint8_t)((1 << 6) + (image_distance & 0x3f))); - encode(encoder, (uint8_t)((image_distance >> 6) & 255)); -#elif defined(GLZ_ENCODE_SIZE) - encode_size = 4; -#endif - } else if (image_distance < SHORT_PIX_IMAGE_DIST_LEVEL_3) { -#if defined(GLZ_ENCODE_MATCH) - encode(encoder, (uint8_t)((1 << 7) + (image_distance & 0x3f))); - encode(encoder, (uint8_t)((image_distance >> 6) & 255)); - encode(encoder, (uint8_t)((image_distance >> 14) & 255)); -#elif defined(GLZ_ENCODE_SIZE) - encode_size = 5; -#endif - } else { -#if defined(GLZ_ENCODE_MATCH) - encode(encoder, (uint8_t)((1 << 7) + (1 << 6) + (image_distance & 0x3f))); - encode(encoder, (uint8_t)((image_distance >> 6) & 255)); - encode(encoder, (uint8_t)((image_distance >> 14) & 255)); - encode(encoder, (uint8_t)((image_distance >> 22) & 255)); -#elif defined(GLZ_ENCODE_SIZE) - encode_size = 6; -#endif - } - } else { - /* the third MSB bit indicates if the pixel_distance is medium/long*/ - uint8_t long_dist_control = (pixel_distance < MAX_PIXEL_MEDIUM_DISTANCE) ? 0 : 32; - if (image_distance == 0) { -#if defined(GLZ_ENCODE_MATCH) - encode(encoder, (uint8_t)(long_dist_control + ((pixel_distance >> 12) & 31))); -#elif defined(GLZ_ENCODE_SIZE) - encode_size = 3; -#endif - } else if (image_distance < FAR_PIX_IMAGE_DIST_LEVEL_1) { -#if defined(GLZ_ENCODE_MATCH) - encode(encoder, - (uint8_t)(long_dist_control + (1 << 6) + ((pixel_distance >> 12) & 31))); - encode(encoder, (uint8_t)(image_distance & 255)); -#elif defined(GLZ_ENCODE_SIZE) - encode_size = 4; -#endif - } else if (image_distance < FAR_PIX_IMAGE_DIST_LEVEL_2) { -#if defined(GLZ_ENCODE_MATCH) - encode(encoder, - (uint8_t)(long_dist_control + (1 << 7) + ((pixel_distance >> 12) & 31))); - encode(encoder, (uint8_t)(image_distance & 255)); - encode(encoder, (uint8_t)((image_distance >> 8) & 255)); -#elif defined(GLZ_ENCODE_SIZE) - encode_size = 5; -#endif - } else { -#if defined(GLZ_ENCODE_MATCH) - encode(encoder, - (uint8_t)(long_dist_control + (1 << 7) + (1 << 6) + - ((pixel_distance >> 12) & 31))); - encode(encoder, (uint8_t)(image_distance & 255)); - encode(encoder, (uint8_t)((image_distance >> 8) & 255)); - encode(encoder, (uint8_t)((image_distance >> 16) & 255)); -#elif defined(GLZ_ENCODE_SIZE) - encode_size = 6; -#endif - } - - if (long_dist_control) { -#if defined(GLZ_ENCODE_MATCH) - encode(encoder, (uint8_t)((pixel_distance >> 17) & 255)); -#elif defined(GLZ_ENCODE_SIZE) - encode_size++; -#endif - } - } - -#if defined(GLZ_ENCODE_SIZE) - return encode_size; -#endif -} - -#undef GLZ_ENCODE_SIZE -#undef GLZ_ENCODE_MATCH diff --git a/server/glz_encode_tmpl.c b/server/glz_encode_tmpl.c deleted file mode 100644 index 1402f953..00000000 --- a/server/glz_encode_tmpl.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - Copyright (C) 2009 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 - -#define DJB2_START 5381; -#define DJB2_HASH(hash, c) (hash = ((hash << 5) + hash) ^ (c)) //|{hash = ((hash << 5) + hash) + c;} - -/* - For each pixel type the following macros are defined: - PIXEL : input type - FNAME(name) - ENCODE_PIXEL(encoder, pixel) : writing a pixel to the compressed buffer (byte by byte) - SAME_PIXEL(pix1, pix2) : comparing two pixels - HASH_FUNC(value, pix_ptr) : hash func of 3 consecutive pixels -*/ - -#ifdef LZ_PLT -#define PIXEL one_byte_pixel_t -#define FNAME(name) glz_plt_##name -#define ENCODE_PIXEL(e, pix) encode(e, (pix).a) // gets the pixel and write only the needed bytes - // from the pixel -#define SAME_PIXEL(pix1, pix2) ((pix1).a == (pix2).a) -#define MIN_REF_ENCODE_SIZE 4 -#define MAX_REF_ENCODE_SIZE 7 -#define HASH_FUNC(v, p) { \ - v = DJB2_START; \ - DJB2_HASH(v, p[0].a); \ - DJB2_HASH(v, p[1].a); \ - DJB2_HASH(v, p[2].a); \ - v &= HASH_MASK; \ - } -#endif - -#ifdef LZ_RGB_ALPHA -//#undef LZ_RGB_ALPHA -#define PIXEL rgb32_pixel_t -#define FNAME(name) glz_rgb_alpha_##name -#define ENCODE_PIXEL(e, pix) {encode(e, (pix).pad);} -#define SAME_PIXEL(pix1, pix2) ((pix1).pad == (pix2).pad) -#define MIN_REF_ENCODE_SIZE 4 -#define MAX_REF_ENCODE_SIZE 7 -#define HASH_FUNC(v, p) { \ - v = DJB2_START; \ - DJB2_HASH(v, p[0].pad); \ - DJB2_HASH(v, p[1].pad); \ - DJB2_HASH(v, p[2].pad); \ - v &= HASH_MASK; \ - } -#endif - - -#ifdef LZ_RGB16 -#define PIXEL rgb16_pixel_t -#define FNAME(name) glz_rgb16_##name -#define GET_r(pix) (((pix) >> 10) & 0x1f) -#define GET_g(pix) (((pix) >> 5) & 0x1f) -#define GET_b(pix) ((pix) & 0x1f) -#define ENCODE_PIXEL(e, pix) {encode(e, (pix) >> 8); encode(e, (pix) & 0xff);} -#define MIN_REF_ENCODE_SIZE 2 -#define MAX_REF_ENCODE_SIZE 3 -#define HASH_FUNC(v, p) { \ - v = DJB2_START; \ - DJB2_HASH(v, p[0] & (0x00ff)); \ - DJB2_HASH(v, (p[0] >> 8) & (0x007f)); \ - DJB2_HASH(v, p[1] & (0x00ff)); \ - DJB2_HASH(v, (p[1] >> 8) & (0x007f)); \ - DJB2_HASH(v, p[2] & (0x00ff)); \ - DJB2_HASH(v, (p[2] >> 8) & (0x007f)); \ - v &= HASH_MASK; \ -} -#endif - -#ifdef LZ_RGB24 -#define PIXEL rgb24_pixel_t -#define FNAME(name) glz_rgb24_##name -#define ENCODE_PIXEL(e, pix) {encode(e, (pix).b); encode(e, (pix).g); encode(e, (pix).r);} -#define MIN_REF_ENCODE_SIZE 2 -#define MAX_REF_ENCODE_SIZE 2 -#endif - -#ifdef LZ_RGB32 -#define PIXEL rgb32_pixel_t -#define FNAME(name) glz_rgb32_##name -#define ENCODE_PIXEL(e, pix) {encode(e, (pix).b); encode(e, (pix).g); encode(e, (pix).r);} -#define MIN_REF_ENCODE_SIZE 2 -#define MAX_REF_ENCODE_SIZE 2 -#endif - - -#if defined(LZ_RGB24) || defined(LZ_RGB32) -#define GET_r(pix) ((pix).r) -#define GET_g(pix) ((pix).g) -#define GET_b(pix) ((pix).b) -#define HASH_FUNC(v, p) { \ - v = DJB2_START; \ - DJB2_HASH(v, p[0].r); \ - DJB2_HASH(v, p[0].g); \ - DJB2_HASH(v, p[0].b); \ - DJB2_HASH(v, p[1].r); \ - DJB2_HASH(v, p[1].g); \ - DJB2_HASH(v, p[1].b); \ - DJB2_HASH(v, p[2].r); \ - DJB2_HASH(v, p[2].g); \ - DJB2_HASH(v, p[2].b); \ - v &= HASH_MASK; \ - } -#endif - -#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32) -#define SAME_PIXEL(p1, p2) (GET_r(p1) == GET_r(p2) && GET_g(p1) == GET_g(p2) && \ - GET_b(p1) == GET_b(p2)) - -#endif - -#ifndef LZ_PLT -#define PIXEL_ID(pix_ptr, seg_ptr) \ - ((pix_ptr) - ((PIXEL *)(seg_ptr)->lines) + (seg_ptr)->pixels_so_far) -#define PIXEL_DIST(src_pix_ptr, src_seg_ptr, ref_pix_ptr, ref_seg_ptr) \ - (PIXEL_ID(src_pix_ptr,src_seg_ptr) - PIXEL_ID(ref_pix_ptr, ref_seg_ptr)) -#else -#define PIXEL_ID(pix_ptr, seg_ptr, pix_per_byte) \ - (((pix_ptr) - ((PIXEL *)(seg_ptr)->lines)) * pix_per_byte + (seg_ptr)->pixels_so_far) -#define PIXEL_DIST(src_pix_ptr, src_seg_ptr, ref_pix_ptr, ref_seg_ptr, pix_per_byte) \ - ((PIXEL_ID(src_pix_ptr,src_seg_ptr, pix_per_byte) - \ - PIXEL_ID(ref_pix_ptr, ref_seg_ptr, pix_per_byte)) / pix_per_byte) -#endif - -/* returns the length of the match. 0 if no match. - if image_distance = 0, pixel_distance is the distance between the matching pixels. - Otherwise, it is the offset from the beginning of the referred image */ -static INLINE size_t FNAME(do_match)(SharedDictionary *dict, - WindowImageSegment *ref_seg, const PIXEL *ref, - const PIXEL *ref_limit, - WindowImageSegment *ip_seg, const PIXEL *ip, - const PIXEL *ip_limit, -#ifdef LZ_PLT - int pix_per_byte, -#endif - size_t *o_image_dist, size_t *o_pix_distance) -{ - int encode_size; - const PIXEL *tmp_ip = ip; - const PIXEL *tmp_ref = ref; - - if (ref > (ref_limit - MIN_REF_ENCODE_SIZE)) { - return 0; // in case the hash entry is not relevant - } - - - /* min match length == MIN_REF_ENCODE_SIZE (depends on pixel type) */ - - if (!SAME_PIXEL(*tmp_ref, *tmp_ip)) { - return 0; - } else { - tmp_ref++; - tmp_ip++; - } - - - if (!SAME_PIXEL(*tmp_ref, *tmp_ip)) { - return 0; - } else { - tmp_ref++; - tmp_ip++; - } - -#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) - if (!SAME_PIXEL(*tmp_ref, *tmp_ip)) { - return 0; - } else { - tmp_ref++; - tmp_ip++; - } - - - if (!SAME_PIXEL(*tmp_ref, *tmp_ip)) { - return 0; - } else { - tmp_ref++; - tmp_ip++; - } - -#endif - - - *o_image_dist = ip_seg->image->id - ref_seg->image->id; - - if (!(*o_image_dist)) { // the ref is inside the same image - encode distance -#ifndef LZ_PLT - *o_pix_distance = PIXEL_DIST(ip, ip_seg, ref, ref_seg); -#else - // in bytes - *o_pix_distance = PIXEL_DIST(ip, ip_seg, ref, ref_seg, pix_per_byte); -#endif - } else { // the ref is at different image - encode offset from the image start -#ifndef LZ_PLT - *o_pix_distance = PIXEL_DIST(ref, ref_seg, - (PIXEL *)(dict->window.segs[ref_seg->image->first_seg].lines), - &dict->window.segs[ref_seg->image->first_seg] - ); -#else - // in bytes - *o_pix_distance = PIXEL_DIST(ref, ref_seg, - (PIXEL *)(dict->window.segs[ref_seg->image->first_seg].lines), - &dict->window.segs[ref_seg->image->first_seg], - pix_per_byte); -#endif - } - - if ((*o_pix_distance == 0) || (*o_pix_distance >= MAX_PIXEL_LONG_DISTANCE) || - (*o_image_dist > MAX_IMAGE_DIST)) { - return 0; - } - - - /* continue the match*/ - while ((tmp_ip < ip_limit) && (tmp_ref < ref_limit)) { - if (!SAME_PIXEL(*tmp_ref, *tmp_ip)) { - break; - } else { - tmp_ref++; - tmp_ip++; - } - } - - - if ((tmp_ip - ip) > MAX_REF_ENCODE_SIZE) { - return (tmp_ip - ip); - } - - encode_size = get_encode_ref_size(*o_image_dist, *o_pix_distance); - - // min number of identical pixels for a match -#if defined(LZ_RGB16) - encode_size /= 2; -#elif defined(LZ_RGB24) || defined(LZ_RGB32) - encode_size /= 3; -#endif - - encode_size++; // the minimum match - // match len is smaller than the encoding - not worth encoding - if ((tmp_ip - ip) < encode_size) { - return 0; - } - return (tmp_ip - ip); -} - -/* compresses one segment starting from 'from'. - In order to encode a match, we use pixels resolution when we encode RGB image, - and bytes count when we encode PLT. -*/ -static void FNAME(compress_seg)(Encoder *encoder, uint32_t seg_idx, PIXEL *from, int copied) -{ - WindowImageSegment *seg = &encoder->dict->window.segs[seg_idx]; - const PIXEL *ip = from; - const PIXEL *ip_bound = (PIXEL *)(seg->lines_end) - BOUND_OFFSET; - const PIXEL *ip_limit = (PIXEL *)(seg->lines_end) - LIMIT_OFFSET; - int hval; - int copy = copied; -#ifdef LZ_PLT - int pix_per_byte = PLT_PIXELS_PER_BYTE[encoder->cur_image.type]; -#endif - -#ifdef DEBUG_ENCODE - int n_encoded = 0; -#endif - - if (copy == 0) { - encode_copy_count(encoder, MAX_COPY - 1); - } - - - while (LZ_EXPECT_CONDITIONAL(ip < ip_limit)) { - const PIXEL *ref; - const PIXEL *ref_limit; - WindowImageSegment *ref_seg; - uint32_t ref_seg_idx; - size_t pix_dist; - size_t image_dist; - /* minimum match length */ - size_t len = 0; - - /* comparison starting-point */ - const PIXEL *anchor = ip; -#ifdef CHAINED_HASH - int hash_id = 0; - size_t best_len = 0; - size_t best_pix_dist = 0; - size_t best_image_dist = 0; -#endif - - /* check for a run */ - - if (LZ_EXPECT_CONDITIONAL(ip > (PIXEL *)(seg->lines))) { - if (SAME_PIXEL(ip[-1], ip[0]) && SAME_PIXEL(ip[0], ip[1]) && SAME_PIXEL(ip[1], ip[2])) { - PIXEL x; - pix_dist = 1; - image_dist = 0; - - ip += 3; - ref = anchor + 2; - ref_limit = (PIXEL *)(seg->lines_end); - len = 3; - - x = *ref; - - while (ip < ip_bound) { // TODO: maybe separate a run from the same seg or from - // different ones in order to spare ref < ref_limit - if (!SAME_PIXEL(*ip, x)) { - ip++; - break; - } else { - ip++; - len++; - } - } - - goto match; - } // END RLE MATCH - } - - /* find potential match */ - HASH_FUNC(hval, ip); - -#ifdef CHAINED_HASH - for (hash_id = 0; hash_id < HASH_CHAIN_SIZE; hash_id++) { - ref_seg_idx = encoder->dict->htab[hval][hash_id].image_seg_idx; -#else - ref_seg_idx = encoder->dict->htab[hval].image_seg_idx; -#endif - ref_seg = encoder->dict->window.segs + ref_seg_idx; - if (REF_SEG_IS_VALID(encoder->dict, encoder->id, - ref_seg, seg)) { -#ifdef CHAINED_HASH - ref = ((PIXEL *)ref_seg->lines) + encoder->dict->htab[hval][hash_id].ref_pix_idx; -#else - ref = ((PIXEL *)ref_seg->lines) + encoder->dict->htab[hval].ref_pix_idx; -#endif - ref_limit = (PIXEL *)ref_seg->lines_end; - - len = FNAME(do_match)(encoder->dict, ref_seg, ref, ref_limit, seg, ip, ip_bound, -#ifdef LZ_PLT - pix_per_byte, -#endif - &image_dist, &pix_dist); - -#ifdef CHAINED_HASH - // TODO. not compare len but rather len - encode_size - if (len > best_len) { - best_len = len; - best_pix_dist = pix_dist; - best_image_dist = image_dist; - } -#endif - } - -#ifdef CHAINED_HASH - } // end chain loop - len = best_len; - pix_dist = best_pix_dist; - image_dist = best_image_dist; -#endif - - /* update hash table */ - UPDATE_HASH(encoder->dict, hval, seg_idx, anchor - ((PIXEL *)seg->lines)); - - if (!len) { - goto literal; - } - -match: // RLE or dictionary (both are encoded by distance from ref (-1) and length) -#ifdef DEBUG_ENCODE - printf(", match(%d, %d, %d)", image_dist, pix_dist, len); - n_encoded += len; -#endif - - /* distance is biased */ - if (!image_dist) { - pix_dist--; - } - - /* if we have copied something, adjust the copy count */ - if (copy) { - /* copy is biased, '0' means 1 byte copy */ - update_copy_count(encoder, copy - 1); - } else { - /* back, to overwrite the copy count */ - compress_output_prev(encoder); - } - - /* reset literal counter */ - copy = 0; - - /* length is biased, '1' means a match of 3 pixels for PLT and alpha*/ - /* for RGB 16 1 means 2 */ - /* for RGB24/32 1 means 1...*/ - ip = anchor + len - 2; - -#if defined(LZ_RGB16) - len--; -#elif defined(LZ_PLT) || defined(LZ_RGB_ALPHA) - len -= 2; -#endif - GLZ_ASSERT(encoder->usr, len > 0); - encode_match(encoder, image_dist, pix_dist, len); - - /* update the hash at match boundary */ -#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32) - if (ip > anchor) { -#endif - HASH_FUNC(hval, ip); - UPDATE_HASH(encoder->dict, hval, seg_idx, ip - ((PIXEL *)seg->lines)); - ip++; -#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32) - } else {ip++; - } -#endif -#if defined(LZ_RGB24) || defined(LZ_RGB32) - if (ip > anchor) { -#endif - HASH_FUNC(hval, ip); - UPDATE_HASH(encoder->dict, hval, seg_idx, ip - ((PIXEL *)seg->lines)); - ip++; -#if defined(LZ_RGB24) || defined(LZ_RGB32) - } else { - ip++; - } -#endif - /* assuming literal copy */ - encode_copy_count(encoder, MAX_COPY - 1); - continue; - -literal: -#ifdef DEBUG_ENCODE - printf(", copy"); - n_encoded++; -#endif - ENCODE_PIXEL(encoder, *anchor); - anchor++; - ip = anchor; - copy++; - - if (LZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) { - copy = 0; - encode_copy_count(encoder, MAX_COPY - 1); - } - } // END LOOP (ip < ip_limit) - - - /* left-over as literal copy */ - ip_bound++; - while (ip <= ip_bound) { -#ifdef DEBUG_ENCODE - printf(", copy"); - n_encoded++; -#endif - ENCODE_PIXEL(encoder, *ip); - ip++; - copy++; - if (copy == MAX_COPY) { - copy = 0; - encode_copy_count(encoder, MAX_COPY - 1); - } - } - - /* if we have copied something, adjust the copy length */ - if (copy) { - update_copy_count(encoder, copy - 1); - } else { - compress_output_prev(encoder); - } -#ifdef DEBUG_ENCODE - printf("\ntotal encoded=%d\n", n_encoded); -#endif -} - - -/* If the file is very small, copies it. - copies the first two pixels of the first segment, and sends the segments - one by one to compress_seg. - the number of bytes compressed are stored inside encoder. */ -static void FNAME(compress)(Encoder *encoder) -{ - uint32_t seg_id = encoder->cur_image.first_win_seg; - PIXEL *ip; - SharedDictionary *dict = encoder->dict; - int hval; - - // fetch the first image segment that is not too small - while ((seg_id != NULL_IMAGE_SEG_ID) && - (dict->window.segs[seg_id].image->id == encoder->cur_image.id) && - ((((PIXEL *)dict->window.segs[seg_id].lines_end) - - ((PIXEL *)dict->window.segs[seg_id].lines)) < 4)) { - // coping the segment - if (dict->window.segs[seg_id].lines != dict->window.segs[seg_id].lines_end) { - ip = (PIXEL *)dict->window.segs[seg_id].lines; - // Note: we assume MAX_COPY > 3 - encode_copy_count(encoder, (uint8_t)( - (((PIXEL *)dict->window.segs[seg_id].lines_end) - - ((PIXEL *)dict->window.segs[seg_id].lines)) - 1)); - while (ip < (PIXEL *)dict->window.segs[seg_id].lines_end) { - ENCODE_PIXEL(encoder, *ip); - ip++; - } - } - seg_id = dict->window.segs[seg_id].next; - } - - if ((seg_id == NULL_IMAGE_SEG_ID) || - (dict->window.segs[seg_id].image->id != encoder->cur_image.id)) { - return; - } - - ip = (PIXEL *)dict->window.segs[seg_id].lines; - - - encode_copy_count(encoder, MAX_COPY - 1); - - HASH_FUNC(hval, ip); - UPDATE_HASH(encoder->dict, hval, seg_id, 0); - - ENCODE_PIXEL(encoder, *ip); - ip++; - ENCODE_PIXEL(encoder, *ip); - ip++; -#ifdef DEBUG_ENCODE - printf("copy, copy"); -#endif - // compressing the first segment - FNAME(compress_seg)(encoder, seg_id, ip, 2); - - // compressing the next segments - for (seg_id = dict->window.segs[seg_id].next; - seg_id != NULL_IMAGE_SEG_ID && ( - dict->window.segs[seg_id].image->id == encoder->cur_image.id); - seg_id = dict->window.segs[seg_id].next) { - FNAME(compress_seg)(encoder, seg_id, (PIXEL *)dict->window.segs[seg_id].lines, 0); - } -} - -#undef FNAME -#undef PIXEL_ID -#undef PIXEL_DIST -#undef PIXEL -#undef ENCODE_PIXEL -#undef SAME_PIXEL -#undef HASH_FUNC -#undef GET_r -#undef GET_g -#undef GET_b -#undef GET_CODE -#undef LZ_PLT -#undef LZ_RGB_ALPHA -#undef LZ_RGB16 -#undef LZ_RGB24 -#undef LZ_RGB32 -#undef MIN_REF_ENCODE_SIZE -#undef MAX_REF_ENCODE_SIZE diff --git a/server/glz_encoder.c b/server/glz_encoder.c deleted file mode 100644 index 1ec1f9bd..00000000 --- a/server/glz_encoder.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - Copyright (C) 2009 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 <pthread.h> -#include <stdio.h> -#include "glz_encoder.h" -#include "glz_encoder_dictionary_protected.h" - - -/* Holds a specific data for one encoder, and data that is relevant for the current image encoded */ -typedef struct Encoder { - GlzEncoderUsrContext *usr; - uint8_t id; - SharedDictionary *dict; - - struct { - LzImageType type; - uint32_t id; - uint32_t first_win_seg; - } cur_image; - - struct { - uint8_t *start; - uint8_t *now; - uint8_t *end; - size_t bytes_count; - uint8_t *last_copy; // pointer to the last byte in which copy count was written - } io; -} Encoder; - - -/************************************************************************** -* Handling writing the encoded image to the output buffer -***************************************************************************/ -static INLINE int more_io_bytes(Encoder *encoder) -{ - uint8_t *io_ptr; - int num_io_bytes = encoder->usr->more_space(encoder->usr, &io_ptr); - encoder->io.bytes_count += num_io_bytes; - encoder->io.now = io_ptr; - encoder->io.end = encoder->io.now + num_io_bytes; - return num_io_bytes; -} - -static INLINE void encode(Encoder *encoder, uint8_t byte) -{ - if (encoder->io.now == encoder->io.end) { - if (more_io_bytes(encoder) <= 0) { - encoder->usr->error(encoder->usr, "%s: no more bytes\n", __FUNCTION__); - } - GLZ_ASSERT(encoder->usr, encoder->io.now); - } - - GLZ_ASSERT(encoder->usr, encoder->io.now < encoder->io.end); - *(encoder->io.now++) = byte; -} - -static INLINE void encode_32(Encoder *encoder, unsigned int word) -{ - encode(encoder, (uint8_t)(word >> 24)); - encode(encoder, (uint8_t)(word >> 16) & 0x0000ff); - encode(encoder, (uint8_t)(word >> 8) & 0x0000ff); - encode(encoder, (uint8_t)(word & 0x0000ff)); -} - -static INLINE void encode_64(Encoder *encoder, uint64_t word) -{ - encode_32(encoder, (uint32_t)(word >> 32)); - encode_32(encoder, (uint32_t)(word & 0xffffff)); -} - -static INLINE void encode_copy_count(Encoder *encoder, uint8_t copy_count) -{ - encode(encoder, copy_count); - encoder->io.last_copy = encoder->io.now - 1; // io_now cannot be the first byte of the buffer -} - -static INLINE void update_copy_count(Encoder *encoder, uint8_t copy_count) -{ - GLZ_ASSERT(encoder->usr, encoder->io.last_copy); - *(encoder->io.last_copy) = copy_count; -} - -// decrease the io ptr by 1 -static INLINE void compress_output_prev(Encoder *encoder) -{ - // io_now cannot be the first byte of the buffer - encoder->io.now--; - // the function should be called only when copy count is written unnecessarily by glz_compress - GLZ_ASSERT(encoder->usr, encoder->io.now == encoder->io.last_copy) -} - -static int encoder_reset(Encoder *encoder, uint8_t *io_ptr, uint8_t *io_ptr_end) -{ - GLZ_ASSERT(encoder->usr, io_ptr <= io_ptr_end); - encoder->io.bytes_count = io_ptr_end - io_ptr; - encoder->io.start = io_ptr; - encoder->io.now = io_ptr; - encoder->io.end = io_ptr_end; - encoder->io.last_copy = NULL; - - return TRUE; -} - -/********************************************************** -* Encoding -***********************************************************/ - -GlzEncoderContext *glz_encoder_create(uint8_t id, GlzEncDictContext *dictionary, - GlzEncoderUsrContext *usr) -{ - Encoder *encoder; - - if (!usr || !usr->error || !usr->warn || !usr->info || !usr->malloc || - !usr->free || !usr->more_space) { - return NULL; - } - - if (!(encoder = (Encoder *)usr->malloc(usr, sizeof(Encoder)))) { - return NULL; - } - - encoder->id = id; - encoder->usr = usr; - encoder->dict = (SharedDictionary *)dictionary; - - return (GlzEncoderContext *)encoder; -} - -void glz_encoder_destroy(GlzEncoderContext *opaque_encoder) -{ - Encoder *encoder = (Encoder *)opaque_encoder; - - if (!opaque_encoder) { - return; - } - - encoder->usr->free(encoder->usr, encoder); -} - -/* - * Give hints to the compiler for branch prediction optimization. - */ -#if defined(__GNUC__) && (__GNUC__ > 2) -#define LZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1)) -#define LZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0)) -#else -#define LZ_EXPECT_CONDITIONAL(c) (c) -#define LZ_UNEXPECT_CONDITIONAL(c) (c) -#endif - - -typedef uint8_t BYTE; - -typedef struct __attribute__ ((__packed__)) one_byte_pixel_t { - BYTE a; -} one_byte_pixel_t; - -typedef struct __attribute__ ((__packed__)) rgb32_pixel_t { - BYTE b; - BYTE g; - BYTE r; - BYTE pad; -} rgb32_pixel_t; - -typedef struct __attribute__ ((__packed__)) rgb24_pixel_t { - BYTE b; - BYTE g; - BYTE r; -} rgb24_pixel_t; - -typedef uint16_t rgb16_pixel_t; - -#define BOUND_OFFSET 2 -#define LIMIT_OFFSET 6 -#define MIN_FILE_SIZE 4 - -#define MAX_PIXEL_SHORT_DISTANCE 4096 // (1 << 12) -#define MAX_PIXEL_MEDIUM_DISTANCE 131072 // (1 << 17) 2 ^ (12 + 5) -#define MAX_PIXEL_LONG_DISTANCE 33554432 // (1 << 25) 2 ^ (12 + 5 + 8) -#define MAX_IMAGE_DIST 16777215 // (1 << 24 - 1) - - -//#define DEBUG_ENCODE - - -#define GLZ_ENCODE_SIZE -#include "glz_encode_match_tmpl.c" -#define GLZ_ENCODE_MATCH -#include "glz_encode_match_tmpl.c" - -#define LZ_PLT -#include "glz_encode_tmpl.c" - -#define LZ_RGB16 -#include "glz_encode_tmpl.c" - -#define LZ_RGB24 -#include "glz_encode_tmpl.c" - -#define LZ_RGB32 -#include "glz_encode_tmpl.c" - -#define LZ_RGB_ALPHA -#include "glz_encode_tmpl.c" - - -int glz_encode(GlzEncoderContext *opaque_encoder, - LzImageType type, int width, int height, int top_down, - uint8_t *lines, unsigned int num_lines, int stride, - uint8_t *io_ptr, unsigned int num_io_bytes, - GlzUsrImageContext *usr_context, GlzEncDictImageContext **o_enc_dict_context) -{ - Encoder *encoder = (Encoder *)opaque_encoder; - WindowImage *dict_image; - uint8_t *io_ptr_end = io_ptr + num_io_bytes; - uint32_t win_head_image_dist; - - if (IS_IMAGE_TYPE_PLT[type]) { - if (stride > (width / PLT_PIXELS_PER_BYTE[type])) { - if (((width % PLT_PIXELS_PER_BYTE[type]) == 0) || ( - (stride - (width / PLT_PIXELS_PER_BYTE[type])) > 1)) { - encoder->usr->error(encoder->usr, "stride overflows (plt)\n"); - } - } - } else { - if (stride != width * RGB_BYTES_PER_PIXEL[type]) { - encoder->usr->error(encoder->usr, "stride != width*bytes_per_pixel (rgb)\n"); - } - } - - // assign the output buffer - if (!encoder_reset(encoder, io_ptr, io_ptr_end)) { - encoder->usr->error(encoder->usr, "lz encoder io reset failed\n"); - } - - // first read the list of the image segments into the dictionary window - dict_image = glz_dictionary_pre_encode(encoder->id, encoder->usr, - encoder->dict, type, width, height, stride, - lines, num_lines, usr_context, &win_head_image_dist); - *o_enc_dict_context = (GlzEncDictImageContext *)dict_image; - - encoder->cur_image.type = type; - encoder->cur_image.id = dict_image->id; - encoder->cur_image.first_win_seg = dict_image->first_seg; - - encode_32(encoder, LZ_MAGIC); - encode_32(encoder, LZ_VERSION); - if (top_down) { - encode(encoder, (type & LZ_IMAGE_TYPE_MASK) | (1 << LZ_IMAGE_TYPE_LOG)); - } else { - encode(encoder, (type & LZ_IMAGE_TYPE_MASK)); - } - - encode_32(encoder, width); - encode_32(encoder, height); - encode_32(encoder, stride); - encode_64(encoder, dict_image->id); - encode_32(encoder, win_head_image_dist); - - switch (encoder->cur_image.type) { - case LZ_IMAGE_TYPE_PLT1_BE: - case LZ_IMAGE_TYPE_PLT1_LE: - case LZ_IMAGE_TYPE_PLT4_BE: - case LZ_IMAGE_TYPE_PLT4_LE: - case LZ_IMAGE_TYPE_PLT8: - glz_plt_compress(encoder); - break; - case LZ_IMAGE_TYPE_RGB16: - glz_rgb16_compress(encoder); - break; - case LZ_IMAGE_TYPE_RGB24: - glz_rgb24_compress(encoder); - break; - case LZ_IMAGE_TYPE_RGB32: - glz_rgb32_compress(encoder); - break; - case LZ_IMAGE_TYPE_RGBA: - glz_rgb32_compress(encoder); - glz_rgb_alpha_compress(encoder); - break; - case LZ_IMAGE_TYPE_INVALID: - default: - encoder->usr->error(encoder->usr, "bad image type\n"); - } - - glz_dictionary_post_encode(encoder->id, encoder->usr, encoder->dict); - - // move all the used segments to the free ones - encoder->io.bytes_count -= (encoder->io.end - encoder->io.now); - - return encoder->io.bytes_count; -} diff --git a/server/glz_encoder.h b/server/glz_encoder.h deleted file mode 100644 index 34c363a3..00000000 --- a/server/glz_encoder.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (C) 2009 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 _H_GLZ_ENCODER -#define _H_GLZ_ENCODER - -/* Manging the lz encoding using a dictionary that is shared among encoders */ - -#include <stdint.h> -#include "common/lz_common.h" -#include "glz_encoder_dictionary.h" -#include "glz_encoder_config.h" - -typedef void GlzEncoderContext; - -GlzEncoderContext *glz_encoder_create(uint8_t id, GlzEncDictContext *dictionary, - GlzEncoderUsrContext *usr); - -void glz_encoder_destroy(GlzEncoderContext *opaque_encoder); - -/* - assumes width is in pixels and stride is in bytes - usr_context : when an image is released from the window due to capacity overflow, - usr_context is given as a parameter to the free_image callback. - o_enc_dict_context: if glz_enc_dictionary_remove_image is called, it should be - called with the o_enc_dict_context that is associated with - the image. - - return: the number of bytes in the compressed data and sets o_enc_dict_context - - NOTE : currently supports only rgb images in which width*bytes_per_pixel = stride OR - palette images in which stride equals the min number of bytes to hold a line. - The stride should be > 0 -*/ -int glz_encode(GlzEncoderContext *opaque_encoder, LzImageType type, int width, int height, - int top_down, uint8_t *lines, unsigned int num_lines, int stride, - uint8_t *io_ptr, unsigned int num_io_bytes, GlzUsrImageContext *usr_context, - GlzEncDictImageContext **o_enc_dict_context); - - -#endif // _H_GLZ_ENCODER diff --git a/server/glz_encoder_config.h b/server/glz_encoder_config.h deleted file mode 100644 index 886c68ba..00000000 --- a/server/glz_encoder_config.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 2009 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 _H_GLZ_ENCODER_CONFIG -#define _H_GLZ_ENCODER_CONFIG - -#include <spice/macros.h> -#include "common/lz_common.h" - -typedef void GlzUsrImageContext; -typedef struct GlzEncoderUsrContext GlzEncoderUsrContext; - -struct GlzEncoderUsrContext { - SPICE_GNUC_PRINTF(2, 3) void (*error)(GlzEncoderUsrContext *usr, const char *fmt, ...); - SPICE_GNUC_PRINTF(2, 3) void (*warn)(GlzEncoderUsrContext *usr, const char *fmt, ...); - SPICE_GNUC_PRINTF(2, 3) void (*info)(GlzEncoderUsrContext *usr, const char *fmt, ...); - void *(*malloc)(GlzEncoderUsrContext *usr, int size); - void (*free)(GlzEncoderUsrContext *usr, void *ptr); - - // get the next chunk of the image which is entered to the dictionary. If the image is down to - // top, return it from the last line to the first one (stride should always be positive) - int (*more_lines)(GlzEncoderUsrContext *usr, uint8_t **lines); - - // get the next chunk of the compressed buffer.return number of bytes in the chunk. - int (*more_space)(GlzEncoderUsrContext *usr, uint8_t **io_ptr); - - // called when an image is removed from the dictionary, due to the window size limit - void (*free_image)(GlzEncoderUsrContext *usr, GlzUsrImageContext *image); - -}; - - -#ifdef DEBUG - -#define GLZ_ASSERT(usr, x) \ - if (!(x)) (usr)->error(usr, "%s: ASSERT %s failed\n", __FUNCTION__, #x); - -#else - -#define GLZ_ASSERT(usr, x) - -#endif - -#define INLINE inline - - -#endif diff --git a/server/glz_encoder_dictionary.c b/server/glz_encoder_dictionary.c deleted file mode 100644 index df346d08..00000000 --- a/server/glz_encoder_dictionary.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - Copyright (C) 2009 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 <pthread.h> -#include <string.h> -#include <stdio.h> - -#include "glz_encoder_dictionary.h" -#include "glz_encoder_dictionary_protected.h" - -/* turning all used images to free ones. If they are alive, calling the free_image callback for - each one */ -static INLINE void __glz_dictionary_window_reset_images(SharedDictionary *dict) -{ - WindowImage *tmp; - - while (dict->window.used_images_head) { - tmp = dict->window.used_images_head; - dict->window.used_images_head = dict->window.used_images_head->next; - if (tmp->is_alive) { - dict->cur_usr->free_image(dict->cur_usr, tmp->usr_context); - } - tmp->next = dict->window.free_images; - tmp->is_alive = FALSE; - dict->window.free_images = tmp; - } - dict->window.used_images_tail = NULL; -} - -/* allocate window fields (no reset)*/ -static int glz_dictionary_window_create(SharedDictionary *dict, uint32_t size) -{ - if (size > LZ_MAX_WINDOW_SIZE) { - return FALSE; - } - - dict->window.size_limit = size; - dict->window.segs = (WindowImageSegment *)( - dict->cur_usr->malloc(dict->cur_usr, sizeof(WindowImageSegment) * INIT_IMAGE_SEGS_NUM)); - - if (!dict->window.segs) { - return FALSE; - } - - dict->window.segs_quota = INIT_IMAGE_SEGS_NUM; - - dict->window.encoders_heads = (uint32_t *)dict->cur_usr->malloc(dict->cur_usr, - sizeof(uint32_t) * dict->max_encoders); - - if (!dict->window.encoders_heads) { - dict->cur_usr->free(dict->cur_usr, dict->window.segs); - return FALSE; - } - - dict->window.used_images_head = NULL; - dict->window.used_images_tail = NULL; - dict->window.free_images = NULL; - dict->window.pixels_so_far = 0; - - return TRUE; -} - -/* initializes an empty window (segs and encoder_heads should be pre allocated. - resets the image infos, and calls the free_image usr callback*/ -static void glz_dictionary_window_reset(SharedDictionary *dict) -{ - uint32_t i; - WindowImageSegment *seg, *last_seg; - - last_seg = dict->window.segs + dict->window.segs_quota; - /* reset free segs list */ - dict->window.free_segs_head = 0; - for (seg = dict->window.segs, i = 0; seg < last_seg; seg++, i++) { - seg->next = i + 1; - seg->image = NULL; - seg->lines = NULL; - seg->lines_end = NULL; - seg->pixels_num = 0; - seg->pixels_so_far = 0; - } - dict->window.segs[dict->window.segs_quota - 1].next = NULL_IMAGE_SEG_ID; - - dict->window.used_segs_head = NULL_IMAGE_SEG_ID; - dict->window.used_segs_tail = NULL_IMAGE_SEG_ID; - - // reset encoders heads - for (i = 0; i < dict->max_encoders; i++) { - dict->window.encoders_heads[i] = NULL_IMAGE_SEG_ID; - } - - __glz_dictionary_window_reset_images(dict); -} - -static INLINE void glz_dictionary_reset_hash(SharedDictionary *dict) -{ - memset(dict->htab, 0, sizeof(HashEntry) * HASH_SIZE * HASH_CHAIN_SIZE); -#ifdef CHAINED_HASH - memset(dict->htab_counter, 0, HASH_SIZE * sizeof(uint8_t)); -#endif -} - -static INLINE void glz_dictionary_window_destroy(SharedDictionary *dict) -{ - __glz_dictionary_window_reset_images(dict); - - if (dict->window.segs) { - dict->cur_usr->free(dict->cur_usr, dict->window.segs); - dict->window.segs = NULL; - } - - while (dict->window.free_images) { - WindowImage *tmp = dict->window.free_images; - dict->window.free_images = tmp->next; - - dict->cur_usr->free(dict->cur_usr, tmp); - } - - if (dict->window.encoders_heads) { - dict->cur_usr->free(dict->cur_usr, dict->window.encoders_heads); - dict->window.encoders_heads = NULL; - } -} - -/* logic removal only */ -static INLINE void glz_dictionary_window_kill_image(SharedDictionary *dict, WindowImage *image) -{ - image->is_alive = FALSE; -} - -GlzEncDictContext *glz_enc_dictionary_create(uint32_t size, uint32_t max_encoders, - GlzEncoderUsrContext *usr) -{ - SharedDictionary *dict; - - if (!(dict = (SharedDictionary *)usr->malloc(usr, - sizeof(SharedDictionary)))) { - return NULL; - } - - dict->cur_usr = usr; - dict->last_image_id = 0; - dict->max_encoders = max_encoders; - - pthread_mutex_init(&dict->lock, NULL); - pthread_rwlock_init(&dict->rw_alloc_lock, NULL); - - dict->window.encoders_heads = NULL; - - // alloc window fields and reset - if (!glz_dictionary_window_create(dict, size)) { - dict->cur_usr->free(usr, dict); - return NULL; - } - - // reset window and hash - glz_enc_dictionary_reset((GlzEncDictContext *)dict, usr); - - return (GlzEncDictContext *)dict; -} - -void glz_enc_dictionary_get_restore_data(GlzEncDictContext *opaque_dict, - GlzEncDictRestoreData *out_data, GlzEncoderUsrContext *usr) -{ - SharedDictionary *dict = (SharedDictionary *)opaque_dict; - dict->cur_usr = usr; - GLZ_ASSERT(dict->cur_usr, opaque_dict); - GLZ_ASSERT(dict->cur_usr, out_data); - - out_data->last_image_id = dict->last_image_id; - out_data->max_encoders = dict->max_encoders; - out_data->size = dict->window.size_limit; -} - -GlzEncDictContext *glz_enc_dictionary_restore(GlzEncDictRestoreData *restore_data, - GlzEncoderUsrContext *usr) -{ - if (!restore_data) { - return NULL; - } - SharedDictionary *ret = (SharedDictionary *)glz_enc_dictionary_create( - restore_data->size, restore_data->max_encoders, usr); - ret->last_image_id = restore_data->last_image_id; - return ((GlzEncDictContext *)ret); -} - -void glz_enc_dictionary_reset(GlzEncDictContext *opaque_dict, GlzEncoderUsrContext *usr) -{ - SharedDictionary *dict = (SharedDictionary *)opaque_dict; - dict->cur_usr = usr; - GLZ_ASSERT(dict->cur_usr, opaque_dict); - - dict->last_image_id = 0; - glz_dictionary_window_reset(dict); - glz_dictionary_reset_hash(dict); -} - -void glz_enc_dictionary_destroy(GlzEncDictContext *opaque_dict, GlzEncoderUsrContext *usr) -{ - SharedDictionary *dict = (SharedDictionary *)opaque_dict; - - if (!opaque_dict) { - return; - } - - dict->cur_usr = usr; - glz_dictionary_window_destroy(dict); - - pthread_mutex_destroy(&dict->lock); - pthread_rwlock_destroy(&dict->rw_alloc_lock); - - dict->cur_usr->free(dict->cur_usr, dict); -} - -uint32_t glz_enc_dictionary_get_size(GlzEncDictContext *opaque_dict) -{ - SharedDictionary *dict = (SharedDictionary *)opaque_dict; - - if (!opaque_dict) { - return 0; - } - return dict->window.size_limit; -} - -/* doesn't call the remove image callback */ -void glz_enc_dictionary_remove_image(GlzEncDictContext *opaque_dict, - GlzEncDictImageContext *opaque_image, - GlzEncoderUsrContext *usr) -{ - SharedDictionary *dict = (SharedDictionary *)opaque_dict; - WindowImage *image = (WindowImage *)opaque_image; - dict->cur_usr = usr; - GLZ_ASSERT(dict->cur_usr, opaque_image && opaque_dict); - - glz_dictionary_window_kill_image(dict, image); -} - -/*********************************************************************************** - Mutators of the window. Should be called by the encoder before and after encoding. - ***********************************************************************************/ - -static INLINE int __get_pixels_num(LzImageType image_type, unsigned int num_lines, int stride) -{ - if (IS_IMAGE_TYPE_RGB[image_type]) { - return num_lines * stride / RGB_BYTES_PER_PIXEL[image_type]; - } else { - return num_lines * stride * PLT_PIXELS_PER_BYTE[image_type]; - } -} - -static void __glz_dictionary_window_segs_realloc(SharedDictionary *dict) -{ - WindowImageSegment *new_segs; - uint32_t new_quota = (MAX_IMAGE_SEGS_NUM < (dict->window.segs_quota * 2)) ? - MAX_IMAGE_SEGS_NUM : (dict->window.segs_quota * 2); - WindowImageSegment *seg; - uint32_t i; - - pthread_rwlock_wrlock(&dict->rw_alloc_lock); - - if (dict->window.segs_quota == MAX_IMAGE_SEGS_NUM) { - dict->cur_usr->error(dict->cur_usr, "overflow in image segments window\n"); - } - - new_segs = (WindowImageSegment*)dict->cur_usr->malloc( - dict->cur_usr, sizeof(WindowImageSegment) * new_quota); - - if (!new_segs) { - dict->cur_usr->error(dict->cur_usr, - "realloc of dictionary window failed\n"); - } - - memcpy(new_segs, dict->window.segs, - sizeof(WindowImageSegment) * dict->window.segs_quota); - - // reseting the new elements - for (i = dict->window.segs_quota, seg = new_segs + i; i < new_quota; i++, seg++) { - seg->image = NULL; - seg->lines = NULL; - seg->lines_end = NULL; - seg->pixels_num = 0; - seg->pixels_so_far = 0; - seg->next = i + 1; - } - new_segs[new_quota - 1].next = dict->window.free_segs_head; - dict->window.free_segs_head = dict->window.segs_quota; - - dict->cur_usr->free(dict->cur_usr, dict->window.segs); - dict->window.segs = new_segs; - dict->window.segs_quota = new_quota; - - pthread_rwlock_unlock(&dict->rw_alloc_lock); -} - -/* NOTE - it also updates the used_images_list*/ -static WindowImage *__glz_dictionary_window_alloc_image(SharedDictionary *dict) -{ - WindowImage *ret; - - if (dict->window.free_images) { - ret = dict->window.free_images; - dict->window.free_images = ret->next; - } else { - if (!(ret = (WindowImage *)dict->cur_usr->malloc(dict->cur_usr, - sizeof(*ret)))) { - return NULL; - } - } - - ret->next = NULL; - if (dict->window.used_images_tail) { - dict->window.used_images_tail->next = ret; - } - dict->window.used_images_tail = ret; - - if (!dict->window.used_images_head) { - dict->window.used_images_head = ret; - } - return ret; -} - -/* NOTE - it doesn't update the used_segs list*/ -static uint32_t __glz_dictionary_window_alloc_image_seg(SharedDictionary *dict) -{ - uint32_t seg_id; - WindowImageSegment *seg; - - // TODO: when is it best to realloc? when full or when half full? - if (dict->window.free_segs_head == NULL_IMAGE_SEG_ID) { - __glz_dictionary_window_segs_realloc(dict); - } - - GLZ_ASSERT(dict->cur_usr, dict->window.free_segs_head != NULL_IMAGE_SEG_ID); - - seg_id = dict->window.free_segs_head; - seg = dict->window.segs + seg_id; - dict->window.free_segs_head = seg->next; - - return seg_id; -} - -/* moves image to free list and "kill" it. Calls the free_image callback if was alive. */ -static INLINE void __glz_dictionary_window_free_image(SharedDictionary *dict, WindowImage *image) -{ - if (image->is_alive) { - dict->cur_usr->free_image(dict->cur_usr, image->usr_context); - } - image->is_alive = FALSE; - image->next = dict->window.free_images; - dict->window.free_images = image; -} - -/* moves all the segments that were associated with the images to the free segments */ -static INLINE void __glz_dictionary_window_free_image_segs(SharedDictionary *dict, - WindowImage *image) -{ - uint32_t old_free_head = dict->window.free_segs_head; - uint32_t seg_id, next_seg_id; - - GLZ_ASSERT(dict->cur_usr, image->first_seg != NULL_IMAGE_SEG_ID); - dict->window.free_segs_head = image->first_seg; - - // retrieving the last segment of the image - for (seg_id = image->first_seg, next_seg_id = dict->window.segs[seg_id].next; - (next_seg_id != NULL_IMAGE_SEG_ID) && (dict->window.segs[next_seg_id].image == image); - seg_id = next_seg_id, next_seg_id = dict->window.segs[seg_id].next) { - } - - // concatenate the free list - dict->window.segs[seg_id].next = old_free_head; -} - -/* Returns the logical head of the window after we add an image with the give size to its tail. - Returns NULL when the window is empty, of when we have to empty the window in order - to insert the new image. */ -static WindowImage *glz_dictionary_window_get_new_head(SharedDictionary *dict, int new_image_size) -{ - uint32_t cur_win_size; - WindowImage *cur_head; - - if ((uint32_t)new_image_size > dict->window.size_limit) { - dict->cur_usr->error(dict->cur_usr, "image is bigger than window\n"); - } - - GLZ_ASSERT(dict->cur_usr, new_image_size < dict->window.size_limit) - - // the window is empty - if (!dict->window.used_images_head) { - return NULL; - } - - GLZ_ASSERT(dict->cur_usr, dict->window.used_segs_head != NULL_IMAGE_SEG_ID); - GLZ_ASSERT(dict->cur_usr, dict->window.used_segs_tail != NULL_IMAGE_SEG_ID); - - // used_segs_head is the latest logical head (the physical head may preceed it) - cur_head = dict->window.segs[dict->window.used_segs_head].image; - cur_win_size = dict->window.segs[dict->window.used_segs_tail].pixels_num + - dict->window.segs[dict->window.used_segs_tail].pixels_so_far - - dict->window.segs[dict->window.used_segs_head].pixels_so_far; - - while ((cur_win_size + new_image_size) > dict->window.size_limit) { - GLZ_ASSERT(dict->cur_usr, cur_head); - cur_win_size -= cur_head->size; - cur_head = cur_head->next; - } - - return cur_head; -} - -static INLINE int glz_dictionary_is_in_use(SharedDictionary *dict) -{ - uint32_t i = 0; - for (i = 0; i < dict->max_encoders; i++) { - if (dict->window.encoders_heads[i] != NULL_IMAGE_SEG_ID) { - return TRUE; - } - } - return FALSE; -} - -/* remove from the window (and free relevant data) the images between the oldest physical head - (inclusive) and the end_image (exclusive). If end_image is NULL, empties the window*/ -static void glz_dictionary_window_remove_head(SharedDictionary *dict, uint32_t encoder_id, - WindowImage *end_image) -{ - // note that the segs list heads (one per encoder) may be different than the - // used_segs_head and it is updated somewhere else - while (dict->window.used_images_head != end_image) { - WindowImage *image = dict->window.used_images_head; - - __glz_dictionary_window_free_image_segs(dict, image); - dict->window.used_images_head = image->next; - __glz_dictionary_window_free_image(dict, image); - } - - if (!dict->window.used_images_head) { - dict->window.used_segs_head = NULL_IMAGE_SEG_ID; - dict->window.used_segs_tail = NULL_IMAGE_SEG_ID; - dict->window.used_images_tail = NULL; - } else { - dict->window.used_segs_head = end_image->first_seg; - } -} - -static uint32_t glz_dictionary_window_alloc_image_seg(SharedDictionary *dict, WindowImage* image, - int size, int stride, - uint8_t *lines, unsigned int num_lines) -{ - uint32_t seg_id = __glz_dictionary_window_alloc_image_seg(dict); - WindowImageSegment *seg = &dict->window.segs[seg_id]; - - seg->image = image; - seg->lines = lines; - seg->lines_end = lines + num_lines * stride; - seg->pixels_num = size; - seg->pixels_so_far = dict->window.pixels_so_far; - dict->window.pixels_so_far += seg->pixels_num; - - seg->next = NULL_IMAGE_SEG_ID; - - return seg_id; -} - -static WindowImage *glz_dictionary_window_add_image(SharedDictionary *dict, LzImageType image_type, - int image_size, int image_height, - int image_stride, uint8_t *first_lines, - unsigned int num_first_lines, - GlzUsrImageContext *usr_image_context) -{ - unsigned int num_lines = num_first_lines; - unsigned int row; - uint32_t seg_id, prev_seg_id; - uint8_t* lines = first_lines; - // alloc image info,update used head tail, if used_head null - update head - WindowImage *image = __glz_dictionary_window_alloc_image(dict); - image->id = dict->last_image_id++; - image->size = image_size; - image->type = image_type; - image->usr_context = usr_image_context; - - if (num_lines <= 0) { - num_lines = dict->cur_usr->more_lines(dict->cur_usr, &lines); - if (num_lines <= 0) { - dict->cur_usr->error(dict->cur_usr, "more lines failed\n"); - } - } - - for (row = 0;;) { - seg_id = glz_dictionary_window_alloc_image_seg(dict, image, - image_size * num_lines / image_height, - image_stride, - lines, num_lines); - if (row == 0) { - image->first_seg = seg_id; - } else { - dict->window.segs[prev_seg_id].next = seg_id; - } - - row += num_lines; - if (row < (uint32_t)image_height) { - num_lines = dict->cur_usr->more_lines(dict->cur_usr, &lines); - if (num_lines <= 0) { - dict->cur_usr->error(dict->cur_usr, "more lines failed\n"); - } - } else { - break; - } - prev_seg_id = seg_id; - } - - if (dict->window.used_segs_tail == NULL_IMAGE_SEG_ID) { - dict->window.used_segs_head = image->first_seg; - dict->window.used_segs_tail = seg_id; - } else { - int prev_tail = dict->window.used_segs_tail; - - // The used segs may be in use by another thread which is during encoding - // (read-only use - when going over the segs of an image, - // see glz_encode_tmpl::compress). - // Thus, the 'next' field of the list's tail can be accessed only - // after all the new tail's data was set. Note that we are relying on - // an atomic assignment (32 bit variable). - // For the other thread that may read 'next' of the old tail, NULL_IMAGE_SEG_ID - // is equivalent to a segment with an image id that is different - // from the image id of the tail, so we don't need to further protect this field. - dict->window.segs[prev_tail].next = image->first_seg; - dict->window.used_segs_tail = seg_id; - } - image->is_alive = TRUE; - - return image; -} - -WindowImage *glz_dictionary_pre_encode(uint32_t encoder_id, GlzEncoderUsrContext *usr, - SharedDictionary *dict, LzImageType image_type, - int image_width, int image_height, int image_stride, - uint8_t *first_lines, unsigned int num_first_lines, - GlzUsrImageContext *usr_image_context, - uint32_t *image_head_dist) -{ - WindowImage *new_win_head, *ret; - int image_size; - - - pthread_mutex_lock(&dict->lock); - - dict->cur_usr = usr; - GLZ_ASSERT(dict->cur_usr, dict->window.encoders_heads[encoder_id] == NULL_IMAGE_SEG_ID); - - image_size = __get_pixels_num(image_type, image_height, image_stride); - new_win_head = glz_dictionary_window_get_new_head(dict, image_size); - - if (!glz_dictionary_is_in_use(dict)) { - glz_dictionary_window_remove_head(dict, encoder_id, new_win_head); - } - - ret = glz_dictionary_window_add_image(dict, image_type, image_size, image_height, image_stride, - first_lines, num_first_lines, usr_image_context); - - if (new_win_head) { - dict->window.encoders_heads[encoder_id] = new_win_head->first_seg; - *image_head_dist = (uint32_t)(ret->id - new_win_head->id); // shouldn't be greater than 32 - // bit because the window size is - // limited to 2^25 - } else { - dict->window.encoders_heads[encoder_id] = ret->first_seg; - *image_head_dist = 0; - } - - - // update encoders head (the other heads were already updated) - pthread_mutex_unlock(&dict->lock); - pthread_rwlock_rdlock(&dict->rw_alloc_lock); - return ret; -} - -void glz_dictionary_post_encode(uint32_t encoder_id, GlzEncoderUsrContext *usr, - SharedDictionary *dict) -{ - uint32_t i; - uint32_t early_head_seg = NULL_IMAGE_SEG_ID; - uint32_t this_encoder_head_seg; - - pthread_rwlock_unlock(&dict->rw_alloc_lock); - pthread_mutex_lock(&dict->lock); - dict->cur_usr = usr; - - GLZ_ASSERT(dict->cur_usr, dict->window.encoders_heads[encoder_id] != NULL_IMAGE_SEG_ID); - // get the earliest head in use (not including this encoder head) - for (i = 0; i < dict->max_encoders; i++) { - if (i != encoder_id) { - if (IMAGE_SEG_IS_EARLIER(dict, dict->window.encoders_heads[i], early_head_seg)) { - early_head_seg = dict->window.encoders_heads[i]; - } - } - } - - // possible only if early_head_seg == NULL - if (IMAGE_SEG_IS_EARLIER(dict, dict->window.used_segs_head, early_head_seg)) { - early_head_seg = dict->window.used_segs_head; - } - - this_encoder_head_seg = dict->window.encoders_heads[encoder_id]; - - GLZ_ASSERT(dict->cur_usr, early_head_seg != NULL_IMAGE_SEG_ID); - - if (IMAGE_SEG_IS_EARLIER(dict, this_encoder_head_seg, early_head_seg)) { - GLZ_ASSERT(dict->cur_usr, - this_encoder_head_seg == dict->window.used_images_head->first_seg); - glz_dictionary_window_remove_head(dict, encoder_id, - dict->window.segs[early_head_seg].image); - } - - - dict->window.encoders_heads[encoder_id] = NULL_IMAGE_SEG_ID; - pthread_mutex_unlock(&dict->lock); -} diff --git a/server/glz_encoder_dictionary.h b/server/glz_encoder_dictionary.h deleted file mode 100644 index eb57aa54..00000000 --- a/server/glz_encoder_dictionary.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (C) 2009 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 _H_GLZ_ENCODER_DICTIONARY -#define _H_GLZ_ENCODER_DICTIONARY - -#include <stdint.h> -#include "glz_encoder_config.h" - -/* - Interface for maintaining lz dictionary that is shared among several encoders. - The interface for accessing the dictionary for encoding purposes is located in - glz_encoder_dictionary_protected.h -*/ - -typedef void GlzEncDictContext; -typedef void GlzEncDictImageContext; - -/* NOTE: DISPLAY_MIGRATE_DATA_VERSION should change in case GlzEncDictRestoreData changes*/ -typedef struct GlzEncDictRestoreData { - uint32_t size; - uint32_t max_encoders; - uint64_t last_image_id; -} GlzEncDictRestoreData; - -/* size : maximal number of pixels occupying the window - max_encoders: maximal number of encoders that use the dictionary - usr : callbacks */ -GlzEncDictContext *glz_enc_dictionary_create(uint32_t size, uint32_t max_encoders, - GlzEncoderUsrContext *usr); - -void glz_enc_dictionary_destroy(GlzEncDictContext *opaque_dict, GlzEncoderUsrContext *usr); - -/* returns the window capacity in pixels */ -uint32_t glz_enc_dictionary_get_size(GlzEncDictContext *); - -/* returns the current state of the dictionary. - NOTE - you should use it only when no encoder uses the dictionary. */ -void glz_enc_dictionary_get_restore_data(GlzEncDictContext *opaque_dict, - GlzEncDictRestoreData *out_data, - GlzEncoderUsrContext *usr); - -/* creates a dictionary and initialized it by use the given info */ -GlzEncDictContext *glz_enc_dictionary_restore(GlzEncDictRestoreData *restore_data, - GlzEncoderUsrContext *usr); - -/* NOTE - you should use this routine only when no encoder uses the dictionary. */ -void glz_enc_dictionary_reset(GlzEncDictContext *opaque_dict, GlzEncoderUsrContext *usr); - -/* image: the context returned by the encoder when the image was encoded. - NOTE - you should use this routine only when no encoder uses the dictionary.*/ -void glz_enc_dictionary_remove_image(GlzEncDictContext *opaque_dict, - GlzEncDictImageContext *image, GlzEncoderUsrContext *usr); - -#endif // _H_GLZ_ENCODER_DICTIONARY diff --git a/server/glz_encoder_dictionary_protected.h b/server/glz_encoder_dictionary_protected.h deleted file mode 100644 index ee1f8d8e..00000000 --- a/server/glz_encoder_dictionary_protected.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - Copyright (C) 2009 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 _H_GLZ_ENCODER_DICTIONARY_PROTECTED -#define _H_GLZ_ENCODER_DICTIONARY_PROTECTED - -/* Interface for using the dictionary for encoding. - Data structures are exposed for the encoder for efficiency - purposes. */ -typedef struct WindowImage WindowImage; -typedef struct WindowImageSegment WindowImageSegment; - - -//#define CHAINED_HASH - -#ifdef CHAINED_HASH -#define HASH_SIZE_LOG 16 -#define HASH_CHAIN_SIZE 4 -#else -#define HASH_SIZE_LOG 20 -#define HASH_CHAIN_SIZE 1 -#endif - -#define HASH_SIZE (1 << HASH_SIZE_LOG) -#define HASH_MASK (HASH_SIZE - 1) - -typedef struct HashEntry HashEntry; - -typedef struct SharedDictionary SharedDictionary; - -struct WindowImage { - uint64_t id; - LzImageType type; - int size; // in pixels - uint32_t first_seg; - GlzUsrImageContext *usr_context; - WindowImage* next; - uint8_t is_alive; -}; - -#define MAX_IMAGE_SEGS_NUM (0xffffffff) -#define NULL_IMAGE_SEG_ID MAX_IMAGE_SEGS_NUM -#define INIT_IMAGE_SEGS_NUM 1000 - -/* Images can be separated into several chunks. The basic unit of the - dictionary window is one image segment. Each segment is encoded separately. - An encoded match can refer to only one segment.*/ -struct WindowImageSegment { - WindowImage *image; - uint8_t *lines; - uint8_t *lines_end; - uint32_t pixels_num; // Number of pixels in the segment - uint64_t pixels_so_far; // Total no. pixels passed through the window till this segment. - // NOTE - never use size delta independently. It should - // always be used with respect to a previous size delta - uint32_t next; -}; - - -struct __attribute__ ((__packed__)) HashEntry { - uint32_t image_seg_idx; - uint32_t ref_pix_idx; -}; - - -struct SharedDictionary { - struct { - /* The segments storage. A dynamic array. - By referring to a segment by its index, instead of address, - we save space in the hash entries (32bit instead of 64bit) */ - WindowImageSegment *segs; - uint32_t segs_quota; - - /* The window is manged as a linked list rather than as a cyclic - array in order to keep the indices of the segments consistent - after reallocation */ - - /* the window in a resolution of image segments */ - uint32_t used_segs_head; // the latest head - uint32_t used_segs_tail; - uint32_t free_segs_head; - - uint32_t *encoders_heads; // Holds for each encoder (by id), the window head when - // it started the encoding. - // The head is NULL_IMAGE_SEG_ID when the encoder is - // not encoding. - - /* the window in a resolution of images. But here the head contains the oldest head*/ - WindowImage* used_images_tail; - WindowImage* used_images_head; - WindowImage* free_images; - - uint64_t pixels_so_far; - uint32_t size_limit; // max number of pixels in a window (per encoder) - } window; - - /* Concurrency issues: the reading/writing of each entry field should be atomic. - It is allowed that the reading/writing of the whole entry won't be atomic, - since before we access a reference we check its validity*/ -#ifdef CHAINED_HASH - HashEntry htab[HASH_SIZE][HASH_CHAIN_SIZE]; - uint8_t htab_counter[HASH_SIZE]; //cyclic counter for the next entry in a chain to be assigned -#else - HashEntry htab[HASH_SIZE]; -#endif - - uint64_t last_image_id; - uint32_t max_encoders; - pthread_mutex_t lock; - pthread_rwlock_t rw_alloc_lock; - GlzEncoderUsrContext *cur_usr; // each encoder has other context. -}; - -/* - Add the image to the tail of the window. - If possible, release images from the head of the window. - Also perform concurrency related operations. - - usr_image_context: when an image is released from the window due to capacity overflow, - usr_image_context is given as a parameter to the free_image callback. - - image_head_dist : the number of images between the current image and the head of the - window that is associated with the encoder. -*/ -WindowImage *glz_dictionary_pre_encode(uint32_t encoder_id, GlzEncoderUsrContext *usr, - SharedDictionary *dict, LzImageType image_type, - int image_width, int image_height, int image_stride, - uint8_t *first_lines, unsigned int num_first_lines, - GlzUsrImageContext *usr_image_context, - uint32_t *image_head_dist); - -/* - Performs concurrency related operations. - If possible, release images from the head of the window. -*/ -void glz_dictionary_post_encode(uint32_t encoder_id, GlzEncoderUsrContext *usr, - SharedDictionary *dict); - -#define IMAGE_SEG_IS_EARLIER(dict, dst_seg, src_seg) ( \ - ((src_seg) == NULL_IMAGE_SEG_ID) || (((dst_seg) != NULL_IMAGE_SEG_ID) \ - && ((dict)->window.segs[(dst_seg)].pixels_so_far < \ - (dict)->window.segs[(src_seg)].pixels_so_far))) - - -#ifdef CHAINED_HASH -#define UPDATE_HASH(dict, hval, seg, pix) { \ - uint8_t tmp_count = (dict)->htab_counter[hval]; \ - (dict)->htab[hval][tmp_count].image_seg_idx = seg; \ - (dict)->htab[hval][tmp_count].ref_pix_idx = pix; \ - tmp_count = ((tmp_count) + 1) & (HASH_CHAIN_SIZE - 1); \ - dict->htab_counter[hval] = tmp_count; \ -} -#else -#define UPDATE_HASH(dict, hval, seg, pix) { \ - (dict)->htab[hval].image_seg_idx = seg; \ - (dict)->htab[hval].ref_pix_idx = pix; \ -} -#endif - -/* checks if the reference segment is located in the range of the window - of the current encoder */ -#define REF_SEG_IS_VALID(dict, enc_id, ref_seg, src_seg) ( \ - ((ref_seg) == (src_seg)) || \ - ((ref_seg)->image && \ - (ref_seg)->image->is_alive && \ - (src_seg->image->type == ref_seg->image->type) && \ - (ref_seg->pixels_so_far <= src_seg->pixels_so_far) && \ - ((dict)->window.segs[ \ - (dict)->window.encoders_heads[enc_id]].pixels_so_far <= \ - ref_seg->pixels_so_far))) - -#endif // _H_GLZ_ENCODER_DICTIONARY_PROTECTED diff --git a/server/migration_protocol.h b/server/migration_protocol.h index fa17c7c4..ad4cca3f 100644 --- a/server/migration_protocol.h +++ b/server/migration_protocol.h @@ -19,7 +19,7 @@ #define _H_MIGRATION_PROTOCOL #include <spice/vd_agent.h> -#include "glz_encoder_dictionary.h" +#include "common/glz_encoder_dictionary.h" /* ************************************************ * src-server to dst-server migration data messages diff --git a/server/red_memslots.c b/server/red_memslots.c index 1b3ec622..841ea4c0 100644 --- a/server/red_memslots.c +++ b/server/red_memslots.c @@ -118,6 +118,18 @@ unsigned long get_virt(RedMemSlotInfo *info, QXLPHYSICAL addr, uint32_t add_size *error = 1; return 0; } + { + static int memset_test = -1; + uint8_t *start = (uint8_t *)h_virt; + + if (memset_test == -1) { + memset_test = (getenv("SPICE_GET_VIRT_MEMSET") != NULL); + } + + if (memset_test > 0) { + memmove(start, start, add_size); + } + } return h_virt; } diff --git a/server/red_worker.c b/server/red_worker.c index 619f7bcc..8c6dd411 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -66,8 +66,8 @@ #include "red_worker.h" #include "reds_stream.h" #include "reds_sw_canvas.h" -#include "glz_encoder_dictionary.h" -#include "glz_encoder.h" +#include "common/glz_encoder_dictionary.h" +#include "common/glz_encoder.h" #include "stat.h" #include "reds.h" #include "mjpeg_encoder.h" diff --git a/spice-common b/spice-common -Subproject b3a00f4411962e0c06c7ad89a9936df388aa002 +Subproject 4edc6c0daa0f967445982945d351eab61c68b08 |