Module Name:    src
Committed By:   jmcneill
Date:           Fri Dec 30 09:36:02 UTC 2011

Modified Files:
        src/sys/arch/usermode/include: thunk.h
        src/sys/arch/usermode/usermode: thunk.c

Log Message:
optimize rfb updates by allowing queueing of multiple update messages,
dropping duplicates, and transmitting them in batches


To generate a diff of this commit:
cvs rdiff -u -r1.47 -r1.48 src/sys/arch/usermode/include/thunk.h
cvs rdiff -u -r1.56 -r1.57 src/sys/arch/usermode/usermode/thunk.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/usermode/include/thunk.h
diff -u src/sys/arch/usermode/include/thunk.h:1.47 src/sys/arch/usermode/include/thunk.h:1.48
--- src/sys/arch/usermode/include/thunk.h:1.47	Thu Dec 29 21:22:49 2011
+++ src/sys/arch/usermode/include/thunk.h	Fri Dec 30 09:36:01 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: thunk.h,v 1.47 2011/12/29 21:22:49 jmcneill Exp $ */
+/* $NetBSD: thunk.h,v 1.48 2011/12/30 09:36:01 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2011 Jared D. McNeill <jmcne...@invisible.ca>
@@ -191,10 +191,11 @@ typedef struct {
 } thunk_rfb_event_t;
 
 typedef struct {
-	bool			pending;
 	uint16_t		x, y, w, h;
 } thunk_rfb_update_t;
 
+#define THUNK_RFB_QUEUELEN	128
+
 typedef struct {
 	int			sockfd;
 	int			clientfd;
@@ -207,7 +208,8 @@ typedef struct {
 	uint8_t			depth;
 	char			name[64];
 	uint8_t			*framebuf;
-	thunk_rfb_update_t	update;
+	thunk_rfb_update_t	update[THUNK_RFB_QUEUELEN];
+	unsigned int		nupdates;
 } thunk_rfb_t;
 
 int	thunk_rfb_open(thunk_rfb_t *, uint16_t);

Index: src/sys/arch/usermode/usermode/thunk.c
diff -u src/sys/arch/usermode/usermode/thunk.c:1.56 src/sys/arch/usermode/usermode/thunk.c:1.57
--- src/sys/arch/usermode/usermode/thunk.c:1.56	Thu Dec 29 21:22:49 2011
+++ src/sys/arch/usermode/usermode/thunk.c	Fri Dec 30 09:36:02 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: thunk.c,v 1.56 2011/12/29 21:22:49 jmcneill Exp $ */
+/* $NetBSD: thunk.c,v 1.57 2011/12/30 09:36:02 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2011 Jared D. McNeill <jmcne...@invisible.ca>
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 #ifdef __NetBSD__
-__RCSID("$NetBSD: thunk.c,v 1.56 2011/12/29 21:22:49 jmcneill Exp $");
+__RCSID("$NetBSD: thunk.c,v 1.57 2011/12/30 09:36:02 jmcneill Exp $");
 #endif
 
 #include <sys/types.h>
@@ -970,44 +970,68 @@ thunk_rfb_handshake(thunk_rfb_t *rfb)
 static void
 thunk_rfb_send_pending(thunk_rfb_t *rfb)
 {
+	thunk_rfb_update_t *update;
 	uint8_t rfb_update[16];
-	uint8_t *p = rfb_update;
-	uint16_t x, y, w, h;
+	uint8_t *p;
+	unsigned int n;
 	ssize_t len;
 
-	if (rfb->connected == false || rfb->update.pending == false)
+	if (rfb->connected == false || rfb->nupdates == 0)
 		return;
 
-	x = rfb->update.x;
-	y = rfb->update.y;
-	w = rfb->update.w;
-	h = rfb->update.h;
-	rfb->update.pending = false;
+	/* If we have too many updates queued, just send a single update */
+	if (rfb->nupdates >= __arraycount(rfb->update)) {
+		rfb->nupdates = 1;
+		rfb->update[0].x = 0;
+		rfb->update[0].y = 0;
+		rfb->update[0].w = rfb->width;
+		rfb->update[0].h = rfb->height;
+	}
+
+#ifdef RFB_DEBUG
+	fprintf(stdout, "rfb: sending %d updates\n", rfb->nupdates);
+#endif
 
+	p = rfb_update;
 	*(uint8_t *)p = 0;		p += 1;		/* FramebufferUpdate */
 	*(uint8_t *)p = 0;		p += 1;		/* padding */
-	*(uint16_t *)p = htons(1);	p += 2;		/* # rects */
-	*(uint16_t *)p = htons(x);	p += 2;
-	*(uint16_t *)p = htons(y);	p += 2;
-	*(uint16_t *)p = htons(w);	p += 2;
-	*(uint16_t *)p = htons(h);	p += 2;
-	*(uint32_t *)p = htonl(0);	p += 4;		/* Raw encoding */
+	*(uint16_t *)p = htons(rfb->nupdates);	p += 2;	/* # rects */
 
-	len = send(rfb->clientfd, rfb_update, sizeof(rfb_update),
-	    MSG_NOSIGNAL);
+	len = send(rfb->clientfd, rfb_update, 4, MSG_NOSIGNAL);
 	if (len <= 0)
 		goto disco;
 
-	p = rfb->framebuf + (y * rfb->width * (rfb->depth / 8)) +
-	    (x * (rfb->depth / 8));
-	while (h-- > 0) {
-		len = send(rfb->clientfd, p, w * (rfb->depth / 8),
-		    MSG_NOSIGNAL);
+	for (n = 0; n < rfb->nupdates; n++) {
+		p = rfb_update;
+		update = &rfb->update[n];
+		*(uint16_t *)p = htons(update->x);	p += 2;
+		*(uint16_t *)p = htons(update->y);	p += 2;
+		*(uint16_t *)p = htons(update->w);	p += 2;
+		*(uint16_t *)p = htons(update->h);	p += 2;
+		*(uint32_t *)p = htonl(0);		p += 4;	/* Raw enc */
+
+#ifdef RFB_DEBUG
+		fprintf(stdout, "rfb:   [%u] x=%d y=%d w=%d h=%d\n",
+		    n, update->x, update->y, update->w, update->h);
+#endif
+
+		len = send(rfb->clientfd, rfb_update, 12, MSG_NOSIGNAL);
 		if (len <= 0)
 			goto disco;
-		p += rfb->width * (rfb->depth / 8);
+
+		p = rfb->framebuf + (update->y * rfb->width * (rfb->depth / 8))
+		    + (update->x * (rfb->depth / 8));
+		while (update->h-- > 0) {
+			len = send(rfb->clientfd, p,
+			    update->w * (rfb->depth / 8), MSG_NOSIGNAL);
+			if (len <= 0)
+				goto disco;
+			p += rfb->width * (rfb->depth / 8);
+		}
 	}
 
+	rfb->nupdates = 0;
+
 	return;
 
 disco:
@@ -1059,6 +1083,7 @@ thunk_rfb_poll(thunk_rfb_t *rfb, thunk_r
 		}
 
 		rfb->connected = true;
+		rfb->nupdates = 0;
 		thunk_rfb_update(rfb, 0, 0, rfb->width, rfb->height);
 	}
 
@@ -1124,18 +1149,29 @@ thunk_rfb_poll(thunk_rfb_t *rfb, thunk_r
 void
 thunk_rfb_update(thunk_rfb_t *rfb, int x, int y, int w, int h)
 {
-	if (rfb->update.pending) {
-		/* pending update, just redraw the whole screen */
-		rfb->update.x = 0;
-		rfb->update.y = 0;
-		rfb->update.w = rfb->width;
-		rfb->update.h = rfb->height;
-	} else {
-		/* try to only update the requested rectangle */
-		rfb->update.x = x;
-		rfb->update.y = y;
-		rfb->update.w = w;
-		rfb->update.h = h;
+	thunk_rfb_update_t *update = NULL;
+	unsigned int n;
+
+	/* if the queue is full, just return */
+	if (rfb->nupdates >= __arraycount(rfb->update))
+		return;
+
+	/* no sense in queueing duplicate updates */
+	for (n = 0; n < rfb->nupdates; n++) {
+		if (rfb->update[n].x == x && rfb->update[n].y == y &&
+		    rfb->update[n].w == w && rfb->update[n].h == h)
+			return;
 	}
-	rfb->update.pending = true;
+
+#ifdef RFB_DEBUG
+	fprintf(stdout, "rfb: queue slot %d, x=%d y=%d w=%d h=%d\n",
+	    rfb->nupdates, x, y, w, h);
+#endif
+
+	/* add the update request to the queue */
+	update = &rfb->update[rfb->nupdates++];
+	update->x = x;
+	update->y = y;
+	update->w = w;
+	update->h = h;
 }

Reply via email to