And this is the second part that makes this weird 32bpp mode work. Remember, this is the default 32bpp mode of VNC server on FreeBSD: bgrabb, i.e. 10 bits for blue, 11 bits for green and 11 bits for red r=0x7ff g=0x3ff800, b=0xffc00000 The problem in palette.c was that we assumed that a given color would be coded in 8bits or less. But, IIRC, X allows for up to 16bits (or even 32?), per individual color component. The problem is that when you have a windows color with 8 bits per component and you have to convert it to 10 bits you cannot shift in the same direction as if you were converting it to just 5 bits. With this patch we should support up to 16 bits per color component with no significant loss of speed in the regular case. Changelog: François Gouget <fgouget@codeweavers.com> * graphics/x11drv/palette.c Handle more than 8 bits per color component -- François Gouget fgouget@codeweavers.com
Index: graphics/x11drv/palette.c =================================================================== RCS file: /home/wine/wine/graphics/x11drv/palette.c,v retrieving revision 1.27 diff -u -r1.27 palette.c --- graphics/x11drv/palette.c 2001/10/17 17:45:33 1.27 +++ graphics/x11drv/palette.c 2001/12/20 00:31:23 @@ -50,16 +50,20 @@ Colormap X11DRV_PALETTE_PaletteXColormap = 0; UINT16 X11DRV_PALETTE_PaletteFlags = 0; -static int X11DRV_PALETTE_Redshift = 0; /* to handle abortive X11DRV_PALETTE_VIRTUAL visuals */ -static int X11DRV_PALETTE_Redscale = 0; -static int X11DRV_PALETTE_Redmax = 0; -static int X11DRV_PALETTE_Greenshift = 0; -static int X11DRV_PALETTE_Greenscale = 0; -static int X11DRV_PALETTE_Greenmax = 0; -static int X11DRV_PALETTE_Blueshift = 0; -static int X11DRV_PALETTE_Bluescale = 0; -static int X11DRV_PALETTE_Bluemax = 0; -static int X11DRV_PALETTE_Graymax = 0; +typedef struct { + int shift; + int scale; + int max; +} ColorShifts; + +/* initialize to zero to handle abortive X11DRV_PALETTE_VIRTUAL visuals */ +static ColorShifts X11DRV_PALETTE_PRed = {0,0,0}; +static ColorShifts X11DRV_PALETTE_LRed = {0,0,0}; +static ColorShifts X11DRV_PALETTE_PGreen = {0,0,0}; +static ColorShifts X11DRV_PALETTE_LGreen = {0,0,0}; +static ColorShifts X11DRV_PALETTE_PBlue = {0,0,0}; +static ColorShifts X11DRV_PALETTE_LBlue = {0,0,0}; +static int X11DRV_PALETTE_Graymax = 0; static int palette_size; @@ -87,7 +91,7 @@ static BOOL X11DRV_PALETTE_BuildPrivateMap(void); static BOOL X11DRV_PALETTE_BuildSharedMap(void); -static void X11DRV_PALETTE_ComputeShifts(unsigned long maskbits, int *shift, int *max, int *scale); +static void X11DRV_PALETTE_ComputeShifts(unsigned long maskbits, ColorShifts *physical, ColorShifts *to_logical); static void X11DRV_PALETTE_FillDefaultColors(void); static void X11DRV_PALETTE_FormatSystemPalette(void); static BOOL X11DRV_PALETTE_CheckSysColor(COLORREF c); @@ -191,10 +195,10 @@ X11DRV_PALETTE_PaletteXColormap = TSXCreateColormap(gdi_display, root_window, visual, AllocNone); X11DRV_PALETTE_PaletteFlags |= X11DRV_PALETTE_FIXED; - X11DRV_PALETTE_ComputeShifts(visual->red_mask, &X11DRV_PALETTE_Redshift, &X11DRV_PALETTE_Redmax, &X11DRV_PALETTE_Redscale); - X11DRV_PALETTE_ComputeShifts(visual->green_mask, &X11DRV_PALETTE_Greenshift, &X11DRV_PALETTE_Greenmax, &X11DRV_PALETTE_Greenscale); - X11DRV_PALETTE_ComputeShifts(visual->blue_mask, &X11DRV_PALETTE_Blueshift, &X11DRV_PALETTE_Bluemax, &X11DRV_PALETTE_Bluescale); - break; + X11DRV_PALETTE_ComputeShifts(visual->red_mask, &X11DRV_PALETTE_PRed, &X11DRV_PALETTE_LRed); + X11DRV_PALETTE_ComputeShifts(visual->green_mask, &X11DRV_PALETTE_PGreen, &X11DRV_PALETTE_LGreen); + X11DRV_PALETTE_ComputeShifts(visual->blue_mask, &X11DRV_PALETTE_PBlue, &X11DRV_PALETTE_LBlue); + break; } } @@ -240,26 +244,45 @@ * * Calculate conversion parameters for direct mapped visuals */ -static void X11DRV_PALETTE_ComputeShifts(unsigned long maskbits, int *shift, int *max, int *scale) +static void X11DRV_PALETTE_ComputeShifts(unsigned long maskbits, ColorShifts *physical, ColorShifts *to_logical) { int i; if (maskbits==0) { - *shift=0; - *max=0; + physical->shift=0; + physical->scale=0; + physical->max=0; + to_logical->shift=0; + to_logical->scale=0; + to_logical->max=0; return; } for(i=0;!(maskbits&1);i++) maskbits >>= 1; - *shift = i; - *max = maskbits; + physical->shift = i; + physical->max = maskbits; for(i=0;maskbits!=0;i++) maskbits >>= 1; - *scale = i; + physical->scale = i; + + if (physical->scale>8) + { + /* On FreeBSD, VNC's default 32bpp mode is bgrabb (ffc00000,3ff800,7ff)! + * So we adjust the shifts to also normalize the color fields to + * the Win32 standard of 8 bits per color. + */ + to_logical->shift=physical->shift+(physical->scale-8); + to_logical->scale=8; + to_logical->max=0xff; + } else { + to_logical->shift=physical->shift; + to_logical->scale=physical->scale; + to_logical->max=physical->max; + } } /*********************************************************************** @@ -625,11 +648,11 @@ if( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL ) { - if (X11DRV_PALETTE_Redmax != 255) no_r = (red * X11DRV_PALETTE_Redmax) / 255; - if (X11DRV_PALETTE_Greenmax != 255) no_g = (green * X11DRV_PALETTE_Greenmax) / 255; - if (X11DRV_PALETTE_Bluemax != 255) no_b = (blue * X11DRV_PALETTE_Bluemax) / 255; + if (X11DRV_PALETTE_PRed.max != 255) no_r = (red * X11DRV_PALETTE_PRed.max) / 255; + if (X11DRV_PALETTE_PGreen.max != 255) no_g = (green * X11DRV_PALETTE_PGreen.max) / 255; + if (X11DRV_PALETTE_PBlue.max != 255) no_b = (blue * X11DRV_PALETTE_PBlue.max) / 255; - X11DRV_PALETTE_PaletteToXPixel[idx] = (no_r << X11DRV_PALETTE_Redshift) | (no_g << X11DRV_PALETTE_Greenshift) | (no_b << X11DRV_PALETTE_Blueshift); + X11DRV_PALETTE_PaletteToXPixel[idx] = (no_r << X11DRV_PALETTE_PRed.shift) | (no_g << X11DRV_PALETTE_PGreen.shift) | (no_b << X11DRV_PALETTE_PBlue.shift); } else if( !(X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) ) { @@ -696,15 +719,19 @@ if ( (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) && !X11DRV_PALETTE_Graymax ) { - color.red = (pixel >> X11DRV_PALETTE_Redshift) & X11DRV_PALETTE_Redmax; - color.green = (pixel >> X11DRV_PALETTE_Greenshift) & X11DRV_PALETTE_Greenmax; - color.blue = (pixel >> X11DRV_PALETTE_Blueshift) & X11DRV_PALETTE_Bluemax; - return RGB(color.red << (8-X11DRV_PALETTE_Redscale) | - color.red >> (2*X11DRV_PALETTE_Redscale-8), - color.green << (8-X11DRV_PALETTE_Greenscale) | - color.green >> (2*X11DRV_PALETTE_Greenscale-8), - color.blue << (8-X11DRV_PALETTE_Bluescale) | - color.blue >> (2*X11DRV_PALETTE_Bluescale-8)); + color.red = (pixel >> X11DRV_PALETTE_LRed.shift) & X11DRV_PALETTE_LRed.max; + if (X11DRV_PALETTE_LRed.scale<8) + color.red= color.red << (8-X11DRV_PALETTE_LRed.scale) | + color.red >> (2*X11DRV_PALETTE_LRed.scale-8); + color.green = (pixel >> X11DRV_PALETTE_LGreen.shift) & X11DRV_PALETTE_LGreen.max; + if (X11DRV_PALETTE_LGreen.scale<8) + color.green=color.green << (8-X11DRV_PALETTE_LGreen.scale) | + color.green >> (2*X11DRV_PALETTE_LGreen.scale-8); + color.blue = (pixel >> X11DRV_PALETTE_LBlue.shift) & X11DRV_PALETTE_LBlue.max; + if (X11DRV_PALETTE_LBlue.scale<8) + color.blue= color.blue << (8-X11DRV_PALETTE_LBlue.scale) | + color.blue >> (2*X11DRV_PALETTE_LBlue.scale-8); + return RGB(color.red,color.green,color.blue); } /* check if we can bypass X */ @@ -789,15 +816,24 @@ else { /* scale each individually and construct the TrueColor pixel value */ - if (X11DRV_PALETTE_Redscale != 8) - red = red >> (8-X11DRV_PALETTE_Redscale); - if (X11DRV_PALETTE_Greenscale != 8) - green = green >> (8-X11DRV_PALETTE_Greenscale); - if (X11DRV_PALETTE_Bluescale != 8) - blue = blue >> (8-X11DRV_PALETTE_Bluescale); + if (X11DRV_PALETTE_PRed.scale < 8) + red = red >> (8-X11DRV_PALETTE_PRed.scale); + else if (X11DRV_PALETTE_PRed.scale > 8) + red = red << (X11DRV_PALETTE_PRed.scale-8) | + red >> (16-X11DRV_PALETTE_PRed.scale); + if (X11DRV_PALETTE_PGreen.scale < 8) + green = green >> (8-X11DRV_PALETTE_PGreen.scale); + else if (X11DRV_PALETTE_PGreen.scale > 8) + green = green << (X11DRV_PALETTE_PGreen.scale-8) | + green >> (16-X11DRV_PALETTE_PGreen.scale); + if (X11DRV_PALETTE_PBlue.scale < 8) + blue = blue >> (8-X11DRV_PALETTE_PBlue.scale); + else if (X11DRV_PALETTE_PBlue.scale > 8) + blue = blue << (X11DRV_PALETTE_PBlue.scale-8) | + blue >> (16-X11DRV_PALETTE_PBlue.scale); GDI_ReleaseObj( hPal ); - return (red << X11DRV_PALETTE_Redshift) | (green << X11DRV_PALETTE_Greenshift) | (blue << X11DRV_PALETTE_Blueshift); + return (red << X11DRV_PALETTE_PRed.shift) | (green << X11DRV_PALETTE_PGreen.shift) | (blue << X11DRV_PALETTE_PBlue.shift); } } else