41 |
41 |
#include "vnc_keysym.h"
|
42 |
42 |
#include "d3des.h"
|
43 |
43 |
|
44 |
|
#define count_bits(c, v) { \
|
45 |
|
for (c = 0; v; v >>= 1) \
|
46 |
|
{ \
|
47 |
|
c += v & 1; \
|
48 |
|
} \
|
49 |
|
}
|
50 |
|
|
51 |
44 |
static VncDisplay *vnc_display; /* needed for info vnc */
|
52 |
45 |
static DisplayChangeListener *dcl;
|
53 |
46 |
|
... | ... | |
378 |
371 |
static void vnc_refresh(void *opaque);
|
379 |
372 |
static int vnc_refresh_server_surface(VncDisplay *vd);
|
380 |
373 |
|
381 |
|
static inline void vnc_set_bit(uint32_t *d, int k)
|
382 |
|
{
|
383 |
|
d[k >> 5] |= 1 << (k & 0x1f);
|
384 |
|
}
|
385 |
|
|
386 |
|
static inline void vnc_clear_bit(uint32_t *d, int k)
|
387 |
|
{
|
388 |
|
d[k >> 5] &= ~(1 << (k & 0x1f));
|
389 |
|
}
|
390 |
|
|
391 |
|
static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
|
392 |
|
{
|
393 |
|
int j;
|
394 |
|
|
395 |
|
j = 0;
|
396 |
|
while (n >= 32) {
|
397 |
|
d[j++] = -1;
|
398 |
|
n -= 32;
|
399 |
|
}
|
400 |
|
if (n > 0)
|
401 |
|
d[j++] = (1 << n) - 1;
|
402 |
|
while (j < nb_words)
|
403 |
|
d[j++] = 0;
|
404 |
|
}
|
405 |
|
|
406 |
|
static inline int vnc_get_bit(const uint32_t *d, int k)
|
407 |
|
{
|
408 |
|
return (d[k >> 5] >> (k & 0x1f)) & 1;
|
409 |
|
}
|
410 |
|
|
411 |
|
static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2,
|
412 |
|
int nb_words)
|
413 |
|
{
|
414 |
|
int i;
|
415 |
|
for(i = 0; i < nb_words; i++) {
|
416 |
|
if ((d1[i] & d2[i]) != 0)
|
417 |
|
return 1;
|
418 |
|
}
|
419 |
|
return 0;
|
420 |
|
}
|
421 |
|
|
422 |
374 |
static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
|
423 |
375 |
{
|
424 |
376 |
int i;
|
... | ... | |
441 |
393 |
|
442 |
394 |
for (; y < h; y++)
|
443 |
395 |
for (i = 0; i < w; i += 16)
|
444 |
|
vnc_set_bit(s->dirty[y], (x + i) / 16);
|
|
396 |
set_bit((x + i) / 16, s->dirty[y]);
|
445 |
397 |
}
|
446 |
398 |
|
447 |
399 |
void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
|
... | ... | |
780 |
732 |
memmove(dst_row, src_row, cmp_bytes);
|
781 |
733 |
QTAILQ_FOREACH(vs, &vd->clients, next) {
|
782 |
734 |
if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
|
783 |
|
vnc_set_bit(vs->dirty[y], ((x + dst_x) / 16));
|
|
735 |
set_bit(((x + dst_x) / 16), vs->dirty[y]);
|
784 |
736 |
}
|
785 |
737 |
}
|
786 |
738 |
}
|
... | ... | |
850 |
802 |
|
851 |
803 |
for (h = 1; h < (vd->server->height - y); h++) {
|
852 |
804 |
int tmp_x;
|
853 |
|
if (!vnc_get_bit(vs->dirty[y + h], last_x))
|
|
805 |
if (!test_bit(last_x, vs->dirty[y + h])) {
|
854 |
806 |
break;
|
855 |
|
for (tmp_x = last_x; tmp_x < x; tmp_x++)
|
856 |
|
vnc_clear_bit(vs->dirty[y + h], tmp_x);
|
|
807 |
}
|
|
808 |
for (tmp_x = last_x; tmp_x < x; tmp_x++) {
|
|
809 |
clear_bit(tmp_x, vs->dirty[y + h]);
|
|
810 |
}
|
857 |
811 |
}
|
858 |
812 |
|
859 |
813 |
return h;
|
... | ... | |
905 |
859 |
int x;
|
906 |
860 |
int last_x = -1;
|
907 |
861 |
for (x = 0; x < width / 16; x++) {
|
908 |
|
if (vnc_get_bit(vs->dirty[y], x)) {
|
|
862 |
if (test_and_clear_bit(x, vs->dirty[y])) {
|
909 |
863 |
if (last_x == -1) {
|
910 |
864 |
last_x = x;
|
911 |
865 |
}
|
912 |
|
vnc_clear_bit(vs->dirty[y], x);
|
913 |
866 |
} else {
|
914 |
867 |
if (last_x != -1) {
|
915 |
868 |
int h = find_and_clear_dirty_height(vs, y, last_x, x);
|
... | ... | |
1702 |
1655 |
if (!incremental) {
|
1703 |
1656 |
vs->force_update = 1;
|
1704 |
1657 |
for (i = 0; i < h; i++) {
|
1705 |
|
vnc_set_bits(vs->dirty[y_position + i],
|
1706 |
|
(ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
|
|
1658 |
bitmap_set(vs->dirty[y_position + i], x_position / 16, w / 16);
|
1707 |
1659 |
}
|
1708 |
1660 |
}
|
1709 |
1661 |
}
|
... | ... | |
1842 |
1794 |
|
1843 |
1795 |
vs->clientds = *(vs->vd->guest.ds);
|
1844 |
1796 |
vs->clientds.pf.rmax = red_max;
|
1845 |
|
count_bits(vs->clientds.pf.rbits, red_max);
|
|
1797 |
vs->clientds.pf.rbits = hweight_long(red_max);
|
1846 |
1798 |
vs->clientds.pf.rshift = red_shift;
|
1847 |
1799 |
vs->clientds.pf.rmask = red_max << red_shift;
|
1848 |
1800 |
vs->clientds.pf.gmax = green_max;
|
1849 |
|
count_bits(vs->clientds.pf.gbits, green_max);
|
|
1801 |
vs->clientds.pf.gbits = hweight_long(green_max);
|
1850 |
1802 |
vs->clientds.pf.gshift = green_shift;
|
1851 |
1803 |
vs->clientds.pf.gmask = green_max << green_shift;
|
1852 |
1804 |
vs->clientds.pf.bmax = blue_max;
|
1853 |
|
count_bits(vs->clientds.pf.bbits, blue_max);
|
|
1805 |
vs->clientds.pf.bbits = hweight_long(blue_max);
|
1854 |
1806 |
vs->clientds.pf.bshift = blue_shift;
|
1855 |
1807 |
vs->clientds.pf.bmask = blue_max << blue_shift;
|
1856 |
1808 |
vs->clientds.pf.bits_per_pixel = bits_per_pixel;
|
... | ... | |
2315 |
2267 |
x = x / VNC_STAT_RECT * VNC_STAT_RECT;
|
2316 |
2268 |
|
2317 |
2269 |
QTAILQ_FOREACH(vs, &vd->clients, next) {
|
2318 |
|
int j, i;
|
|
2270 |
int j;
|
2319 |
2271 |
|
2320 |
2272 |
/* kernel send buffers are full -> refresh later */
|
2321 |
2273 |
if (vs->output.offset) {
|
... | ... | |
2328 |
2280 |
|
2329 |
2281 |
vs->lossy_rect[sty][stx] = 0;
|
2330 |
2282 |
for (j = 0; j < VNC_STAT_RECT; ++j) {
|
2331 |
|
for (i = x / 16; i < VNC_STAT_RECT / 16 + x / 16; ++i) {
|
2332 |
|
vnc_set_bit(vs->dirty[y + j], i);
|
2333 |
|
}
|
|
2283 |
bitmap_set(vs->dirty[y + j], x / 16, VNC_STAT_RECT / 16);
|
2334 |
2284 |
}
|
2335 |
2285 |
has_dirty++;
|
2336 |
2286 |
}
|
... | ... | |
2433 |
2383 |
uint8_t *guest_row;
|
2434 |
2384 |
uint8_t *server_row;
|
2435 |
2385 |
int cmp_bytes;
|
2436 |
|
uint32_t width_mask[VNC_DIRTY_WORDS];
|
|
2386 |
unsigned long width_mask[VNC_DIRTY_WORDS];
|
2437 |
2387 |
VncState *vs;
|
2438 |
2388 |
int has_dirty = 0;
|
2439 |
2389 |
|
... | ... | |
2447 |
2397 |
* Check and copy modified bits from guest to server surface.
|
2448 |
2398 |
* Update server dirty map.
|
2449 |
2399 |
*/
|
2450 |
|
vnc_set_bits(width_mask, (ds_get_width(vd->ds) / 16), VNC_DIRTY_WORDS);
|
|
2400 |
bitmap_set(width_mask, 0, (ds_get_width(vd->ds) / 16));
|
|
2401 |
bitmap_clear(width_mask, (ds_get_width(vd->ds) / 16),
|
|
2402 |
VNC_DIRTY_WORDS * BITS_PER_LONG);
|
2451 |
2403 |
cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds);
|
2452 |
2404 |
guest_row = vd->guest.ds->data;
|
2453 |
2405 |
server_row = vd->server->data;
|
2454 |
2406 |
for (y = 0; y < vd->guest.ds->height; y++) {
|
2455 |
|
if (vnc_and_bits(vd->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) {
|
|
2407 |
if (bitmap_intersects(vd->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) {
|
2456 |
2408 |
int x;
|
2457 |
2409 |
uint8_t *guest_ptr;
|
2458 |
2410 |
uint8_t *server_ptr;
|
... | ... | |
2462 |
2414 |
|
2463 |
2415 |
for (x = 0; x < vd->guest.ds->width;
|
2464 |
2416 |
x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
|
2465 |
|
if (!vnc_get_bit(vd->guest.dirty[y], (x / 16)))
|
|
2417 |
if (!test_and_clear_bit((x / 16), vd->guest.dirty[y]))
|
2466 |
2418 |
continue;
|
2467 |
|
vnc_clear_bit(vd->guest.dirty[y], (x / 16));
|
2468 |
2419 |
if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
|
2469 |
2420 |
continue;
|
2470 |
2421 |
memcpy(server_ptr, guest_ptr, cmp_bytes);
|
2471 |
2422 |
vnc_rect_updated(vd, x, y, &tv);
|
2472 |
2423 |
QTAILQ_FOREACH(vs, &vd->clients, next) {
|
2473 |
|
vnc_set_bit(vs->dirty[y], (x / 16));
|
|
2424 |
set_bit((x / 16), vs->dirty[y]);
|
2474 |
2425 |
}
|
2475 |
2426 |
has_dirty++;
|
2476 |
2427 |
}
|