⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vnc-backoff-screen-scan

📁 xen 3.2.2 源码
💻
字号:
Index: ioemu/vnc.c===================================================================--- ioemu.orig/vnc.c	2007-05-10 15:18:01.000000000 +0100+++ ioemu/vnc.c	2007-05-10 15:18:58.000000000 +0100@@ -28,7 +28,19 @@ #include "qemu_socket.h" #include <assert.h> -#define VNC_REFRESH_INTERVAL (1000 / 30)+/* The refresh interval starts at BASE.  If we scan the buffer and+   find no change, we increase by INC, up to MAX.  If the mouse moves+   or we get a keypress, the interval is set back to BASE.  If we find+   an update, halve the interval.++   All times in milliseconds. */+#define VNC_REFRESH_INTERVAL_BASE 30+#define VNC_REFRESH_INTERVAL_INC  50+#define VNC_REFRESH_INTERVAL_MAX  2000++/* Wait at most one second between updates, so that we can detect a+   minimised vncviewer reasonably quickly. */+#define VNC_MAX_UPDATE_INTERVAL   5000  #include "vnc_keysym.h" #include "keymaps.c"@@ -61,10 +73,11 @@ struct VncState {     QEMUTimer *timer;+    int timer_interval;+    int64_t last_update_time;     int lsock;     int csock;     DisplayState *ds;-    int need_update;     int width;     int height;     uint64_t *dirty_row;	/* screen regions which are possibly dirty */@@ -102,8 +115,6 @@     int visible_w;     int visible_h; -    int slow_client;-     /* input */     uint8_t modifiers_state[256]; };@@ -408,7 +419,7 @@     int y = 0;     int pitch = ds->linesize;     VncState *vs = ds->opaque;-    int updating_client = !vs->slow_client;+    int updating_client = 1;      if (src_x < vs->visible_x || src_y < vs->visible_y || 	dst_x < vs->visible_x || dst_y < vs->visible_y ||@@ -418,10 +429,8 @@ 	(dst_y + h) > (vs->visible_y + vs->visible_h)) 	updating_client = 0; -    if (updating_client) {-	vs->need_update = 1;+    if (updating_client) 	_vnc_update_client(vs);-    }      if (dst_y > src_y) { 	y = h - 1;@@ -473,110 +482,149 @@ static void _vnc_update_client(void *opaque) {     VncState *vs = opaque;-    int64_t now = qemu_get_clock(rt_clock);--    if (vs->need_update && vs->csock != -1) {-	int y;-	char *row;-	char *old_row;-	uint64_t width_mask;-	int n_rectangles;-	int saved_offset;-	int maxx, maxy;-	int tile_bytes = vs->depth * DP2X(vs, 1);+    int64_t now;+    int y;+    char *row;+    char *old_row;+    uint64_t width_mask;+    int n_rectangles;+    int saved_offset;+    int maxx, maxy;+    int tile_bytes = vs->depth * DP2X(vs, 1); -	qemu_mod_timer(vs->timer, now + VNC_REFRESH_INTERVAL);+    if (vs->csock == -1)+	return; -	if (vs->width != DP2X(vs, DIRTY_PIXEL_BITS))-	    width_mask = (1ULL << X2DP_UP(vs, vs->ds->width)) - 1;-	else-	    width_mask = ~(0ULL);+    now = qemu_get_clock(rt_clock); -	/* Walk through the dirty map and eliminate tiles that-	   really aren't dirty */-	row = vs->ds->data;-	old_row = vs->old_data;--	for (y = 0; y < vs->ds->height; y++) {-	    if (vs->dirty_row[y] & width_mask) {-		int x;-		char *ptr, *old_ptr;--		ptr = row;-		old_ptr = old_row;--		for (x = 0; x < X2DP_UP(vs, vs->ds->width); x++) {-		    if (vs->dirty_row[y] & (1ULL << x)) {-			if (memcmp(old_ptr, ptr, tile_bytes)) {-			    vs->has_update = 1;-			    vs->update_row[y] |= (1ULL << x);-			    memcpy(old_ptr, ptr, tile_bytes);-			}-			vs->dirty_row[y] &= ~(1ULL << x);-		    }+    if (vs->width != DP2X(vs, DIRTY_PIXEL_BITS))+	width_mask = (1ULL << X2DP_UP(vs, vs->ds->width)) - 1;+    else+	width_mask = ~(0ULL); -		    ptr += tile_bytes;-		    old_ptr += tile_bytes;-		}-	    }+    /* Walk through the dirty map and eliminate tiles that really+       aren't dirty */+    row = vs->ds->data;+    old_row = vs->old_data; -	    row += vs->ds->linesize;-	    old_row += vs->ds->linesize;-	}+    for (y = 0; y < vs->ds->height; y++) {+	if (vs->dirty_row[y] & width_mask) {+	    int x;+	    char *ptr, *old_ptr; -	if (!vs->has_update || vs->visible_y >= vs->ds->height ||-	    vs->visible_x >= vs->ds->width)-	    return;+	    ptr = row;+	    old_ptr = old_row; -	/* Count rectangles */-	n_rectangles = 0;-	vnc_write_u8(vs, 0);  /* msg id */-	vnc_write_u8(vs, 0);-	saved_offset = vs->output.offset;-	vnc_write_u16(vs, 0);+	    for (x = 0; x < X2DP_UP(vs, vs->ds->width); x++) {+		if (vs->dirty_row[y] & (1ULL << x)) {+		    if (memcmp(old_ptr, ptr, tile_bytes)) {+			vs->has_update = 1;+			vs->update_row[y] |= (1ULL << x);+			memcpy(old_ptr, ptr, tile_bytes);+		    }+		    vs->dirty_row[y] &= ~(1ULL << x);+		} -	maxy = vs->visible_y + vs->visible_h;-	if (maxy > vs->ds->height)-	    maxy = vs->ds->height;-	maxx = vs->visible_x + vs->visible_w;-	if (maxx > vs->ds->width)-	    maxx = vs->ds->width;+		ptr += tile_bytes;+		old_ptr += tile_bytes;+	    }+	}+  +	row += vs->ds->linesize;+	old_row += vs->ds->linesize;+    } -	for (y = vs->visible_y; y < maxy; y++) {-	    int x;-	    int last_x = -1;-	    for (x = X2DP_DOWN(vs, vs->visible_x);-		 x < X2DP_UP(vs, maxx); x++) {-		if (vs->update_row[y] & (1ULL << x)) {-		    if (last_x == -1)-			last_x = x;-		    vs->update_row[y] &= ~(1ULL << x);-		} else {-		    if (last_x != -1) {-			int h = find_update_height(vs, y, maxy, last_x, x);+    if (!vs->has_update || vs->visible_y >= vs->ds->height ||+	vs->visible_x >= vs->ds->width)+	goto backoff;++    /* Count rectangles */+    n_rectangles = 0;+    vnc_write_u8(vs, 0);  /* msg id */+    vnc_write_u8(vs, 0);+    saved_offset = vs->output.offset;+    vnc_write_u16(vs, 0);+    +    maxy = vs->visible_y + vs->visible_h;+    if (maxy > vs->ds->height)+	maxy = vs->ds->height;+    maxx = vs->visible_x + vs->visible_w;+    if (maxx > vs->ds->width)+	maxx = vs->ds->width;++    for (y = vs->visible_y; y < maxy; y++) {+	int x;+	int last_x = -1;+	for (x = X2DP_DOWN(vs, vs->visible_x);+	     x < X2DP_UP(vs, maxx); x++) {+	    if (vs->update_row[y] & (1ULL << x)) {+		if (last_x == -1)+		    last_x = x;+		vs->update_row[y] &= ~(1ULL << x);+	    } else {+		if (last_x != -1) {+		    int h = find_update_height(vs, y, maxy, last_x, x);+		    if (h != 0) { 			send_framebuffer_update(vs, DP2X(vs, last_x), y, 						DP2X(vs, (x - last_x)), h); 			n_rectangles++; 		    }-		    last_x = -1; 		}+		last_x = -1; 	    }-	    if (last_x != -1) {-		int h = find_update_height(vs, y, maxy, last_x, x);+	}+	if (last_x != -1) {+	    int h = find_update_height(vs, y, maxy, last_x, x);+	    if (h != 0) { 		send_framebuffer_update(vs, DP2X(vs, last_x), y, 					DP2X(vs, (x - last_x)), h); 		n_rectangles++; 	    } 	}-	vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;-	vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;+    }+    vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;+    vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF; -	vs->has_update = 0;-	vs->need_update = 0;-	vnc_flush(vs);-	vs->slow_client = 0;-    } else-	vs->slow_client = 1;+    if (n_rectangles == 0)+	goto backoff;++    vs->has_update = 0;+    vnc_flush(vs);+    vs->last_update_time = now;++    vs->timer_interval /= 2;+    if (vs->timer_interval < VNC_REFRESH_INTERVAL_BASE)+	vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;++    return;++ backoff:+    /* No update -> back off a bit */+    vs->timer_interval += VNC_REFRESH_INTERVAL_INC;+    if (vs->timer_interval > VNC_REFRESH_INTERVAL_MAX) {+	vs->timer_interval = VNC_REFRESH_INTERVAL_MAX;+	if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL) {+	    /* Send a null update.  If the client is no longer+	       interested (e.g. minimised) it'll ignore this, and we+	       can stop scanning the buffer until it sends another+	       update request. */+	    /* It turns out that there's a bug in realvncviewer 4.1.2+	       which means that if you send a proper null update (with+	       no update rectangles), it gets a bit out of sync and+	       never sends any further requests, regardless of whether+	       it needs one or not.  Fix this by sending a single 1x1+	       update rectangle instead. */+	    vnc_write_u8(vs, 0);+	    vnc_write_u8(vs, 0);+	    vnc_write_u16(vs, 1);+	    send_framebuffer_update(vs, 0, 0, 1, 1);+	    vnc_flush(vs);+	    vs->last_update_time = now;+	    return;+	}+    }+    qemu_mod_timer(vs->timer, now + vs->timer_interval);+    return; }  static void vnc_update_client(void *opaque)@@ -589,8 +637,10 @@  static void vnc_timer_init(VncState *vs) {-    if (vs->timer == NULL)+    if (vs->timer == NULL) { 	vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);+	vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;+    } }  static void vnc_dpy_refresh(DisplayState *ds)@@ -650,7 +700,6 @@ 	vs->csock = -1; 	buffer_reset(&vs->input); 	buffer_reset(&vs->output);-	vs->need_update = 0; 	return 0;     }     return ret;@@ -957,7 +1006,6 @@ 				       int x_position, int y_position, 				       int w, int h) {-    vs->need_update = 1;     if (!incremental) 	framebuffer_set_updated(vs, x_position, y_position, w, h);     vs->visible_x = x_position;@@ -1087,6 +1135,7 @@ {     int i;     uint16_t limit;+    int64_t now;      switch (data[0]) {     case 0:@@ -1130,12 +1179,18 @@ 	if (len == 1) 	    return 8; +	vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;+	qemu_advance_timer(vs->timer,+			   qemu_get_clock(rt_clock) + vs->timer_interval); 	key_event(vs, read_u8(data, 1), read_u32(data, 4)); 	break;     case 5: 	if (len == 1) 	    return 6; +	vs->timer_interval = VNC_REFRESH_INTERVAL_BASE;+	qemu_advance_timer(vs->timer,+			   qemu_get_clock(rt_clock) + vs->timer_interval); 	pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4)); 	break;     case 6:Index: ioemu/vl.c===================================================================--- ioemu.orig/vl.c	2007-05-10 15:18:01.000000000 +0100+++ ioemu/vl.c	2007-05-10 15:18:58.000000000 +0100@@ -811,6 +811,12 @@     } } +void qemu_advance_timer(QEMUTimer *ts, int64_t expire_time)+{+    if (ts->expire_time > expire_time || !qemu_timer_pending(ts))+	qemu_mod_timer(ts, expire_time);+}+ /* modify the current timer so that it will be fired when current_time    >= expire_time. The corresponding callback will be called. */ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)Index: ioemu/vl.h===================================================================--- ioemu.orig/vl.h	2007-05-10 15:18:01.000000000 +0100+++ ioemu/vl.h	2007-05-10 15:18:58.000000000 +0100@@ -441,6 +441,7 @@ void qemu_free_timer(QEMUTimer *ts); void qemu_del_timer(QEMUTimer *ts); void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);+void qemu_advance_timer(QEMUTimer *ts, int64_t expire_time); int qemu_timer_pending(QEMUTimer *ts);  extern int64_t ticks_per_sec;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -