From: Anthony Liguori <aliguori@linux.vnet.ibm.com>
To: Corentin Chary <corentincj@iksaif.net>
Cc: Adam Litke <agl@us.ibm.com>,
qemu-devel@nongnu.org, Alexander Graf <agraf@suse.de>
Subject: [Qemu-devel] Re: [PATCH v2 06/10] vnc: add support for tight fill encoding
Date: Tue, 18 May 2010 08:34:58 -0500 [thread overview]
Message-ID: <4BF29782.5040401@linux.vnet.ibm.com> (raw)
In-Reply-To: <1274186986-26878-7-git-send-email-corentincj@iksaif.net>
On 05/18/2010 07:49 AM, Corentin Chary wrote:
> Fill encoding detects rectangle using only one color and send only
> one pixel value.
>
> Signed-off-by: Corentin Chary<corentincj@iksaif.net>
> ---
> vnc-encoding-tight.c | 245 +++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 244 insertions(+), 1 deletions(-)
>
> diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
> index 0d328c2..5ea90c0 100644
> --- a/vnc-encoding-tight.c
> +++ b/vnc-encoding-tight.c
> @@ -54,6 +54,135 @@ static const struct {
> { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 }
> };
>
> +/*
> + * Check if a rectangle is all of the same color. If needSameColor is
> + * set to non-zero, then also check that its color equals to the
> + * *colorPtr value. The result is 1 if the test is successfull, and in
> + * that case new color will be stored in *colorPtr.
> + */
> +
> +#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \
> + \
> + static bool \
> + check_solid_tile##bpp(VncState *vs, int x, int y, int w, int h, \
> + uint32_t* color, bool samecolor) \
> + { \
> + VncDisplay *vd = vs->vd; \
> + uint##bpp##_t *fbptr; \
> + uint##bpp##_t c; \
> + int dx, dy; \
> + \
> + fbptr = (uint##bpp##_t *) \
> + (vd->server->data + y * ds_get_linesize(vs->ds) + \
> + x * ds_get_bytes_per_pixel(vs->ds)); \
> + \
> + c = *fbptr; \
> + if (samecolor&& (uint32_t)c != *color) \
> + return false; \
> + \
> + for (dy = 0; dy< h; dy++) { \
> + for (dx = 0; dx< w; dx++) { \
> + if (c != fbptr[dx]) \
> + return false; \
> + } \
> + fbptr = (uint##bpp##_t *) \
> + ((uint8_t *)fbptr + ds_get_linesize(vs->ds)); \
> + } \
> + \
> + *color = (uint32_t)c; \
> + return true; \
> + }
> +
> +DEFINE_CHECK_SOLID_FUNCTION(32)
> +DEFINE_CHECK_SOLID_FUNCTION(16)
> +DEFINE_CHECK_SOLID_FUNCTION(8)
> +
> +static bool check_solid_tile(VncState *vs, int x, int y, int w, int h,
> + uint32_t* color, bool samecolor)
> +{
> + VncDisplay *vd = vs->vd;
> +
> + switch(vd->server->pf.bytes_per_pixel) {
> + case 4:
> + return check_solid_tile32(vs, x, y, w, h, color, samecolor);
> + case 2:
> + return check_solid_tile16(vs, x, y, w, h, color, samecolor);
> + default:
> + return check_solid_tile8(vs, x, y, w, h, color, samecolor);
> + }
> +}
> +
> +static void find_best_solid_area(VncState *vs, int x, int y, int w, int h,
> + uint32_t color, int *w_ptr, int *h_ptr)
> +{
> + int dx, dy, dw, dh;
> + int w_prev;
> + int w_best = 0, h_best = 0;
> +
> + w_prev = w;
> +
> + for (dy = y; dy< y + h; dy += VNC_TIGHT_MAX_SPLIT_TILE_SIZE) {
> +
> + dh = min(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, y + h - dy);
> + dw = min(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, w_prev);
> +
> + if (!check_solid_tile(vs, x, dy, dw, dh,&color, true))
> + break;
> +
> + for (dx = x + dw; dx< x + w_prev;) {
> + dw = min(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, x + w_prev - dx);
> +
> + if (!check_solid_tile(vs, dx, dy, dw, dh,&color, true))
> + break;
> + dx += dw;
> + }
> +
> + w_prev = dx - x;
> + if (w_prev * (dy + dh - y)> w_best * h_best) {
> + w_best = w_prev;
> + h_best = dy + dh - y;
> + }
> + }
> +
> + *w_ptr = w_best;
> + *h_ptr = h_best;
> +}
> +
> +static void extend_solid_area(VncState *vs, int x, int y, int w, int h,
> + uint32_t color, int *x_ptr, int *y_ptr,
> + int *w_ptr, int *h_ptr)
> +{
> + int cx, cy;
> +
> + /* Try to extend the area upwards. */
> + for ( cy = *y_ptr - 1;
> + cy>= y&& check_solid_tile(vs, *x_ptr, cy, *w_ptr, 1,&color, true);
> + cy-- );
> + *h_ptr += *y_ptr - (cy + 1);
> + *y_ptr = cy + 1;
>
>
Please check this file against CODING_STYLE. There are extra spaces in
the for()s and missing {}s.
Regards,
Anthony Liguori
> + /* ... downwards. */
> + for ( cy = *y_ptr + *h_ptr;
> + cy< y + h&&
> + check_solid_tile(vs, *x_ptr, cy, *w_ptr, 1,&color, true);
> + cy++ );
> + *h_ptr += cy - (*y_ptr + *h_ptr);
> +
> + /* ... to the left. */
> + for ( cx = *x_ptr - 1;
> + cx>= x&& check_solid_tile(vs, cx, *y_ptr, 1, *h_ptr,&color, true);
> + cx-- );
> + *w_ptr += *x_ptr - (cx + 1);
> + *x_ptr = cx + 1;
> +
> + /* ... to the right. */
> + for ( cx = *x_ptr + *w_ptr;
> + cx< x + w&&
> + check_solid_tile(vs, cx, *y_ptr, 1, *h_ptr,&color, true);
> + cx++ );
> + *w_ptr += cx - (*x_ptr + *w_ptr);
> +}
> +
> static int tight_init_stream(VncState *vs, int stream_id,
> int level, int strategy)
> {
> @@ -205,6 +334,23 @@ static int send_full_color_rect(VncState *vs, int w, int h)
> return (bytes>= 0);
> }
>
> +static int send_solid_rect(VncState *vs)
> +{
> + size_t bytes;
> +
> + vnc_write_u8(vs, VNC_TIGHT_FILL<< 4); /* no flushing, no filter */
> +
> + if (vs->tight_pixel24) {
> + tight_pack24(vs, 1);
> + bytes = 3;
> + } else {
> + bytes = vs->clientds.pf.bytes_per_pixel;
> + }
> +
> + vnc_write(vs, vs->tight.buffer, bytes);
> + return 1;
> +}
> +
> static void vnc_tight_start(VncState *vs)
> {
> buffer_reset(&vs->tight);
> @@ -237,6 +383,17 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
> return send_full_color_rect(vs, w, h);
> }
>
> +static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h)
> +{
> + vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_TIGHT);
> +
> + vnc_tight_start(vs);
> + vnc_raw_send_framebuffer_update(vs, x, y, w, h);
> + vnc_tight_stop(vs);
> +
> + return send_solid_rect(vs);
> +}
> +
> static int send_rect_simple(VncState *vs, int x, int y, int w, int h)
> {
> int max_size, max_width;
> @@ -266,6 +423,82 @@ static int send_rect_simple(VncState *vs, int x, int y, int w, int h)
> return n;
> }
>
> +static int find_large_solid_color_rect(VncState *vs, int x, int y,
> + int w, int h, int max_rows)
> +{
> + int dx, dy, dw, dh;
> + int n = 0;
> +
> + /* Try to find large solid-color areas and send them separately. */
> +
> + for (dy = y; dy< y + h; dy += VNC_TIGHT_MAX_SPLIT_TILE_SIZE) {
> +
> + /* 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);
> + y += max_rows;
> + h -= max_rows;
> + }
> +
> + dh = min(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, (y + h - dy));
> +
> + for (dx = x; dx< x + w; dx += VNC_TIGHT_MAX_SPLIT_TILE_SIZE) {
> + uint32_t color_value;
> + int x_best, y_best, w_best, h_best;
> +
> + dw = min(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, (x + w - dx));
> +
> + if (!check_solid_tile(vs, dx, dy, dw, dh,&color_value, false))
> + continue ;
> +
> + /* Get dimensions of solid-color area. */
> +
> + find_best_solid_area(vs, dx, dy, w - (dx - x), h - (dy - y),
> + color_value,&w_best,&h_best);
> +
> + /* Make sure a solid rectangle is large enough
> + (or the whole rectangle is of the same color). */
> +
> + if (w_best * h_best != w * h&&
> + w_best * h_best< VNC_TIGHT_MIN_SOLID_SUBRECT_SIZE)
> + continue;
> +
> + /* Try to extend solid rectangle to maximum size. */
> +
> + x_best = dx; y_best = dy;
> + extend_solid_area(vs, x, y, w, h, color_value,
> +&x_best,&y_best,&w_best,&h_best);
> +
> + /* 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);
> + if (x_best != x)
> + n += vnc_tight_send_framebuffer_update(vs, 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);
> +
> + /* Send remaining rectangles (at right and bottom). */
> +
> + if (x_best + w_best != x + w)
> + n += vnc_tight_send_framebuffer_update(vs, x_best+w_best,
> + y_best,
> + w-(x_best-x)-w_best,
> + h_best);
> + if (y_best + h_best != y + h)
> + n += vnc_tight_send_framebuffer_update(vs, x, y_best+h_best,
> + w, h-(y_best-y)-h_best);
> +
> + /* Return after all recursive calls are done. */
> + return n;
> + }
> + }
> + return n + send_rect_simple(vs, x, y, w, h);
> +}
> +
> void vnc_tight_init(VncState *vs)
> {
> int i;
> @@ -276,6 +509,8 @@ void vnc_tight_init(VncState *vs)
> int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y,
> int w, int h)
> {
> + int max_rows;
> +
> if (vs->clientds.pf.bytes_per_pixel == 4&& vs->clientds.pf.rmax == 0xFF&&
> vs->clientds.pf.bmax == 0xFF&& vs->clientds.pf.gmax == 0xFF) {
> vs->tight_pixel24 = true;
> @@ -283,5 +518,13 @@ int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y,
> vs->tight_pixel24 = false;
> }
>
> - return send_rect_simple(vs, x, y, w, h);
> + if (w * h< VNC_TIGHT_MIN_SPLIT_RECT_SIZE)
> + return send_rect_simple(vs, x, y, w, h);
> +
> + /* 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);
> +
> + return find_large_solid_color_rect(vs, x, y, w, h, max_rows);
> }
>
next prev parent reply other threads:[~2010-05-18 13:35 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-18 12:49 [Qemu-devel] [PATCH v2 00/10] vnc-encodings Corentin Chary
2010-05-18 12:49 ` [Qemu-devel] [PATCH v2 01/10] vnc: refactor set_encodings Corentin Chary
2010-05-18 12:54 ` [Qemu-devel] " Alexander Graf
2010-05-18 18:09 ` Corentin Chary
2010-05-18 18:18 ` Alexander Graf
2010-05-18 19:23 ` Corentin Chary
2010-05-18 12:49 ` [Qemu-devel] [PATCH v2 02/10] vnc: really call zlib if we want zlib Corentin Chary
2010-05-18 12:54 ` [Qemu-devel] " Alexander Graf
2010-05-18 12:49 ` [Qemu-devel] [PATCH v2 03/10] vnc: only use a single zlib stream Corentin Chary
2010-05-18 12:51 ` [Qemu-devel] " Alexander Graf
2010-05-18 13:39 ` Anthony Liguori
2010-05-18 13:52 ` Alexander Graf
2010-05-18 13:55 ` Anthony Liguori
2010-05-18 13:56 ` Alexander Graf
2010-05-18 13:58 ` Anthony Liguori
2010-05-18 12:49 ` [Qemu-devel] [PATCH v2 04/10] vnc: adjust compression zstream level Corentin Chary
2010-05-18 12:55 ` [Qemu-devel] " Alexander Graf
2010-05-18 12:49 ` [Qemu-devel] [PATCH v2 05/10] vnc: add basic tight support Corentin Chary
2010-05-18 13:33 ` [Qemu-devel] " Anthony Liguori
2010-05-18 13:49 ` Alexander Graf
2010-05-18 13:54 ` Anthony Liguori
2010-05-18 12:49 ` [Qemu-devel] [PATCH v2 06/10] vnc: add support for tight fill encoding Corentin Chary
2010-05-18 13:34 ` Anthony Liguori [this message]
2010-05-18 12:49 ` [Qemu-devel] [PATCH v2 07/10] vnc: don't clear zlib stream on set_encoding Corentin Chary
2010-05-18 12:49 ` [Qemu-devel] [PATCH v2 08/10] vnc: remove memory leaks in zlib and tight encoding Corentin Chary
2010-05-18 12:49 ` [Qemu-devel] [PATCH v2 09/10] vnc: tight: add palette encoding Corentin Chary
2010-05-18 12:49 ` [Qemu-devel] [PATCH v2 10/10] vnc: update copyrights for vnc-encoding-tight.c Corentin Chary
2010-05-18 13:37 ` [Qemu-devel] " Anthony Liguori
2010-05-18 13:47 ` Chris Krumme
2010-05-18 17:26 ` Blue Swirl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4BF29782.5040401@linux.vnet.ibm.com \
--to=aliguori@linux.vnet.ibm.com \
--cc=agl@us.ibm.com \
--cc=agraf@suse.de \
--cc=corentincj@iksaif.net \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).