From: <mi...@pr...> - 2004-01-31 03:07:49
|
Update of /cvsroot/gc-linux/linux/drivers/video In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6902/drivers/video Modified Files: gamecubefb.c Log Message: Framebuffer colors are correct now. Thanks to Costis for his fixpoint conversion code. The framebuffer console text is still yellow - is that normal? Because Tux' colors are perfect... Index: gamecubefb.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/video/gamecubefb.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- gamecubefb.c 29 Jan 2004 01:02:49 -0000 1.2 +++ gamecubefb.c 29 Jan 2004 22:13:24 -0000 1.3 @@ -47,6 +47,79 @@ static void (*pmi_start)(void); static void (*pmi_pal)(void); + +/* --------------------------------------------------------------------- */ +// This is Costis' RGB to YCbYCr conversion code. This looks like a bad +// hack, because we make the original cfbimgblit.c encode RGB 5:5:5 pixel +// data and convert it into YCbYCr on every write of an int into the +// framebuffer. But this is also quite good implementation, because YCbYCr +// means that two pixels are always encoded together and, while each one +// has its own luminance, they share the chrominance, so a putpixel() is +// not possible, and just hooking into settwopixels() solves all problems. +// +// What doesn't work correctly right now, is setting a single pixel, because +// the cfbimgblit.c code reads two pixels, assumes that it is RGB, changes +// one pixel, and we'll convert it into YCbYCr. This breaks the encoding. +// So we need to implement a 32 bit read from the framebuffer as well and +// return RGB encoded data. +#define CLAMP(x,l,h) ((x > h) ? h : ((x < l) ? l : x)) + +// 16:16 fixed point... hopefully not much accuracy is lost! +#define Ya 16843 // 0.257 +#define Yb 33030 // 0.504 +#define Yc 6423 // 0.098 +#define Yd 1048576 // 16.0 +#define Ye 32768 // 0.5 + +#define Cba -9699 // 0.148 +#define Cbb -19071 // 0.291 +#define Cbc 28770 // 0.439 +#define Cbd 8388608 // 128.0 +#define Cbe 32768 // 0.5 + +#define Cra 28770 // 0.439 +#define Crb -24117 // 0.368 +#define Crc -4653 // 0.071 +#define Crd 8388608 // 128.0 +#define Cre 32768 // 0.5 + +unsigned long GC_Video_RGBToYCbCrFixed (unsigned char r, unsigned char g, unsigned char b) +{ + unsigned long Y, Cb, Cr; + + Y = ((Ya * r) + (Yb * g) + (Yc * b) + Yd + Ye) >> 16; + Cb = ((Cba * r) + (Cbb * g) + (Cbc * b) + Cbd + Cre) >> 16; + Cr = ((Cra * r) + (Crb * g) + (Crc * b) + Crd + Cre) >> 16; + + Y = CLAMP(Y , 16, 235); + Cb = CLAMP(Cb, 16, 240); + Cr = CLAMP(Cr, 16, 240); + + return (unsigned long)(((unsigned char)Y << 24) | ((unsigned char)Cb << 16) | ((unsigned char)Y << 8) | (unsigned char)Cr); +} + +void gamecubefb_writel(unsigned long color, int *address) +{ + unsigned char r, g, b; + unsigned long pa, pb; + + r = ((color >> 27) & 31) << 3; + g = ((color >> 22) & 31) << 3; + b = ((color >> 17) & 31) << 3; + + pa = GC_Video_RGBToYCbCrFixed (r, g, b); + + r = ((color >> 11) & 31) << 3; + g = ((color >> 6) & 31) << 3; + b = ((color >> 1) & 31) << 3; + + pb = GC_Video_RGBToYCbCrFixed (r, g, b); + + fb_writel_real((pa & 0xFF000000) | (pb & 0x0000FF00) | + (((pa & 0x00FF0000) + (pb & 0x00FF0000)) >> 1) | + (((pa & 0x000000FF) + (pb & 0x000000FF)) >> 1), address); +} + /* --------------------------------------------------------------------- */ static int gamecubefb_pan_display(struct fb_var_screeninfo *var, @@ -207,11 +280,11 @@ gamecubefb_defined.hsync_len = (gamecubefb_defined.xres / 8) & 0xf8; if (gamecubefb_defined.bits_per_pixel > 8) { - gamecubefb_defined.red.offset = 0; + gamecubefb_defined.red.offset = 11; gamecubefb_defined.red.length = 5; - gamecubefb_defined.green.offset = 5; + gamecubefb_defined.green.offset = 6; gamecubefb_defined.green.length = 5; - gamecubefb_defined.blue.offset = 10; + gamecubefb_defined.blue.offset = 1; gamecubefb_defined.blue.length = 5; gamecubefb_defined.transp.offset = 15; gamecubefb_defined.transp.length = 1; |