- SET_PIXEL() in blt.h - this was byte swapping the destination value.
The RFB spec says byte swapping is done on the source value. So I've
updated all callers to do swapping before passing in the source pixel
and removed the SWAP() call from SET_PIXEL() itself
- Rich cursor - this was not correctly calculating pixel shifts in the
mixed endian client/server scenario. I've updated it to use the same
logic as done in gvnc_set_local(), except with fixed 32bpp RGB format
for the local source, since that's what GdkPixbuf requires
- Rich cursor - not applying alpha mask on big endian machines - it was
masing the high bits instead of low bits.
- gvnc_set_local() - bogus code to take account of endianness when
calculating pixel shits. You can't take account of endianness in pixel
shifts alone because in 16 bpp format, the green component spans two
bytes. This bogus code is simply removed - byte swapping is done
correctly by caller of SET_PIXEL() now.
- gdk_drawable_get_visual() returns wrong visual in BGR pixelformat
desktops, so use gdk_screen_get_system_visual() instead.
I've tested
- 24bpp local LE client -> 16 bpp BE server
- 24bpp local LE client -> 24 bpp BE server
- 24bpp local LE client -> 16 bpp LE server
- 24bpp local LE client -> 24 bpp LE server
- 24bpp local LE client -> 16 bpp LE server BGR pixelformat
- 24bpp local LE client -> 24 bpp LE server BGR pixelformat
- 24bpp local LE client -> 16 bpp BE server -> 16 bpp LE server
- 24bpp local LE client -> 16 bpp BE server -> 24 bpp LE server
- 24bpp local LE client -> 24 bpp BE server -> 16 bpp LE server
- 24bpp local LE client -> 24 bpp BE server -> 24 bpp LE server
- 24bpp local LE client -> 16 bpp BE server -> 16 bpp LE server -> 24 bpp BE server
- 24bpp local LE client -> 16 bpp BE server -> 24 bpp LE server -> 24 bpp BE server
- 24bpp local LE client -> 24 bpp BE server -> 16 bpp LE server -> 16 bpp BE server
- 24bpp local LE client -> 24 bpp BE server -> 24 bpp LE server -> 16 bpp BE server
Which I think is a reasonable number of combinations & recursive tests :-)
Dan
diff -r fb8ab9818527 src/blt.h
--- a/src/blt.h Fri Mar 07 11:24:19 2008 -0600
+++ b/src/blt.h Tue Mar 18 17:57:26 2008 -0400
@@ -16,7 +16,7 @@
#define RGB24_BLIT SPLICE(gvnc_rgb24_blt_, SUFFIX())
#define TIGHT_COMPUTE_PREDICTED SPLICE(gvnc_tight_compute_predicted_, SUFFIX())
#define TIGHT_SUM_PIXEL SPLICE(gvnc_tight_sum_pixel_, SUFFIX())
-#define SWAP(gvnc, pixel) SPLICE(gvnc_swap_, DST)(gvnc, pixel)
+#define SWAP(gvnc, pixel) SPLICE(gvnc_swap_, SRC)(gvnc, pixel)
#define COMPONENT(color, pixel) ((SWAP(gvnc, pixel) >> gvnc->fmt.SPLICE(color, _shift) & gvnc->fmt.SPLICE(color, _max)))
static void FAST_FILL(struct gvnc *gvnc, src_pixel_t *sp,
@@ -41,18 +41,18 @@ static void FAST_FILL(struct gvnc *gvnc,
}
}
-static void SET_PIXEL(struct gvnc *gvnc, dst_pixel_t *dp, src_pixel_t *sp)
+static void SET_PIXEL(struct gvnc *gvnc, dst_pixel_t *dp, src_pixel_t sp)
{
- *dp = SWAP(gvnc, ((*sp >> gvnc->rrs) & gvnc->rm) << gvnc->rls
- | ((*sp >> gvnc->grs) & gvnc->gm) << gvnc->gls
- | ((*sp >> gvnc->brs) & gvnc->bm) << gvnc->bls);
+ *dp = ((sp >> gvnc->rrs) & gvnc->rm) << gvnc->rls
+ | ((sp >> gvnc->grs) & gvnc->gm) << gvnc->gls
+ | ((sp >> gvnc->brs) & gvnc->bm) << gvnc->bls;
}
static void SET_PIXEL_AT(struct gvnc *gvnc, int x, int y, src_pixel_t *sp)
{
dst_pixel_t *dp = (dst_pixel_t *)gvnc_get_local(gvnc, x, y);
- SET_PIXEL(gvnc, dp, sp);
+ SET_PIXEL(gvnc, dp, SWAP(gvnc, *sp));
}
static void FILL(struct gvnc *gvnc, src_pixel_t *sp,
@@ -66,7 +66,7 @@ static void FILL(struct gvnc *gvnc, src_
int j;
for (j = 0; j < width; j++) {
- SET_PIXEL(gvnc, dp, sp);
+ SET_PIXEL(gvnc, dp, SWAP(gvnc, *sp));
dp++;
}
dst += gvnc->local.linesize;
@@ -88,7 +88,7 @@ static void BLIT(struct gvnc *gvnc, uint
int j;
for (j = 0; j < w; j++) {
- SET_PIXEL(gvnc, dp, sp);
+ SET_PIXEL(gvnc, dp, SWAP(gvnc, *sp));
dp++;
sp++;
}
@@ -171,11 +171,36 @@ static void RICH_CURSOR_BLIT(struct gvnc
uint32_t *dst = (uint32_t *)pixbuf;
uint8_t *src = image;
uint8_t *alpha = mask;
- int rs, gs, bs;
+ int as, rs, gs, bs, n;
- rs = 24 - ((sizeof(src_pixel_t) * 8) - gvnc->fmt.red_shift);
- gs = 16 - (gvnc->fmt.red_shift - gvnc->fmt.green_shift);
- bs = 8 - (gvnc->fmt.green_shift - gvnc->fmt.blue_shift);
+ /*
+ * GdkPixbuf is always 32-bit RGB, so we can't use the precomputed
+ * left / right shift data from gvnc->{r,g,b}{r,l}s. The latter
+ * is set for the local display depth, which may be different
+ * to GdkPixbuf's fixed 32-bit RGBA
+ *
+ * This function isn't called often, so just re-compute them now
+ */
+
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+ as = 0;
+ rs = 8;
+ gs = 16;
+ bs = 24;
+#else
+ as = 24;
+ rs = 16;
+ gs = 8;
+ bs = 0;
+#endif
+
+ /* Then this adjusts for remote having less bpp than 32 */
+ for (n = 255 ; n > gvnc->fmt.red_max ; n>>= 1)
+ rs++;
+ for (n = 255 ; n > gvnc->fmt.green_max ; n>>= 1)
+ gs++;
+ for (n = 255 ; n > gvnc->fmt.blue_max ; n>>= 1)
+ bs++;
for (y1 = 0; y1 < height; y1++) {
src_pixel_t *sp = (src_pixel_t *)src;
@@ -186,7 +211,7 @@ static void RICH_CURSOR_BLIT(struct gvnc
| (COMPONENT(blue, *sp) << bs);
if ((mp[x1 / 8] >> (7 - (x1 % 8))) & 1)
- *dst |= 0xFF000000;
+ *dst |= (0xFF << as);
dst++;
sp++;
@@ -209,6 +234,11 @@ static void RGB24_BLIT(struct gvnc *gvnc
uint8_t *sp = data;
for (i = 0; i < width; i++) {
+ /*
+ * We use gvnc->fmt.XXX_shift instead of usual gvnc->Xls
+ * because the source pixel component is a full 8 bits in
+ * size, and so doesn't need the adjusted shift
+ */
*dp = (((sp[0] * gvnc->fmt.red_max) / 255) << gvnc->fmt.red_shift) |
(((sp[1] * gvnc->fmt.green_max) / 255) << gvnc->fmt.green_shift) |
(((sp[2] * gvnc->fmt.blue_max) / 255) << gvnc->fmt.blue_shift);
diff -r fb8ab9818527 src/gvnc.c
--- a/src/gvnc.c Fri Mar 07 11:24:19 2008 -0600
+++ b/src/gvnc.c Tue Mar 18 17:57:26 2008 -0400
@@ -3022,18 +3022,6 @@ gboolean gvnc_set_local(struct gvnc *gvn
gvnc->gls = gvnc->local.green_shift;
gvnc->bls = gvnc->local.blue_shift;
-
- /* This adjusts for server/client endianness mismatch */
- if (G_BYTE_ORDER != gvnc->fmt.byte_order) {
- gvnc->rrs = gvnc->fmt.bits_per_pixel - gvnc->rrs - (gvnc->fmt.bits_per_pixel - gvnc->fmt.depth);
- gvnc->grs = gvnc->fmt.bits_per_pixel - gvnc->grs - (gvnc->fmt.bits_per_pixel - gvnc->fmt.depth);
- gvnc->brs = gvnc->fmt.bits_per_pixel - gvnc->brs - (gvnc->fmt.bits_per_pixel - gvnc->fmt.depth);
-
- GVNC_DEBUG("Flipped shifts red: %3d, green: %3d, blue: %3d\n",
- gvnc->rrs, gvnc->grs, gvnc->brs);
- }
-
-
/* This adjusts for remote having more bpp than local */
for (n = gvnc->fmt.red_max; n > gvnc->local.red_mask ; n>>= 1)
gvnc->rrs++;
diff -r fb8ab9818527 src/vncdisplay.c
--- a/src/vncdisplay.c Fri Mar 07 11:24:19 2008 -0600
+++ b/src/vncdisplay.c Tue Mar 18 17:57:26 2008 -0400
@@ -750,9 +750,17 @@ static void setup_gdk_image(VncDisplay *
VncDisplayPrivate *priv = obj->priv;
GdkVisual *visual;
- visual = gdk_drawable_get_visual(GTK_WIDGET(obj)->window);
+ visual = gdk_screen_get_system_visual(gdk_screen_get_default());
priv->image = gdk_image_new(GDK_IMAGE_FASTEST, visual, width, height);
+ GVNC_DEBUG("Visual mask: %3d %3d %3d\n shift: %3d %3d %3d\n",
+ visual->red_mask,
+ visual->green_mask,
+ visual->blue_mask,
+ visual->red_shift,
+ visual->green_shift,
+ visual->blue_shift);
+
priv->fb.red_mask = visual->red_mask >> visual->red_shift;
priv->fb.green_mask = visual->green_mask >> visual->green_shift;
priv->fb.blue_mask = visual->blue_mask >> visual->blue_shift;