Compare commits

..

2 Commits

Author SHA1 Message Date
Gerd Hoffmann
dbb2a1326a input: map INPUT_BUTTON_WHEEL_{UP,DOWN} to legacy input z axis moves.
Unbreaks mouse wheel.

Reported-by: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-10 13:49:44 +01:00
Gerd Hoffmann
c3aa84b68f input: sdl: fix guest_cursor logic.
Unbreaks relative mouse mode with SDL.

Reported-by: Gabriel L. Somlo <gsomlo@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-10 13:49:44 +01:00
6 changed files with 128 additions and 148 deletions

View File

@@ -359,6 +359,20 @@ static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
} else { } else {
s->buttons &= ~bmap[evt->btn->button]; s->buttons &= ~bmap[evt->btn->button];
} }
if (evt->btn->down && evt->btn->button == INPUT_BUTTON_WHEEL_UP) {
s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
s->axis[INPUT_AXIS_X],
s->axis[INPUT_AXIS_Y],
-1,
s->buttons);
}
if (evt->btn->down && evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) {
s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
s->axis[INPUT_AXIS_X],
s->axis[INPUT_AXIS_Y],
1,
s->buttons);
}
break; break;
case INPUT_EVENT_KIND_ABS: case INPUT_EVENT_KIND_ABS:
s->axis[evt->abs->axis] = evt->abs->value; s->axis[evt->abs->axis] = evt->abs->value;

View File

@@ -455,13 +455,17 @@ static void sdl_send_mouse_event(int dx, int dy, int x, int y, int state)
real_screen->w); real_screen->w);
qemu_input_queue_abs(dcl->con, INPUT_AXIS_Y, y, qemu_input_queue_abs(dcl->con, INPUT_AXIS_Y, y,
real_screen->h); real_screen->h);
} else if (guest_cursor) { } else {
x -= guest_x; if (guest_cursor) {
y -= guest_y; x -= guest_x;
guest_x += x; y -= guest_y;
guest_y += y; guest_x += x;
qemu_input_queue_rel(dcl->con, INPUT_AXIS_X, x); guest_y += y;
qemu_input_queue_rel(dcl->con, INPUT_AXIS_Y, y); dx = x;
dy = y;
}
qemu_input_queue_rel(dcl->con, INPUT_AXIS_X, dx);
qemu_input_queue_rel(dcl->con, INPUT_AXIS_Y, dy);
} }
qemu_input_event_sync(); qemu_input_event_sync();
} }

View File

@@ -330,7 +330,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h)
} else { } else {
errors = tight_detect_smooth_image16(vs, w, h); errors = tight_detect_smooth_image16(vs, w, h);
} }
if (quality != (uint8_t)-1) { if (quality != -1) {
return (errors < tight_conf[quality].jpeg_threshold); return (errors < tight_conf[quality].jpeg_threshold);
} }
return (errors < tight_conf[compression].gradient_threshold); return (errors < tight_conf[compression].gradient_threshold);

View File

@@ -252,8 +252,6 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
if (job->vs->csock == -1) { if (job->vs->csock == -1) {
vnc_unlock_display(job->vs->vd); vnc_unlock_display(job->vs->vd);
/* Copy persistent encoding data */
vnc_async_encoding_end(job->vs, &vs);
goto disconnected; goto disconnected;
} }
@@ -280,9 +278,6 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
vnc_async_encoding_end(job->vs, &vs); vnc_async_encoding_end(job->vs, &vs);
qemu_bh_schedule(job->vs->bh); qemu_bh_schedule(job->vs->bh);
} else {
/* Copy persistent encoding data */
vnc_async_encoding_end(job->vs, &vs);
} }
vnc_unlock_output(job->vs); vnc_unlock_output(job->vs);

227
ui/vnc.c
View File

@@ -417,7 +417,8 @@ out_error:
3) resolutions > 1024 3) resolutions > 1024
*/ */
static int vnc_update_client(VncState *vs, int has_dirty, bool sync); static int vnc_update_client(VncState *vs, int has_dirty);
static int vnc_update_client_sync(VncState *vs, int has_dirty);
static void vnc_disconnect_start(VncState *vs); static void vnc_disconnect_start(VncState *vs);
static void vnc_colordepth(VncState *vs); static void vnc_colordepth(VncState *vs);
@@ -430,25 +431,29 @@ static int vnc_refresh_server_surface(VncDisplay *vd);
static void vnc_dpy_update(DisplayChangeListener *dcl, static void vnc_dpy_update(DisplayChangeListener *dcl,
int x, int y, int w, int h) int x, int y, int w, int h)
{ {
int i;
VncDisplay *vd = container_of(dcl, VncDisplay, dcl); VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
struct VncSurface *s = &vd->guest; struct VncSurface *s = &vd->guest;
int width = surface_width(vd->ds); int width = surface_width(vd->ds);
int height = surface_height(vd->ds); int height = surface_height(vd->ds);
/* this is needed this to ensure we updated all affected h += y;
* blocks if x % VNC_DIRTY_PIXELS_PER_BIT != 0 */
w += (x % VNC_DIRTY_PIXELS_PER_BIT); /* round x down to ensure the loop only spans one 16-pixel block per,
x -= (x % VNC_DIRTY_PIXELS_PER_BIT); iteration. otherwise, if (x % 16) != 0, the last iteration may span
two 16-pixel blocks but we only mark the first as dirty
*/
w += (x % 16);
x -= (x % 16);
x = MIN(x, width); x = MIN(x, width);
y = MIN(y, height); y = MIN(y, height);
w = MIN(x + w, width) - x; w = MIN(x + w, width) - x;
h = MIN(y + h, height); h = MIN(h, height);
for (; y < h; y++) { for (; y < h; y++)
bitmap_set(s->dirty[y], x / VNC_DIRTY_PIXELS_PER_BIT, for (i = 0; i < w; i += 16)
DIV_ROUND_UP(w, VNC_DIRTY_PIXELS_PER_BIT)); set_bit((x + i) / 16, s->dirty[y]);
}
} }
void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h, void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
@@ -566,15 +571,6 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
ptr += x * VNC_SERVER_FB_BYTES; ptr += x * VNC_SERVER_FB_BYTES;
return ptr; return ptr;
} }
/* this sets only the visible pixels of a dirty bitmap */
#define VNC_SET_VISIBLE_PIXELS_DIRTY(bitmap, w, h) {\
int y;\
memset(bitmap, 0x00, sizeof(bitmap));\
for (y = 0; y < h; y++) {\
bitmap_set(bitmap[y], 0,\
DIV_ROUND_UP(w, VNC_DIRTY_PIXELS_PER_BIT));\
} \
}
static void vnc_dpy_switch(DisplayChangeListener *dcl, static void vnc_dpy_switch(DisplayChangeListener *dcl,
DisplaySurface *surface) DisplaySurface *surface)
@@ -600,9 +596,7 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
qemu_pixman_image_unref(vd->guest.fb); qemu_pixman_image_unref(vd->guest.fb);
vd->guest.fb = pixman_image_ref(surface->image); vd->guest.fb = pixman_image_ref(surface->image);
vd->guest.format = surface->format; vd->guest.format = surface->format;
VNC_SET_VISIBLE_PIXELS_DIRTY(vd->guest.dirty, memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty));
surface_width(vd->ds),
surface_height(vd->ds));
QTAILQ_FOREACH(vs, &vd->clients, next) { QTAILQ_FOREACH(vs, &vd->clients, next) {
vnc_colordepth(vs); vnc_colordepth(vs);
@@ -610,9 +604,7 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
if (vs->vd->cursor) { if (vs->vd->cursor) {
vnc_cursor_define(vs); vnc_cursor_define(vs);
} }
VNC_SET_VISIBLE_PIXELS_DIRTY(vs->dirty, memset(vs->dirty, 0xFF, sizeof(vs->dirty));
surface_width(vd->ds),
surface_height(vd->ds));
} }
} }
@@ -759,7 +751,7 @@ static void vnc_dpy_copy(DisplayChangeListener *dcl,
QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) { QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
vs->force_update = 1; vs->force_update = 1;
vnc_update_client(vs, 1, true); vnc_update_client_sync(vs, 1);
/* vs might be free()ed here */ /* vs might be free()ed here */
} }
} }
@@ -778,12 +770,11 @@ static void vnc_dpy_copy(DisplayChangeListener *dcl,
y = dst_y + h - 1; y = dst_y + h - 1;
inc = -1; inc = -1;
} }
w_lim = w - (VNC_DIRTY_PIXELS_PER_BIT - (dst_x % VNC_DIRTY_PIXELS_PER_BIT)); w_lim = w - (16 - (dst_x % 16));
if (w_lim < 0) { if (w_lim < 0)
w_lim = w; w_lim = w;
} else { else
w_lim = w - (w_lim % VNC_DIRTY_PIXELS_PER_BIT); w_lim = w - (w_lim % 16);
}
for (i = 0; i < h; i++) { for (i = 0; i < h; i++) {
for (x = 0; x <= w_lim; for (x = 0; x <= w_lim;
x += s, src_row += cmp_bytes, dst_row += cmp_bytes) { x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
@@ -791,11 +782,10 @@ static void vnc_dpy_copy(DisplayChangeListener *dcl,
if ((s = w - w_lim) == 0) if ((s = w - w_lim) == 0)
break; break;
} else if (!x) { } else if (!x) {
s = (VNC_DIRTY_PIXELS_PER_BIT - s = (16 - (dst_x % 16));
(dst_x % VNC_DIRTY_PIXELS_PER_BIT));
s = MIN(s, w_lim); s = MIN(s, w_lim);
} else { } else {
s = VNC_DIRTY_PIXELS_PER_BIT; s = 16;
} }
cmp_bytes = s * VNC_SERVER_FB_BYTES; cmp_bytes = s * VNC_SERVER_FB_BYTES;
if (memcmp(src_row, dst_row, cmp_bytes) == 0) if (memcmp(src_row, dst_row, cmp_bytes) == 0)
@@ -803,8 +793,7 @@ static void vnc_dpy_copy(DisplayChangeListener *dcl,
memmove(dst_row, src_row, cmp_bytes); memmove(dst_row, src_row, cmp_bytes);
QTAILQ_FOREACH(vs, &vd->clients, next) { QTAILQ_FOREACH(vs, &vd->clients, next) {
if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
set_bit(((x + dst_x) / VNC_DIRTY_PIXELS_PER_BIT), set_bit(((x + dst_x) / 16), vs->dirty[y]);
vs->dirty[y]);
} }
} }
} }
@@ -873,24 +862,35 @@ static int find_and_clear_dirty_height(struct VncState *vs,
int h; int h;
for (h = 1; h < (height - y); h++) { for (h = 1; h < (height - y); h++) {
int tmp_x;
if (!test_bit(last_x, vs->dirty[y + h])) { if (!test_bit(last_x, vs->dirty[y + h])) {
break; break;
} }
bitmap_clear(vs->dirty[y + h], last_x, x - last_x); for (tmp_x = last_x; tmp_x < x; tmp_x++) {
clear_bit(tmp_x, vs->dirty[y + h]);
}
} }
return h; return h;
} }
static int vnc_update_client(VncState *vs, int has_dirty, bool sync) static int vnc_update_client_sync(VncState *vs, int has_dirty)
{
int ret = vnc_update_client(vs, has_dirty);
vnc_jobs_join(vs);
return ret;
}
static int vnc_update_client(VncState *vs, int has_dirty)
{ {
if (vs->need_update && vs->csock != -1) { if (vs->need_update && vs->csock != -1) {
VncDisplay *vd = vs->vd; VncDisplay *vd = vs->vd;
VncJob *job; VncJob *job;
int y; int y;
int height; int width, height;
int n = 0; int n = 0;
if (vs->output.offset && !vs->audio_cap && !vs->force_update) if (vs->output.offset && !vs->audio_cap && !vs->force_update)
/* kernel send buffers are full -> drop frames to throttle */ /* kernel send buffers are full -> drop frames to throttle */
return 0; return 0;
@@ -906,27 +906,33 @@ static int vnc_update_client(VncState *vs, int has_dirty, bool sync)
*/ */
job = vnc_job_new(vs); job = vnc_job_new(vs);
width = MIN(pixman_image_get_width(vd->server), vs->client_width);
height = MIN(pixman_image_get_height(vd->server), vs->client_height); height = MIN(pixman_image_get_height(vd->server), vs->client_height);
y = 0; for (y = 0; y < height; y++) {
for (;;) { int x;
int x, h; int last_x = -1;
unsigned long x2; for (x = 0; x < width / 16; x++) {
unsigned long offset = find_next_bit((unsigned long *) &vs->dirty, if (test_and_clear_bit(x, vs->dirty[y])) {
height * VNC_DIRTY_BPL(vs), if (last_x == -1) {
y * VNC_DIRTY_BPL(vs)); last_x = x;
if (offset == height * VNC_DIRTY_BPL(vs)) { }
/* no more dirty bits */ } else {
break; if (last_x != -1) {
int h = find_and_clear_dirty_height(vs, y, last_x, x,
height);
n += vnc_job_add_rect(job, last_x * 16, y,
(x - last_x) * 16, h);
}
last_x = -1;
}
}
if (last_x != -1) {
int h = find_and_clear_dirty_height(vs, y, last_x, x, height);
n += vnc_job_add_rect(job, last_x * 16, y,
(x - last_x) * 16, h);
} }
y = offset / VNC_DIRTY_BPL(vs);
x = offset % VNC_DIRTY_BPL(vs);
x2 = find_next_zero_bit((unsigned long *) &vs->dirty[y],
VNC_DIRTY_BPL(vs), x);
bitmap_clear(vs->dirty[y], x, x2 - x);
h = find_and_clear_dirty_height(vs, y, x, x2, height);
n += vnc_job_add_rect(job, x * VNC_DIRTY_PIXELS_PER_BIT, y,
(x2 - x) * VNC_DIRTY_PIXELS_PER_BIT, h);
} }
vnc_job_push(job); vnc_job_push(job);
@@ -934,11 +940,8 @@ static int vnc_update_client(VncState *vs, int has_dirty, bool sync)
return n; return n;
} }
if (vs->csock == -1) { if (vs->csock == -1)
vnc_disconnect_finish(vs); vnc_disconnect_finish(vs);
} else if (sync) {
vnc_jobs_join(vs);
}
return 0; return 0;
} }
@@ -1843,7 +1846,7 @@ static void framebuffer_update_request(VncState *vs, int incremental,
int w, int h) int w, int h)
{ {
int i; int i;
const size_t width = surface_width(vs->vd->ds) / VNC_DIRTY_PIXELS_PER_BIT; const size_t width = surface_width(vs->vd->ds) / 16;
const size_t height = surface_height(vs->vd->ds); const size_t height = surface_height(vs->vd->ds);
if (y_position > height) { if (y_position > height) {
@@ -2545,9 +2548,7 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
vs->lossy_rect[sty][stx] = 0; vs->lossy_rect[sty][stx] = 0;
for (j = 0; j < VNC_STAT_RECT; ++j) { for (j = 0; j < VNC_STAT_RECT; ++j) {
bitmap_set(vs->dirty[y + j], bitmap_set(vs->dirty[y + j], x / 16, VNC_STAT_RECT / 16);
x / VNC_DIRTY_PIXELS_PER_BIT,
VNC_STAT_RECT / VNC_DIRTY_PIXELS_PER_BIT);
} }
has_dirty++; has_dirty++;
} }
@@ -2651,8 +2652,8 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
int width = pixman_image_get_width(vd->guest.fb); int width = pixman_image_get_width(vd->guest.fb);
int height = pixman_image_get_height(vd->guest.fb); int height = pixman_image_get_height(vd->guest.fb);
int y; int y;
uint8_t *guest_row0 = NULL, *server_row0; uint8_t *guest_row;
int guest_stride = 0, server_stride; uint8_t *server_row;
int cmp_bytes; int cmp_bytes;
VncState *vs; VncState *vs;
int has_dirty = 0; int has_dirty = 0;
@@ -2670,64 +2671,47 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
* Check and copy modified bits from guest to server surface. * Check and copy modified bits from guest to server surface.
* Update server dirty map. * Update server dirty map.
*/ */
cmp_bytes = VNC_DIRTY_PIXELS_PER_BIT * VNC_SERVER_FB_BYTES; cmp_bytes = 64;
if (cmp_bytes > vnc_server_fb_stride(vd)) { if (cmp_bytes > vnc_server_fb_stride(vd)) {
cmp_bytes = vnc_server_fb_stride(vd); cmp_bytes = vnc_server_fb_stride(vd);
} }
if (vd->guest.format != VNC_SERVER_FB_FORMAT) { if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
int width = pixman_image_get_width(vd->server); int width = pixman_image_get_width(vd->server);
tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width); tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width);
} else {
guest_row0 = (uint8_t *)pixman_image_get_data(vd->guest.fb);
guest_stride = pixman_image_get_stride(vd->guest.fb);
} }
server_row0 = (uint8_t *)pixman_image_get_data(vd->server); guest_row = (uint8_t *)pixman_image_get_data(vd->guest.fb);
server_stride = pixman_image_get_stride(vd->server); server_row = (uint8_t *)pixman_image_get_data(vd->server);
for (y = 0; y < height; y++) {
if (!bitmap_empty(vd->guest.dirty[y], VNC_DIRTY_BITS)) {
int x;
uint8_t *guest_ptr;
uint8_t *server_ptr;
y = 0; if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
for (;;) { qemu_pixman_linebuf_fill(tmpbuf, vd->guest.fb, width, 0, y);
int x; guest_ptr = (uint8_t *)pixman_image_get_data(tmpbuf);
uint8_t *guest_ptr, *server_ptr; } else {
unsigned long offset = find_next_bit((unsigned long *) &vd->guest.dirty, guest_ptr = guest_row;
height * VNC_DIRTY_BPL(&vd->guest), }
y * VNC_DIRTY_BPL(&vd->guest)); server_ptr = server_row;
if (offset == height * VNC_DIRTY_BPL(&vd->guest)) {
/* no more dirty bits */ for (x = 0; x + 15 < width;
break; x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
if (!test_and_clear_bit((x / 16), vd->guest.dirty[y]))
continue;
if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
continue;
memcpy(server_ptr, guest_ptr, cmp_bytes);
if (!vd->non_adaptive)
vnc_rect_updated(vd, x, y, &tv);
QTAILQ_FOREACH(vs, &vd->clients, next) {
set_bit((x / 16), vs->dirty[y]);
}
has_dirty++;
}
} }
y = offset / VNC_DIRTY_BPL(&vd->guest); guest_row += pixman_image_get_stride(vd->guest.fb);
x = offset % VNC_DIRTY_BPL(&vd->guest); server_row += pixman_image_get_stride(vd->server);
server_ptr = server_row0 + y * server_stride + x * cmp_bytes;
if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
qemu_pixman_linebuf_fill(tmpbuf, vd->guest.fb, width, 0, y);
guest_ptr = (uint8_t *)pixman_image_get_data(tmpbuf);
} else {
guest_ptr = guest_row0 + y * guest_stride;
}
guest_ptr += x * cmp_bytes;
for (; x < DIV_ROUND_UP(width, VNC_DIRTY_PIXELS_PER_BIT);
x++, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
if (!test_and_clear_bit(x, vd->guest.dirty[y])) {
continue;
}
if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0) {
continue;
}
memcpy(server_ptr, guest_ptr, cmp_bytes);
if (!vd->non_adaptive) {
vnc_rect_updated(vd, x * VNC_DIRTY_PIXELS_PER_BIT,
y, &tv);
}
QTAILQ_FOREACH(vs, &vd->clients, next) {
set_bit(x, vs->dirty[y]);
}
has_dirty++;
}
y++;
} }
qemu_pixman_image_unref(tmpbuf); qemu_pixman_image_unref(tmpbuf);
return has_dirty; return has_dirty;
@@ -2750,7 +2734,7 @@ static void vnc_refresh(DisplayChangeListener *dcl)
vnc_unlock_display(vd); vnc_unlock_display(vd);
QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) { QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
rects += vnc_update_client(vs, has_dirty, false); rects += vnc_update_client(vs, has_dirty);
/* vs might be free()ed here */ /* vs might be free()ed here */
} }
@@ -3150,9 +3134,7 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
acl = 1; acl = 1;
#endif #endif
} else if (strncmp(options, "lossy", 5) == 0) { } else if (strncmp(options, "lossy", 5) == 0) {
#ifdef CONFIG_VNC_JPEG
vs->lossy = true; vs->lossy = true;
#endif
} else if (strncmp(options, "non-adaptive", 12) == 0) { } else if (strncmp(options, "non-adaptive", 12) == 0) {
vs->non_adaptive = true; vs->non_adaptive = true;
} else if (strncmp(options, "share=", 6) == 0) { } else if (strncmp(options, "share=", 6) == 0) {
@@ -3169,13 +3151,6 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
} }
} }
/* adaptive updates are only used with tight encoding and
* if lossy updates are enabled so we can disable all the
* calculations otherwise */
if (!vs->lossy) {
vs->non_adaptive = true;
}
#ifdef CONFIG_VNC_TLS #ifdef CONFIG_VNC_TLS
if (acl && x509 && vs->tls.x509verify) { if (acl && x509 && vs->tls.x509verify) {
if (!(vs->tls.acl = qemu_acl_init("vnc.x509dname"))) { if (!(vs->tls.acl = qemu_acl_init("vnc.x509dname"))) {

View File

@@ -81,16 +81,8 @@ typedef void VncSendHextileTile(VncState *vs,
#define VNC_MAX_WIDTH 2560 #define VNC_MAX_WIDTH 2560
#define VNC_MAX_HEIGHT 2048 #define VNC_MAX_HEIGHT 2048
/* VNC_DIRTY_PIXELS_PER_BIT is the number of dirty pixels represented
* by one bit in the dirty bitmap */
#define VNC_DIRTY_PIXELS_PER_BIT 16
/* VNC_DIRTY_BITS is the number of bits in the dirty bitmap. */ /* VNC_DIRTY_BITS is the number of bits in the dirty bitmap. */
#define VNC_DIRTY_BITS (VNC_MAX_WIDTH / VNC_DIRTY_PIXELS_PER_BIT) #define VNC_DIRTY_BITS (VNC_MAX_WIDTH / 16)
/* VNC_DIRTY_BPL (BPL = bits per line) might be greater than
* VNC_DIRTY_BITS due to alignment */
#define VNC_DIRTY_BPL(x) (sizeof((x)->dirty) / VNC_MAX_HEIGHT * BITS_PER_BYTE)
#define VNC_STAT_RECT 64 #define VNC_STAT_RECT 64
#define VNC_STAT_COLS (VNC_MAX_WIDTH / VNC_STAT_RECT) #define VNC_STAT_COLS (VNC_MAX_WIDTH / VNC_STAT_RECT)