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; }