aboutsummaryrefslogtreecommitdiff
path: root/ui/vnc-enc-tight.c
diff options
context:
space:
mode:
Diffstat (limited to 'ui/vnc-enc-tight.c')
-rw-r--r--ui/vnc-enc-tight.c476
1 files changed, 254 insertions, 222 deletions
diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 41f559e..9dfe6ae 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -72,8 +72,8 @@ static const struct {
};
-static int tight_send_framebuffer_update(VncState *vs, int x, int y,
- int w, int h);
+static int tight_send_framebuffer_update(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h);
#ifdef CONFIG_VNC_JPEG
static const struct {
@@ -111,12 +111,12 @@ static const struct {
{ 9, PNG_ALL_FILTERS },
};
-static int send_png_rect(VncState *vs, int x, int y, int w, int h,
- VncPalette *palette);
+static int send_png_rect(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h, VncPalette *palette);
-static bool tight_can_send_png_rect(VncState *vs, int w, int h)
+static bool tight_can_send_png_rect(VncState *vs, VncTight *tight, int w, int h)
{
- if (vs->tight->type != VNC_ENCODING_TIGHT_PNG) {
+ if (tight->type != VNC_ENCODING_TIGHT_PNG) {
return false;
}
@@ -135,7 +135,7 @@ static bool tight_can_send_png_rect(VncState *vs, int w, int h)
*/
static unsigned int
-tight_detect_smooth_image24(VncState *vs, int w, int h)
+tight_detect_smooth_image24(VncState *vs, VncTight *tight, int w, int h)
{
int off;
int x, y, d, dx;
@@ -144,13 +144,13 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
int pixels = 0;
int pix, left[3];
unsigned int errors;
- unsigned char *buf = vs->tight->tight.buffer;
+ unsigned char *buf = tight->tight.buffer;
/*
* If client is big-endian, color samples begin from the second
* byte (offset 1) of a 32-bit pixel value.
*/
- off = vs->client_be;
+ off = vs->client_endian == G_BIG_ENDIAN ? 1 : 0;
memset(stats, 0, sizeof (stats));
@@ -205,7 +205,8 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
#define DEFINE_DETECT_FUNCTION(bpp) \
\
static unsigned int \
- tight_detect_smooth_image##bpp(VncState *vs, int w, int h) { \
+ tight_detect_smooth_image##bpp(VncState *vs, VncTight *tight, \
+ int w, int h) { \
bool endian; \
uint##bpp##_t pix; \
int max[3], shift[3]; \
@@ -215,7 +216,7 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
int pixels = 0; \
int sample, sum, left[3]; \
unsigned int errors; \
- unsigned char *buf = vs->tight->tight.buffer; \
+ unsigned char *buf = tight->tight.buffer; \
\
endian = 0; /* FIXME */ \
\
@@ -293,11 +294,11 @@ DEFINE_DETECT_FUNCTION(16)
DEFINE_DETECT_FUNCTION(32)
static int
-tight_detect_smooth_image(VncState *vs, int w, int h)
+tight_detect_smooth_image(VncState *vs, VncTight *tight, int w, int h)
{
unsigned int errors;
- int compression = vs->tight->compression;
- int quality = vs->tight->quality;
+ int compression = tight->compression;
+ int quality = tight->quality;
if (!vs->vd->lossy) {
return 0;
@@ -309,7 +310,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h)
return 0;
}
- if (vs->tight->quality != (uint8_t)-1) {
+ if (tight->quality != (uint8_t)-1) {
if (w * h < VNC_TIGHT_JPEG_MIN_RECT_SIZE) {
return 0;
}
@@ -320,17 +321,17 @@ tight_detect_smooth_image(VncState *vs, int w, int h)
}
if (vs->client_pf.bytes_per_pixel == 4) {
- if (vs->tight->pixel24) {
- errors = tight_detect_smooth_image24(vs, w, h);
- if (vs->tight->quality != (uint8_t)-1) {
+ if (tight->pixel24) {
+ errors = tight_detect_smooth_image24(vs, tight, w, h);
+ if (tight->quality != (uint8_t)-1) {
return (errors < tight_conf[quality].jpeg_threshold24);
}
return (errors < tight_conf[compression].gradient_threshold24);
} else {
- errors = tight_detect_smooth_image32(vs, w, h);
+ errors = tight_detect_smooth_image32(vs, tight, w, h);
}
} else {
- errors = tight_detect_smooth_image16(vs, w, h);
+ errors = tight_detect_smooth_image16(vs, tight, w, h);
}
if (quality != (uint8_t)-1) {
return (errors < tight_conf[quality].jpeg_threshold);
@@ -344,15 +345,15 @@ tight_detect_smooth_image(VncState *vs, int w, int h)
#define DEFINE_FILL_PALETTE_FUNCTION(bpp) \
\
static int \
- tight_fill_palette##bpp(VncState *vs, int x, int y, \
- int max, size_t count, \
+ tight_fill_palette##bpp(VncState *vs, VncTight *tight, \
+ int x, int y, int max, size_t count, \
uint32_t *bg, uint32_t *fg, \
VncPalette *palette) { \
uint##bpp##_t *data; \
uint##bpp##_t c0, c1, ci; \
int i, n0, n1; \
\
- data = (uint##bpp##_t *)vs->tight->tight.buffer; \
+ data = (uint##bpp##_t *)tight->tight.buffer; \
\
c0 = data[0]; \
i = 1; \
@@ -417,15 +418,15 @@ DEFINE_FILL_PALETTE_FUNCTION(8)
DEFINE_FILL_PALETTE_FUNCTION(16)
DEFINE_FILL_PALETTE_FUNCTION(32)
-static int tight_fill_palette(VncState *vs, int x, int y,
+static int tight_fill_palette(VncState *vs, VncTight *tight, int x, int y,
size_t count, uint32_t *bg, uint32_t *fg,
VncPalette *palette)
{
int max;
- max = count / tight_conf[vs->tight->compression].idx_max_colors_divisor;
+ max = count / tight_conf[tight->compression].idx_max_colors_divisor;
if (max < 2 &&
- count >= tight_conf[vs->tight->compression].mono_min_rect_size) {
+ count >= tight_conf[tight->compression].mono_min_rect_size) {
max = 2;
}
if (max >= 256) {
@@ -434,12 +435,15 @@ static int tight_fill_palette(VncState *vs, int x, int y,
switch (vs->client_pf.bytes_per_pixel) {
case 4:
- return tight_fill_palette32(vs, x, y, max, count, bg, fg, palette);
+ return tight_fill_palette32(vs, tight, x, y, max, count, bg, fg,
+ palette);
case 2:
- return tight_fill_palette16(vs, x, y, max, count, bg, fg, palette);
+ return tight_fill_palette16(vs, tight, x, y, max, count, bg, fg,
+ palette);
default:
max = 2;
- return tight_fill_palette8(vs, x, y, max, count, bg, fg, palette);
+ return tight_fill_palette8(vs, tight, x, y, max, count, bg, fg,
+ palette);
}
return 0;
}
@@ -547,7 +551,8 @@ DEFINE_MONO_ENCODE_FUNCTION(32)
*/
static void
-tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h)
+tight_filter_gradient24(VncState *vs, VncTight *tight, uint8_t *buf,
+ int w, int h)
{
uint32_t *buf32;
uint32_t pix32;
@@ -558,7 +563,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h)
int x, y, c;
buf32 = (uint32_t *)buf;
- memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int));
+ memset(tight->gradient.buffer, 0, w * 3 * sizeof(int));
if (1 /* FIXME */) {
shift[0] = vs->client_pf.rshift;
@@ -575,7 +580,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h)
upper[c] = 0;
here[c] = 0;
}
- prev = (int *)vs->tight->gradient.buffer;
+ prev = (int *)tight->gradient.buffer;
for (x = 0; x < w; x++) {
pix32 = *buf32++;
for (c = 0; c < 3; c++) {
@@ -605,8 +610,8 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h)
#define DEFINE_GRADIENT_FILTER_FUNCTION(bpp) \
\
static void \
- tight_filter_gradient##bpp(VncState *vs, uint##bpp##_t *buf, \
- int w, int h) { \
+ tight_filter_gradient##bpp(VncState *vs, VncTight *tight, \
+ uint##bpp##_t *buf, int w, int h) { \
uint##bpp##_t pix, diff; \
bool endian; \
int *prev; \
@@ -615,7 +620,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h)
int prediction; \
int x, y, c; \
\
- memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int)); \
+ memset(tight->gradient.buffer, 0, w * 3 * sizeof(int)); \
\
endian = 0; /* FIXME */ \
\
@@ -631,7 +636,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h)
upper[c] = 0; \
here[c] = 0; \
} \
- prev = (int *)vs->tight->gradient.buffer; \
+ prev = (int *)tight->gradient.buffer; \
for (x = 0; x < w; x++) { \
pix = *buf; \
if (endian) { \
@@ -782,10 +787,10 @@ static void extend_solid_area(VncState *vs, int x, int y, int w, int h,
*w_ptr += cx - (*x_ptr + *w_ptr);
}
-static int tight_init_stream(VncState *vs, int stream_id,
+static int tight_init_stream(VncState *vs, VncTight *tight, int stream_id,
int level, int strategy)
{
- z_streamp zstream = &vs->tight->stream[stream_id];
+ z_streamp zstream = &tight->stream[stream_id];
if (zstream->opaque == NULL) {
int err;
@@ -803,15 +808,15 @@ static int tight_init_stream(VncState *vs, int stream_id,
return -1;
}
- vs->tight->levels[stream_id] = level;
+ tight->levels[stream_id] = level;
zstream->opaque = vs;
}
- if (vs->tight->levels[stream_id] != level) {
+ if (tight->levels[stream_id] != level) {
if (deflateParams(zstream, level, strategy) != Z_OK) {
return -1;
}
- vs->tight->levels[stream_id] = level;
+ tight->levels[stream_id] = level;
}
return 0;
}
@@ -836,29 +841,29 @@ static void tight_send_compact_size(VncState *vs, size_t len)
}
}
-static int tight_compress_data(VncState *vs, int stream_id, size_t bytes,
- int level, int strategy)
+static int tight_compress_data(VncState *vs, VncTight *tight, int stream_id,
+ size_t bytes, int level, int strategy)
{
- z_streamp zstream = &vs->tight->stream[stream_id];
+ z_streamp zstream = &tight->stream[stream_id];
int previous_out;
if (bytes < VNC_TIGHT_MIN_TO_COMPRESS) {
- vnc_write(vs, vs->tight->tight.buffer, vs->tight->tight.offset);
+ vnc_write(vs, tight->tight.buffer, tight->tight.offset);
return bytes;
}
- if (tight_init_stream(vs, stream_id, level, strategy)) {
+ if (tight_init_stream(vs, tight, stream_id, level, strategy)) {
return -1;
}
/* reserve memory in output buffer */
- buffer_reserve(&vs->tight->zlib, bytes + 64);
+ buffer_reserve(&tight->zlib, bytes + 64);
/* set pointers */
- zstream->next_in = vs->tight->tight.buffer;
- zstream->avail_in = vs->tight->tight.offset;
- zstream->next_out = vs->tight->zlib.buffer + vs->tight->zlib.offset;
- zstream->avail_out = vs->tight->zlib.capacity - vs->tight->zlib.offset;
+ zstream->next_in = tight->tight.buffer;
+ zstream->avail_in = tight->tight.offset;
+ zstream->next_out = tight->zlib.buffer + tight->zlib.offset;
+ zstream->avail_out = tight->zlib.capacity - tight->zlib.offset;
previous_out = zstream->avail_out;
zstream->data_type = Z_BINARY;
@@ -868,14 +873,14 @@ static int tight_compress_data(VncState *vs, int stream_id, size_t bytes,
return -1;
}
- vs->tight->zlib.offset = vs->tight->zlib.capacity - zstream->avail_out;
+ tight->zlib.offset = tight->zlib.capacity - zstream->avail_out;
/* ...how much data has actually been produced by deflate() */
bytes = previous_out - zstream->avail_out;
tight_send_compact_size(vs, bytes);
- vnc_write(vs, vs->tight->zlib.buffer, bytes);
+ vnc_write(vs, tight->zlib.buffer, bytes);
- buffer_reset(&vs->tight->zlib);
+ buffer_reset(&tight->zlib);
return bytes;
}
@@ -891,7 +896,7 @@ static void tight_pack24(VncState *vs, uint8_t *buf, size_t count, size_t *ret)
buf8 = buf;
- if (1 /* FIXME */) {
+ if (vs->client_endian == G_BYTE_ORDER) {
rshift = vs->client_pf.rshift;
gshift = vs->client_pf.gshift;
bshift = vs->client_pf.bshift;
@@ -914,67 +919,69 @@ static void tight_pack24(VncState *vs, uint8_t *buf, size_t count, size_t *ret)
}
}
-static int send_full_color_rect(VncState *vs, int x, int y, int w, int h)
+static int send_full_color_rect(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h)
{
+ VncTight *tight = &worker->tight;
+ int level = tight_conf[tight->compression].raw_zlib_level;
int stream = 0;
ssize_t bytes;
#ifdef CONFIG_PNG
- if (tight_can_send_png_rect(vs, w, h)) {
- return send_png_rect(vs, x, y, w, h, NULL);
+ if (tight_can_send_png_rect(vs, tight, w, h)) {
+ return send_png_rect(vs, worker, x, y, w, h, NULL);
}
#endif
vnc_write_u8(vs, stream << 4); /* no flushing, no filter */
- if (vs->tight->pixel24) {
- tight_pack24(vs, vs->tight->tight.buffer, w * h,
- &vs->tight->tight.offset);
+ if (tight->pixel24) {
+ tight_pack24(vs, tight->tight.buffer, w * h, &tight->tight.offset);
bytes = 3;
} else {
bytes = vs->client_pf.bytes_per_pixel;
}
- bytes = tight_compress_data(vs, stream, w * h * bytes,
- tight_conf[vs->tight->compression].raw_zlib_level,
+ bytes = tight_compress_data(vs, tight, stream, w * h * bytes, level,
Z_DEFAULT_STRATEGY);
return (bytes >= 0);
}
-static int send_solid_rect(VncState *vs)
+static int send_solid_rect(VncState *vs, VncWorker *worker)
{
+ VncTight *tight = &worker->tight;
size_t bytes;
vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */
- if (vs->tight->pixel24) {
- tight_pack24(vs, vs->tight->tight.buffer, 1, &vs->tight->tight.offset);
+ if (tight->pixel24) {
+ tight_pack24(vs, tight->tight.buffer, 1, &tight->tight.offset);
bytes = 3;
} else {
bytes = vs->client_pf.bytes_per_pixel;
}
- vnc_write(vs, vs->tight->tight.buffer, bytes);
+ vnc_write(vs, tight->tight.buffer, bytes);
return 1;
}
-static int send_mono_rect(VncState *vs, int x, int y,
+static int send_mono_rect(VncState *vs, VncWorker *worker, int x, int y,
int w, int h, uint32_t bg, uint32_t fg)
{
ssize_t bytes;
int stream = 1;
- int level = tight_conf[vs->tight->compression].mono_zlib_level;
+ int level = tight_conf[worker->tight.compression].mono_zlib_level;
#ifdef CONFIG_PNG
- if (tight_can_send_png_rect(vs, w, h)) {
+ if (tight_can_send_png_rect(vs, &worker->tight, w, h)) {
int ret;
int bpp = vs->client_pf.bytes_per_pixel * 8;
VncPalette *palette = palette_new(2, bpp);
palette_put(palette, bg);
palette_put(palette, fg);
- ret = send_png_rect(vs, x, y, w, h, palette);
+ ret = send_png_rect(vs, worker, x, y, w, h, palette);
palette_destroy(palette);
return ret;
}
@@ -992,33 +999,43 @@ static int send_mono_rect(VncState *vs, int x, int y,
uint32_t buf[2] = {bg, fg};
size_t ret = sizeof (buf);
- if (vs->tight->pixel24) {
+ if (worker->tight.pixel24) {
tight_pack24(vs, (unsigned char*)buf, 2, &ret);
}
vnc_write(vs, buf, ret);
- tight_encode_mono_rect32(vs->tight->tight.buffer, w, h, bg, fg);
+ tight_encode_mono_rect32(worker->tight.tight.buffer, w, h, bg, fg);
break;
}
case 2:
- vnc_write(vs, &bg, 2);
- vnc_write(vs, &fg, 2);
- tight_encode_mono_rect16(vs->tight->tight.buffer, w, h, bg, fg);
+ {
+ uint16_t bg16 = bg;
+ uint16_t fg16 = fg;
+ vnc_write(vs, &bg16, 2);
+ vnc_write(vs, &fg16, 2);
+ tight_encode_mono_rect16(worker->tight.tight.buffer, w, h, bg, fg);
break;
+ }
default:
- vnc_write_u8(vs, bg);
- vnc_write_u8(vs, fg);
- tight_encode_mono_rect8(vs->tight->tight.buffer, w, h, bg, fg);
+ {
+ uint8_t bg8 = bg;
+ uint8_t fg8 = fg;
+ vnc_write_u8(vs, bg8);
+ vnc_write_u8(vs, fg8);
+ tight_encode_mono_rect8(worker->tight.tight.buffer, w, h, bg, fg);
break;
}
- vs->tight->tight.offset = bytes;
+ }
+ worker->tight.tight.offset = bytes;
- bytes = tight_compress_data(vs, stream, bytes, level, Z_DEFAULT_STRATEGY);
+ bytes = tight_compress_data(vs, &worker->tight, stream, bytes, level,
+ Z_DEFAULT_STRATEGY);
return (bytes >= 0);
}
struct palette_cb_priv {
VncState *vs;
+ VncTight *tight;
uint8_t *header;
#ifdef CONFIG_PNG
png_colorp png_palette;
@@ -1038,53 +1055,58 @@ static void write_palette(int idx, uint32_t color, void *opaque)
}
}
-static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h)
+static bool send_gradient_rect(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h)
{
+ VncTight *tight = &worker->tight;
int stream = 3;
- int level = tight_conf[vs->tight->compression].gradient_zlib_level;
+ int level = tight_conf[tight->compression].gradient_zlib_level;
ssize_t bytes;
if (vs->client_pf.bytes_per_pixel == 1) {
- return send_full_color_rect(vs, x, y, w, h);
+ return send_full_color_rect(vs, worker, x, y, w, h);
}
vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4);
vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT);
- buffer_reserve(&vs->tight->gradient, w * 3 * sizeof(int));
+ buffer_reserve(&tight->gradient, w * 3 * sizeof(int));
- if (vs->tight->pixel24) {
- tight_filter_gradient24(vs, vs->tight->tight.buffer, w, h);
+ if (tight->pixel24) {
+ tight_filter_gradient24(vs, tight, tight->tight.buffer, w, h);
bytes = 3;
} else if (vs->client_pf.bytes_per_pixel == 4) {
- tight_filter_gradient32(vs, (uint32_t *)vs->tight->tight.buffer, w, h);
+ tight_filter_gradient32(vs, tight, (uint32_t *)tight->tight.buffer,
+ w, h);
bytes = 4;
} else {
- tight_filter_gradient16(vs, (uint16_t *)vs->tight->tight.buffer, w, h);
+ tight_filter_gradient16(vs, tight, (uint16_t *)tight->tight.buffer,
+ w, h);
bytes = 2;
}
- buffer_reset(&vs->tight->gradient);
+ buffer_reset(&tight->gradient);
bytes = w * h * bytes;
- vs->tight->tight.offset = bytes;
+ tight->tight.offset = bytes;
- bytes = tight_compress_data(vs, stream, bytes,
+ bytes = tight_compress_data(vs, tight, stream, bytes,
level, Z_FILTERED);
return (bytes >= 0);
}
-static int send_palette_rect(VncState *vs, int x, int y,
+static int send_palette_rect(VncState *vs, VncWorker *worker, int x, int y,
int w, int h, VncPalette *palette)
{
+ VncTight *tight = &worker->tight;
int stream = 2;
- int level = tight_conf[vs->tight->compression].idx_zlib_level;
+ int level = tight_conf[tight->compression].idx_zlib_level;
int colors;
ssize_t bytes;
#ifdef CONFIG_PNG
- if (tight_can_send_png_rect(vs, w, h)) {
- return send_png_rect(vs, x, y, w, h, palette);
+ if (tight_can_send_png_rect(vs, tight, w, h)) {
+ return send_png_rect(vs, worker, x, y, w, h, palette);
}
#endif
@@ -1099,38 +1121,38 @@ static int send_palette_rect(VncState *vs, int x, int y,
{
size_t old_offset, offset, palette_sz = palette_size(palette);
g_autofree uint32_t *header = g_new(uint32_t, palette_sz);
- struct palette_cb_priv priv = { vs, (uint8_t *)header };
+ struct palette_cb_priv priv = { vs, tight, (uint8_t *)header };
old_offset = vs->output.offset;
palette_iter(palette, write_palette, &priv);
vnc_write(vs, header, palette_sz * sizeof(uint32_t));
- if (vs->tight->pixel24) {
+ if (tight->pixel24) {
tight_pack24(vs, vs->output.buffer + old_offset, colors, &offset);
vs->output.offset = old_offset + offset;
}
- tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h, palette);
+ tight_encode_indexed_rect32(tight->tight.buffer, w * h, palette);
break;
}
case 2:
{
size_t palette_sz = palette_size(palette);
g_autofree uint16_t *header = g_new(uint16_t, palette_sz);
- struct palette_cb_priv priv = { vs, (uint8_t *)header };
+ struct palette_cb_priv priv = { vs, tight, (uint8_t *)header };
palette_iter(palette, write_palette, &priv);
vnc_write(vs, header, palette_sz * sizeof(uint16_t));
- tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, palette);
+ tight_encode_indexed_rect16(tight->tight.buffer, w * h, palette);
break;
}
default:
return -1; /* No palette for 8bits colors */
}
bytes = w * h;
- vs->tight->tight.offset = bytes;
+ tight->tight.offset = bytes;
- bytes = tight_compress_data(vs, stream, bytes,
+ bytes = tight_compress_data(vs, tight, stream, bytes,
level, Z_DEFAULT_STRATEGY);
return (bytes >= 0);
}
@@ -1146,8 +1168,8 @@ static int send_palette_rect(VncState *vs, int x, int y,
/* This is called once per encoding */
static void jpeg_init_destination(j_compress_ptr cinfo)
{
- VncState *vs = cinfo->client_data;
- Buffer *buffer = &vs->tight->jpeg;
+ VncTight *tight = cinfo->client_data;
+ Buffer *buffer = &tight->jpeg;
cinfo->dest->next_output_byte = (JOCTET *)buffer->buffer + buffer->offset;
cinfo->dest->free_in_buffer = (size_t)(buffer->capacity - buffer->offset);
@@ -1156,8 +1178,8 @@ static void jpeg_init_destination(j_compress_ptr cinfo)
/* This is called when we ran out of buffer (shouldn't happen!) */
static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo)
{
- VncState *vs = cinfo->client_data;
- Buffer *buffer = &vs->tight->jpeg;
+ VncTight *tight = cinfo->client_data;
+ Buffer *buffer = &tight->jpeg;
buffer->offset = buffer->capacity;
buffer_reserve(buffer, 2048);
@@ -1168,13 +1190,14 @@ static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo)
/* This is called when we are done processing data */
static void jpeg_term_destination(j_compress_ptr cinfo)
{
- VncState *vs = cinfo->client_data;
- Buffer *buffer = &vs->tight->jpeg;
+ VncTight *tight = cinfo->client_data;
+ Buffer *buffer = &tight->jpeg;
buffer->offset = buffer->capacity - cinfo->dest->free_in_buffer;
}
-static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality)
+static int send_jpeg_rect(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h, int quality)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
@@ -1185,15 +1208,15 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality)
int dy;
if (surface_bytes_per_pixel(vs->vd->ds) == 1) {
- return send_full_color_rect(vs, x, y, w, h);
+ return send_full_color_rect(vs, worker, x, y, w, h);
}
- buffer_reserve(&vs->tight->jpeg, 2048);
+ buffer_reserve(&worker->tight.jpeg, 2048);
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
- cinfo.client_data = vs;
+ cinfo.client_data = &worker->tight;
cinfo.image_width = w;
cinfo.image_height = h;
cinfo.input_components = 3;
@@ -1223,9 +1246,9 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality)
vnc_write_u8(vs, VNC_TIGHT_JPEG << 4);
- tight_send_compact_size(vs, vs->tight->jpeg.offset);
- vnc_write(vs, vs->tight->jpeg.buffer, vs->tight->jpeg.offset);
- buffer_reset(&vs->tight->jpeg);
+ tight_send_compact_size(vs, worker->tight.jpeg.offset);
+ vnc_write(vs, worker->tight.jpeg.buffer, worker->tight.jpeg.offset);
+ buffer_reset(&worker->tight.jpeg);
return 1;
}
@@ -1241,7 +1264,7 @@ static void write_png_palette(int idx, uint32_t pix, void *opaque)
VncState *vs = priv->vs;
png_colorp color = &priv->png_palette[idx];
- if (vs->tight->pixel24)
+ if (priv->tight->pixel24)
{
color->red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax;
color->green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax;
@@ -1266,12 +1289,12 @@ static void write_png_palette(int idx, uint32_t pix, void *opaque)
static void png_write_data(png_structp png_ptr, png_bytep data,
png_size_t length)
{
- VncState *vs = png_get_io_ptr(png_ptr);
+ VncWorker *worker = png_get_io_ptr(png_ptr);
- buffer_reserve(&vs->tight->png, vs->tight->png.offset + length);
- memcpy(vs->tight->png.buffer + vs->tight->png.offset, data, length);
+ buffer_reserve(&worker->tight.png, worker->tight.png.offset + length);
+ memcpy(worker->tight.png.buffer + worker->tight.png.offset, data, length);
- vs->tight->png.offset += length;
+ worker->tight.png.offset += length;
}
static void png_flush_data(png_structp png_ptr)
@@ -1288,16 +1311,16 @@ static void vnc_png_free(png_structp png_ptr, png_voidp ptr)
g_free(ptr);
}
-static int send_png_rect(VncState *vs, int x, int y, int w, int h,
- VncPalette *palette)
+static int send_png_rect(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h, VncPalette *palette)
{
png_byte color_type;
png_structp png_ptr;
png_infop info_ptr;
png_colorp png_palette = NULL;
pixman_image_t *linebuf;
- int level = tight_png_conf[vs->tight->compression].png_zlib_level;
- int filters = tight_png_conf[vs->tight->compression].png_filters;
+ int level = tight_png_conf[worker->tight.compression].png_zlib_level;
+ int filters = tight_png_conf[worker->tight.compression].png_filters;
uint8_t *buf;
int dy;
@@ -1314,7 +1337,7 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h,
return -1;
}
- png_set_write_fn(png_ptr, (void *) vs, png_write_data, png_flush_data);
+ png_set_write_fn(png_ptr, worker, png_write_data, png_flush_data);
png_set_compression_level(png_ptr, level);
png_set_filter(png_ptr, PNG_FILTER_TYPE_DEFAULT, filters);
@@ -1335,29 +1358,30 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h,
palette_size(palette));
priv.vs = vs;
+ priv.tight = &worker->tight;
priv.png_palette = png_palette;
palette_iter(palette, write_png_palette, &priv);
png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette));
if (vs->client_pf.bytes_per_pixel == 4) {
- tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h,
+ tight_encode_indexed_rect32(worker->tight.tight.buffer, w * h,
palette);
} else {
- tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h,
+ tight_encode_indexed_rect16(worker->tight.tight.buffer, w * h,
palette);
}
}
png_write_info(png_ptr, info_ptr);
- buffer_reserve(&vs->tight->png, 2048);
+ buffer_reserve(&worker->tight.png, 2048);
linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w);
buf = (uint8_t *)pixman_image_get_data(linebuf);
for (dy = 0; dy < h; dy++)
{
if (color_type == PNG_COLOR_TYPE_PALETTE) {
- memcpy(buf, vs->tight->tight.buffer + (dy * w), w);
+ memcpy(buf, worker->tight.tight.buffer + (dy * w), w);
} else {
qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, x, y + dy);
}
@@ -1375,46 +1399,47 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h,
vnc_write_u8(vs, VNC_TIGHT_PNG << 4);
- tight_send_compact_size(vs, vs->tight->png.offset);
- vnc_write(vs, vs->tight->png.buffer, vs->tight->png.offset);
- buffer_reset(&vs->tight->png);
+ tight_send_compact_size(vs, worker->tight.png.offset);
+ vnc_write(vs, worker->tight.png.buffer, worker->tight.png.offset);
+ buffer_reset(&worker->tight.png);
return 1;
}
#endif /* CONFIG_PNG */
-static void vnc_tight_start(VncState *vs)
+static void vnc_tight_start(VncState *vs, VncTight *tight)
{
- buffer_reset(&vs->tight->tight);
+ buffer_reset(&tight->tight);
// make the output buffer be the zlib buffer, so we can compress it later
- vs->tight->tmp = vs->output;
- vs->output = vs->tight->tight;
+ tight->tmp = vs->output;
+ vs->output = tight->tight;
}
-static void vnc_tight_stop(VncState *vs)
+static void vnc_tight_stop(VncState *vs, VncTight *tight)
{
// switch back to normal output/zlib buffers
- vs->tight->tight = vs->output;
- vs->output = vs->tight->tmp;
+ tight->tight = vs->output;
+ vs->output = tight->tmp;
}
-static int send_sub_rect_nojpeg(VncState *vs, int x, int y, int w, int h,
+static int send_sub_rect_nojpeg(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h,
int bg, int fg, int colors, VncPalette *palette)
{
int ret;
if (colors == 0) {
- if (tight_detect_smooth_image(vs, w, h)) {
- ret = send_gradient_rect(vs, x, y, w, h);
+ if (tight_detect_smooth_image(vs, &worker->tight, w, h)) {
+ ret = send_gradient_rect(vs, worker, x, y, w, h);
} else {
- ret = send_full_color_rect(vs, x, y, w, h);
+ ret = send_full_color_rect(vs, worker, x, y, w, h);
}
} else if (colors == 1) {
- ret = send_solid_rect(vs);
+ ret = send_solid_rect(vs, worker);
} else if (colors == 2) {
- ret = send_mono_rect(vs, x, y, w, h, bg, fg);
+ ret = send_mono_rect(vs, worker, x, y, w, h, bg, fg);
} else if (colors <= 256) {
- ret = send_palette_rect(vs, x, y, w, h, palette);
+ ret = send_palette_rect(vs, worker, x, y, w, h, palette);
} else {
ret = 0;
}
@@ -1422,34 +1447,35 @@ static int send_sub_rect_nojpeg(VncState *vs, int x, int y, int w, int h,
}
#ifdef CONFIG_VNC_JPEG
-static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h,
+static int send_sub_rect_jpeg(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h,
int bg, int fg, int colors,
VncPalette *palette, bool force)
{
int ret;
if (colors == 0) {
- if (force || (tight_jpeg_conf[vs->tight->quality].jpeg_full &&
- tight_detect_smooth_image(vs, w, h))) {
- int quality = tight_conf[vs->tight->quality].jpeg_quality;
+ if (force || (tight_jpeg_conf[worker->tight.quality].jpeg_full &&
+ tight_detect_smooth_image(vs, &worker->tight, w, h))) {
+ int quality = tight_conf[worker->tight.quality].jpeg_quality;
- ret = send_jpeg_rect(vs, x, y, w, h, quality);
+ ret = send_jpeg_rect(vs, worker, x, y, w, h, quality);
} else {
- ret = send_full_color_rect(vs, x, y, w, h);
+ ret = send_full_color_rect(vs, worker, x, y, w, h);
}
} else if (colors == 1) {
- ret = send_solid_rect(vs);
+ ret = send_solid_rect(vs, worker);
} else if (colors == 2) {
- ret = send_mono_rect(vs, x, y, w, h, bg, fg);
+ ret = send_mono_rect(vs, worker, x, y, w, h, bg, fg);
} else if (colors <= 256) {
if (force || (colors > 96 &&
- tight_jpeg_conf[vs->tight->quality].jpeg_idx &&
- tight_detect_smooth_image(vs, w, h))) {
- int quality = tight_conf[vs->tight->quality].jpeg_quality;
+ tight_jpeg_conf[worker->tight.quality].jpeg_idx &&
+ tight_detect_smooth_image(vs, &worker->tight, w, h))) {
+ int quality = tight_conf[worker->tight.quality].jpeg_quality;
- ret = send_jpeg_rect(vs, x, y, w, h, quality);
+ ret = send_jpeg_rect(vs, worker, x, y, w, h, quality);
} else {
- ret = send_palette_rect(vs, x, y, w, h, palette);
+ ret = send_palette_rect(vs, worker, x, y, w, h, palette);
}
} else {
ret = 0;
@@ -1467,8 +1493,10 @@ static void vnc_tight_cleanup(Notifier *n, void *value)
color_count_palette = NULL;
}
-static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
+static int send_sub_rect(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h)
{
+ VncTight *tight = &worker->tight;
uint32_t bg = 0, fg = 0;
int colors;
int ret = 0;
@@ -1483,57 +1511,59 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
qemu_thread_atexit_add(&vnc_tight_cleanup_notifier);
}
- vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type);
+ vnc_framebuffer_update(vs, x, y, w, h, tight->type);
- vnc_tight_start(vs);
+ vnc_tight_start(vs, tight);
vnc_raw_send_framebuffer_update(vs, x, y, w, h);
- vnc_tight_stop(vs);
+ vnc_tight_stop(vs, tight);
#ifdef CONFIG_VNC_JPEG
- if (!vs->vd->non_adaptive && vs->tight->quality != (uint8_t)-1) {
+ if (!vs->vd->non_adaptive && tight->quality != (uint8_t)-1) {
double freq = vnc_update_freq(vs, x, y, w, h);
- if (freq < tight_jpeg_conf[vs->tight->quality].jpeg_freq_min) {
+ if (freq < tight_jpeg_conf[tight->quality].jpeg_freq_min) {
allow_jpeg = false;
}
- if (freq >= tight_jpeg_conf[vs->tight->quality].jpeg_freq_threshold) {
+ if (freq >= tight_jpeg_conf[tight->quality].jpeg_freq_threshold) {
force_jpeg = true;
- vnc_sent_lossy_rect(vs, x, y, w, h);
+ vnc_sent_lossy_rect(worker, x, y, w, h);
}
}
#endif
- colors = tight_fill_palette(vs, x, y, w * h, &bg, &fg, color_count_palette);
+ colors = tight_fill_palette(vs, tight, x, y, w * h, &bg, &fg,
+ color_count_palette);
#ifdef CONFIG_VNC_JPEG
- if (allow_jpeg && vs->tight->quality != (uint8_t)-1) {
- ret = send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors,
+ if (allow_jpeg && tight->quality != (uint8_t)-1) {
+ ret = send_sub_rect_jpeg(vs, worker, x, y, w, h, bg, fg, colors,
color_count_palette, force_jpeg);
} else {
- ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors,
- color_count_palette);
+ ret = send_sub_rect_nojpeg(vs, worker, x, y, w, h, bg, fg,
+ colors, color_count_palette);
}
#else
- ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors,
+ ret = send_sub_rect_nojpeg(vs, worker, x, y, w, h, bg, fg, colors,
color_count_palette);
#endif
return ret;
}
-static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h)
+static int send_sub_rect_solid(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h)
{
- vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type);
+ vnc_framebuffer_update(vs, x, y, w, h, worker->tight.type);
- vnc_tight_start(vs);
+ vnc_tight_start(vs, &worker->tight);
vnc_raw_send_framebuffer_update(vs, x, y, w, h);
- vnc_tight_stop(vs);
+ vnc_tight_stop(vs, &worker->tight);
- return send_solid_rect(vs);
+ return send_solid_rect(vs, worker);
}
-static int send_rect_simple(VncState *vs, int x, int y, int w, int h,
- bool split)
+static int send_rect_simple(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h, bool split)
{
int max_size, max_width;
int max_sub_width, max_sub_height;
@@ -1541,8 +1571,8 @@ static int send_rect_simple(VncState *vs, int x, int y, int w, int h,
int rw, rh;
int n = 0;
- max_size = tight_conf[vs->tight->compression].max_rect_size;
- max_width = tight_conf[vs->tight->compression].max_rect_width;
+ max_size = tight_conf[worker->tight.compression].max_rect_size;
+ max_width = tight_conf[worker->tight.compression].max_rect_width;
if (split && (w > max_width || w * h > max_size)) {
max_sub_width = (w > max_width) ? max_width : w;
@@ -1552,18 +1582,18 @@ static int send_rect_simple(VncState *vs, int x, int y, int w, int h,
for (dx = 0; dx < w; dx += max_width) {
rw = MIN(max_sub_width, w - dx);
rh = MIN(max_sub_height, h - dy);
- n += send_sub_rect(vs, x+dx, y+dy, rw, rh);
+ n += send_sub_rect(vs, worker, x + dx, y + dy, rw, rh);
}
}
} else {
- n += send_sub_rect(vs, x, y, w, h);
+ n += send_sub_rect(vs, worker, x, y, w, h);
}
return n;
}
-static int find_large_solid_color_rect(VncState *vs, int x, int y,
- int w, int h, int max_rows)
+static int find_large_solid_color_rect(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h, int max_rows)
{
int dx, dy, dw, dh;
int n = 0;
@@ -1575,7 +1605,7 @@ static int find_large_solid_color_rect(VncState *vs, int x, int y,
/* If a rectangle becomes too large, send its upper part now. */
if (dy - y >= max_rows) {
- n += send_rect_simple(vs, x, y, w, max_rows, true);
+ n += send_rect_simple(vs, worker, x, y, w, max_rows, true);
y += max_rows;
h -= max_rows;
}
@@ -1614,26 +1644,28 @@ static int find_large_solid_color_rect(VncState *vs, int x, int y,
/* Send rectangles at top and left to solid-color area. */
if (y_best != y) {
- n += send_rect_simple(vs, x, y, w, y_best-y, true);
+ n += send_rect_simple(vs, worker, x, y, w, y_best - y, true);
}
if (x_best != x) {
- n += tight_send_framebuffer_update(vs, x, y_best,
+ n += tight_send_framebuffer_update(vs, worker, x, y_best,
x_best-x, h_best);
}
/* Send solid-color rectangle. */
- n += send_sub_rect_solid(vs, x_best, y_best, w_best, h_best);
+ n += send_sub_rect_solid(vs, worker,
+ x_best, y_best, w_best, h_best);
/* Send remaining rectangles (at right and bottom). */
if (x_best + w_best != x + w) {
- n += tight_send_framebuffer_update(vs, x_best+w_best,
+ n += tight_send_framebuffer_update(vs, worker, x_best + w_best,
y_best,
w-(x_best-x)-w_best,
h_best);
}
if (y_best + h_best != y + h) {
- n += tight_send_framebuffer_update(vs, x, y_best+h_best,
+ n += tight_send_framebuffer_update(vs, worker,
+ x, y_best + h_best,
w, h-(y_best-y)-h_best);
}
@@ -1641,73 +1673,73 @@ static int find_large_solid_color_rect(VncState *vs, int x, int y,
return n;
}
}
- return n + send_rect_simple(vs, x, y, w, h, true);
+ return n + send_rect_simple(vs, worker, x, y, w, h, true);
}
-static int tight_send_framebuffer_update(VncState *vs, int x, int y,
- int w, int h)
+static int tight_send_framebuffer_update(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h)
{
int max_rows;
if (vs->client_pf.bytes_per_pixel == 4 && vs->client_pf.rmax == 0xFF &&
vs->client_pf.bmax == 0xFF && vs->client_pf.gmax == 0xFF) {
- vs->tight->pixel24 = true;
+ worker->tight.pixel24 = true;
} else {
- vs->tight->pixel24 = false;
+ worker->tight.pixel24 = false;
}
#ifdef CONFIG_VNC_JPEG
- if (vs->tight->quality != (uint8_t)-1) {
+ if (worker->tight.quality != (uint8_t)-1) {
double freq = vnc_update_freq(vs, x, y, w, h);
- if (freq > tight_jpeg_conf[vs->tight->quality].jpeg_freq_threshold) {
- return send_rect_simple(vs, x, y, w, h, false);
+ if (freq > tight_jpeg_conf[worker->tight.quality].jpeg_freq_threshold) {
+ return send_rect_simple(vs, worker, x, y, w, h, false);
}
}
#endif
if (w * h < VNC_TIGHT_MIN_SPLIT_RECT_SIZE) {
- return send_rect_simple(vs, x, y, w, h, true);
+ return send_rect_simple(vs, worker, x, y, w, h, true);
}
/* Calculate maximum number of rows in one non-solid rectangle. */
- max_rows = tight_conf[vs->tight->compression].max_rect_size;
- max_rows /= MIN(tight_conf[vs->tight->compression].max_rect_width, w);
+ max_rows = tight_conf[worker->tight.compression].max_rect_size;
+ max_rows /= MIN(tight_conf[worker->tight.compression].max_rect_width, w);
- return find_large_solid_color_rect(vs, x, y, w, h, max_rows);
+ return find_large_solid_color_rect(vs, worker, x, y, w, h, max_rows);
}
-int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y,
- int w, int h)
+int vnc_tight_send_framebuffer_update(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h)
{
- vs->tight->type = VNC_ENCODING_TIGHT;
- return tight_send_framebuffer_update(vs, x, y, w, h);
+ worker->tight.type = VNC_ENCODING_TIGHT;
+ return tight_send_framebuffer_update(vs, worker, x, y, w, h);
}
-int vnc_tight_png_send_framebuffer_update(VncState *vs, int x, int y,
- int w, int h)
+int vnc_tight_png_send_framebuffer_update(VncState *vs, VncWorker *worker,
+ int x, int y, int w, int h)
{
- vs->tight->type = VNC_ENCODING_TIGHT_PNG;
- return tight_send_framebuffer_update(vs, x, y, w, h);
+ worker->tight.type = VNC_ENCODING_TIGHT_PNG;
+ return tight_send_framebuffer_update(vs, worker, x, y, w, h);
}
-void vnc_tight_clear(VncState *vs)
+void vnc_tight_clear(VncWorker *worker)
{
int i;
- for (i = 0; i < ARRAY_SIZE(vs->tight->stream); i++) {
- if (vs->tight->stream[i].opaque) {
- deflateEnd(&vs->tight->stream[i]);
+ for (i = 0; i < ARRAY_SIZE(worker->tight.stream); i++) {
+ if (worker->tight.stream[i].opaque) {
+ deflateEnd(&worker->tight.stream[i]);
}
}
- buffer_free(&vs->tight->tight);
- buffer_free(&vs->tight->zlib);
- buffer_free(&vs->tight->gradient);
+ buffer_free(&worker->tight.tight);
+ buffer_free(&worker->tight.zlib);
+ buffer_free(&worker->tight.gradient);
#ifdef CONFIG_VNC_JPEG
- buffer_free(&vs->tight->jpeg);
+ buffer_free(&worker->tight.jpeg);
#endif
#ifdef CONFIG_PNG
- buffer_free(&vs->tight->png);
+ buffer_free(&worker->tight.png);
#endif
}