Revision 999342a0 ui/vnc.c
b/ui/vnc.c | ||
---|---|---|
35 | 35 |
#define VNC_REFRESH_INTERVAL_BASE 30 |
36 | 36 |
#define VNC_REFRESH_INTERVAL_INC 50 |
37 | 37 |
#define VNC_REFRESH_INTERVAL_MAX 2000 |
38 |
static const struct timeval VNC_REFRESH_STATS = { 0, 500000 }; |
|
39 |
static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 }; |
|
38 | 40 |
|
39 | 41 |
#include "vnc_keysym.h" |
40 | 42 |
#include "d3des.h" |
... | ... | |
2258 | 2260 |
return 0; |
2259 | 2261 |
} |
2260 | 2262 |
|
2263 |
static VncRectStat *vnc_stat_rect(VncDisplay *vd, int x, int y) |
|
2264 |
{ |
|
2265 |
struct VncSurface *vs = &vd->guest; |
|
2266 |
|
|
2267 |
return &vs->stats[y / VNC_STAT_RECT][x / VNC_STAT_RECT]; |
|
2268 |
} |
|
2269 |
|
|
2270 |
static void vnc_update_stats(VncDisplay *vd, struct timeval * tv) |
|
2271 |
{ |
|
2272 |
int x, y; |
|
2273 |
struct timeval res; |
|
2274 |
|
|
2275 |
for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) { |
|
2276 |
for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) { |
|
2277 |
VncRectStat *rect = vnc_stat_rect(vd, x, y); |
|
2278 |
|
|
2279 |
rect->updated = false; |
|
2280 |
} |
|
2281 |
} |
|
2282 |
|
|
2283 |
timersub(tv, &VNC_REFRESH_STATS, &res); |
|
2284 |
|
|
2285 |
if (timercmp(&vd->guest.last_freq_check, &res, >)) { |
|
2286 |
return ; |
|
2287 |
} |
|
2288 |
vd->guest.last_freq_check = *tv; |
|
2289 |
|
|
2290 |
for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) { |
|
2291 |
for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) { |
|
2292 |
VncRectStat *rect= vnc_stat_rect(vd, x, y); |
|
2293 |
int count = ARRAY_SIZE(rect->times); |
|
2294 |
struct timeval min, max; |
|
2295 |
|
|
2296 |
if (!timerisset(&rect->times[count - 1])) { |
|
2297 |
continue ; |
|
2298 |
} |
|
2299 |
|
|
2300 |
max = rect->times[(rect->idx + count - 1) % count]; |
|
2301 |
timersub(tv, &max, &res); |
|
2302 |
|
|
2303 |
if (timercmp(&res, &VNC_REFRESH_LOSSY, >)) { |
|
2304 |
rect->freq = 0; |
|
2305 |
memset(rect->times, 0, sizeof (rect->times)); |
|
2306 |
continue ; |
|
2307 |
} |
|
2308 |
|
|
2309 |
min = rect->times[rect->idx]; |
|
2310 |
max = rect->times[(rect->idx + count - 1) % count]; |
|
2311 |
timersub(&max, &min, &res); |
|
2312 |
|
|
2313 |
rect->freq = res.tv_sec + res.tv_usec / 1000000.; |
|
2314 |
rect->freq /= count; |
|
2315 |
rect->freq = 1. / rect->freq; |
|
2316 |
} |
|
2317 |
} |
|
2318 |
} |
|
2319 |
|
|
2320 |
double vnc_update_freq(VncState *vs, int x, int y, int w, int h) |
|
2321 |
{ |
|
2322 |
int i, j; |
|
2323 |
double total = 0; |
|
2324 |
int num = 0; |
|
2325 |
|
|
2326 |
x = (x / VNC_STAT_RECT) * VNC_STAT_RECT; |
|
2327 |
y = (y / VNC_STAT_RECT) * VNC_STAT_RECT; |
|
2328 |
|
|
2329 |
for (j = y; j <= y + h; j += VNC_STAT_RECT) { |
|
2330 |
for (i = x; i <= x + w; i += VNC_STAT_RECT) { |
|
2331 |
total += vnc_stat_rect(vs->vd, i, j)->freq; |
|
2332 |
num++; |
|
2333 |
} |
|
2334 |
} |
|
2335 |
|
|
2336 |
if (num) { |
|
2337 |
return total / num; |
|
2338 |
} else { |
|
2339 |
return 0; |
|
2340 |
} |
|
2341 |
} |
|
2342 |
|
|
2343 |
static void vnc_rect_updated(VncDisplay *vd, int x, int y, struct timeval * tv) |
|
2344 |
{ |
|
2345 |
VncRectStat *rect; |
|
2346 |
|
|
2347 |
rect = vnc_stat_rect(vd, x, y); |
|
2348 |
if (rect->updated) { |
|
2349 |
return ; |
|
2350 |
} |
|
2351 |
rect->times[rect->idx] = *tv; |
|
2352 |
rect->idx = (rect->idx + 1) % ARRAY_SIZE(rect->times); |
|
2353 |
rect->updated = true; |
|
2354 |
} |
|
2355 |
|
|
2261 | 2356 |
static int vnc_refresh_server_surface(VncDisplay *vd) |
2262 | 2357 |
{ |
2263 | 2358 |
int y; |
... | ... | |
2268 | 2363 |
VncState *vs; |
2269 | 2364 |
int has_dirty = 0; |
2270 | 2365 |
|
2366 |
struct timeval tv; |
|
2367 |
|
|
2368 |
gettimeofday(&tv, NULL); |
|
2369 |
vnc_update_stats(vd, &tv); |
|
2370 |
|
|
2271 | 2371 |
/* |
2272 | 2372 |
* Walk through the guest dirty map. |
2273 | 2373 |
* Check and copy modified bits from guest to server surface. |
... | ... | |
2294 | 2394 |
if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0) |
2295 | 2395 |
continue; |
2296 | 2396 |
memcpy(server_ptr, guest_ptr, cmp_bytes); |
2397 |
vnc_rect_updated(vd, x, y, &tv); |
|
2297 | 2398 |
QTAILQ_FOREACH(vs, &vd->clients, next) { |
2298 | 2399 |
vnc_set_bit(vs->dirty[y], (x / 16)); |
2299 | 2400 |
} |
Also available in: Unified diff