Page MenuHomeFreeBSD

D46402.id142366.diff
No OneTemporary

D46402.id142366.diff

diff --git a/usr.sbin/bhyve/rfb.c b/usr.sbin/bhyve/rfb.c
--- a/usr.sbin/bhyve/rfb.c
+++ b/usr.sbin/bhyve/rfb.c
@@ -139,6 +139,11 @@
uint32_t *crc; /* WxH crc cells */
uint32_t *crc_tmp; /* buffer to store single crc row */
int crc_width, crc_height;
+
+ uint32_t *pixrow;
+ uint8_t red_shift;
+ uint8_t green_shift;
+ uint8_t blue_shift;
};
struct rfb_pixfmt {
@@ -179,6 +184,10 @@
#define RFB_MAX_HEIGHT 1200
#define RFB_ZLIB_BUFSZ RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4
+#define PIXEL_RED_SHIFT 16
+#define PIXEL_GREEN_SHIFT 8
+#define PIXEL_BLUE_SHIFT 0
+
/* percentage changes to screen before sending the entire screen */
#define RFB_SEND_ALL_THRESH 25
@@ -261,9 +270,9 @@
sinfo.pixfmt.red_max = htons(255);
sinfo.pixfmt.green_max = htons(255);
sinfo.pixfmt.blue_max = htons(255);
- sinfo.pixfmt.red_shift = 16;
- sinfo.pixfmt.green_shift = 8;
- sinfo.pixfmt.blue_shift = 0;
+ sinfo.pixfmt.red_shift = PIXEL_RED_SHIFT;
+ sinfo.pixfmt.green_shift = PIXEL_GREEN_SHIFT;
+ sinfo.pixfmt.blue_shift = PIXEL_BLUE_SHIFT;
sinfo.pixfmt.pad[0] = 0;
sinfo.pixfmt.pad[1] = 0;
sinfo.pixfmt.pad[2] = 0;
@@ -318,9 +327,55 @@
rfb_recv_set_pixfmt_msg(struct rfb_softc *rc __unused, int cfd)
{
struct rfb_pixfmt_msg pixfmt_msg;
+ uint32_t *pixelp;
+ uint8_t red_shift, green_shift, blue_shift;
(void)stream_read(cfd, (uint8_t *)&pixfmt_msg + 1,
sizeof(pixfmt_msg) - 1);
+
+ /*
+ * The framebuffer is fixed at 32 bit and orders the colors
+ * as RGB bytes. However, some VNC clients request a different
+ * ordering. We will still require the same bit depth and size
+ * but allow the colors to be shifted when sent to the client.
+ */
+ if ((pixfmt_msg.pixfmt.bpp != 32) || (pixfmt_msg.pixfmt.truecolor != 1))
+ return;
+
+ /* Check for valid max values */
+ if ((htons(pixfmt_msg.pixfmt.red_max) != 255) ||
+ (htons(pixfmt_msg.pixfmt.green_max) != 255) ||
+ (htons(pixfmt_msg.pixfmt.blue_max) != 255))
+ return;
+
+ red_shift = pixfmt_msg.pixfmt.red_shift;
+ green_shift = pixfmt_msg.pixfmt.green_shift;
+ blue_shift = pixfmt_msg.pixfmt.blue_shift;
+
+ /* Check if this is already our default shift */
+ if ((red_shift == PIXEL_RED_SHIFT) &&
+ (green_shift == PIXEL_GREEN_SHIFT) &&
+ (blue_shift == PIXEL_BLUE_SHIFT))
+ return;
+
+ /* Check shifts are 8 bit aligned */
+ if (((red_shift & 0x7) != 0) ||
+ ((green_shift & 0x7) != 0) ||
+ ((blue_shift & 0x7) != 0))
+ return;
+
+ rc->red_shift = red_shift;
+ rc->green_shift = green_shift;
+ rc->blue_shift = blue_shift;
+
+ /* Allocate a pixel array to contain the swapped values */
+ if (rc->pixrow != NULL)
+ return;
+
+ /* Will be using rfb_send_rect which does a row at a time */
+ pixelp = malloc(RFB_MAX_WIDTH * sizeof(uint32_t));
+ if (pixelp != NULL)
+ rc->pixrow = pixelp;
}
static void
@@ -388,6 +443,30 @@
sizeof(struct rfb_srvr_updt_msg));
}
+static uint32_t *
+rfb_adjust_pixels(struct rfb_softc *rc, uint32_t *gcptr, int width, int height)
+{
+ uint32_t *zp;
+ uint32_t red, green, blue;
+ int i;
+
+ /* If no pixrow allocated, send in server format */
+ if (rc->pixrow == NULL) {
+ return (gcptr);
+ }
+
+ for (i = 0, zp = rc->pixrow; i < width * height; i++, zp++, gcptr++) {
+ red = (*gcptr >> 16) & 0xFF;
+ green = (*gcptr >> 8) & 0xFF;
+ blue = (*gcptr & 0xFF);
+ *zp = (red << rc->red_shift) |
+ (green << rc->green_shift) |
+ (blue << rc->blue_shift);
+ }
+
+ return (rc->pixrow);
+}
+
static int
rfb_send_rect(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc,
int x, int y, int w, int h)
@@ -395,8 +474,8 @@
struct rfb_srvr_rect_hdr srect_hdr;
unsigned long zlen;
ssize_t nwrite, total;
- int err;
- uint32_t *p;
+ int err, width;
+ uint32_t *p, *pixelp;
uint8_t *zbufp;
/*
@@ -409,6 +488,7 @@
srect_hdr.width = htons(w);
srect_hdr.height = htons(h);
+ width = w;
h = y + h;
w *= sizeof(uint32_t);
if (rc->enc_zlib_ok) {
@@ -416,7 +496,8 @@
rc->zstream.total_in = 0;
rc->zstream.total_out = 0;
for (p = &gc->data[y * gc->width + x]; y < h; y++) {
- rc->zstream.next_in = (Bytef *)p;
+ pixelp = rfb_adjust_pixels(rc, p, width, 1);
+ rc->zstream.next_in = (Bytef *)pixelp;
rc->zstream.avail_in = w;
rc->zstream.next_out = (Bytef *)zbufp;
rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16 -
@@ -452,7 +533,8 @@
total = 0;
zbufp = rc->zbuf;
for (p = &gc->data[y * gc->width + x]; y < h; y++) {
- memcpy(zbufp, p, w);
+ pixelp = rfb_adjust_pixels(rc, p, width, 1);
+ memcpy(zbufp, pixelp, w);
zbufp += w;
total += w;
p += gc->width;
@@ -491,6 +573,11 @@
if (nwrite <= 0)
return (nwrite);
+ if (rc->pixrow != NULL) {
+ return (rfb_send_rect(rc, cfd, gc, 0, 0,
+ gc->width, gc->height));
+ }
+
/* Rectangle header */
srect_hdr.x = 0;
srect_hdr.y = 0;
@@ -1229,6 +1316,8 @@
close(rc->sfd);
free(rc->crc);
free(rc->crc_tmp);
+ free(rc->zbuf);
+ free(rc->pixrow);
free(rc);
return (-1);
}

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 8, 9:46 PM (11 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28501927
Default Alt Text
D46402.id142366.diff (4 KB)

Event Timeline