Subject: Re: [E3-hacking][MPlayer-dev-eng] [RFC][PATCH v2] Add support for 12-bit color mode.

From: Janusz Krzysztofik <[email-masked]>
Date: Sat, 3 Apr 2010 16:55:10 +0200

Saturday 03 April 2010 10:54:54 Diego Biurrun wrote:
> On Fri, Mar 19, 2010 at 01:52:42AM +0100, Janusz Krzysztofik wrote:
> > The patch extends mplayer with RGB12 aka RGB444 pixel format handling.
> > It works for me with fbdev and fbdev2, selecting required color
> > conversion filters automatically. It also works with directfb when
> > provided with "-vf format=bgr12" option. I wasn't able to get correct
> > results using sdl, neither with qtopia (incorrect collors) nor fbcon (not
> > working at all) drivers. I haven't tested the x11 output driver
> > modifications.
>
> If you give detailed testing instructions, perhaps somebody else can.

Hi Diego,
First, you need a hardware that supports 12-bit graphics mode, I guess. I'm 
not aware of any such machines/graphics adapters except for Amstrad E3 
(Delta), but I may be wrong.

I use a highly customized, OpenEmbedded genrated system based on Angstrom 
distribution, with no stable configuration ready to provide yet. To prepare 
instructions on how SDL or X could be get working on it, I'd in fact spend my 
time on testing it myself.

E3-hacking guys,
I know they don't like cross-posting on the mplayer-dev-eng, but I'm CCing 
you (should probably do it already before) in hope someone who runs Debian 
with X on his E3 can do some testing, please. For best results, please use 
linux-2.6.34-rcX if you can, or try my 12-bit support fix, already mnetioned 
on the e3-hacking before[1]. Below you can find links to this mplayer patch 
submission message copy[2] and pending discussion[3] (you may have a look at 
date/thread indexes for completness since threads tend to get broken on month 
boundaries). I also resubmit the patch (unchanged) for your convenience.

> > --- trunk.orig/libvo/osd.c	2010-02-26 02:40:23.000000000 +0100
> > +++ trunk/libvo/osd.c	2010-03-19 01:01:29.000000000 +0100
> > @@ -329,6 +329,38 @@ void vo_draw_alpha_init(void){
> >
> > +void vo_draw_alpha_rgb12(int w,int h, unsigned char* src, unsigned char
> > *srca, int srcstride, unsigned char* dstbase,int dststride){
> > +} 
> > +
> >  void vo_draw_alpha_rgb15(int w,int h, unsigned char* src, unsigned char
> > *srca, int srcstride, unsigned char* dstbase,int dststride){
>
> vo_draw_alpha_rgb12() looks very similar to vo_draw_alpha_rgb15() and
> vo_draw_alpha_rgb16().  Ideally this should be refactored in some way.

Sounds like better being addressed by a separate patch. Can I revisit it 
later, when finished with this one?

> > --- trunk.orig/libvo/vo_fbdev.c	2010-03-18 21:43:44.000000000 +0100
> > +++ trunk/libvo/vo_fbdev.c	2010-03-19 01:01:29.000000000 +0100
> > @@ -521,6 +521,13 @@ static void set_bpp(struct fb_var_screen
> >          p->green.offset = 5;
> >          p->blue.length  = 5;
> >          break;
> > +    case 12:
> > +        p->red.offset = 8;
> > +        p->green.length = 4;
> > +        p->red.length = 4;
> > +        p->green.offset = 4;
> > +        p->blue.length = 4;
> > +        break;
>
> Please keep the = vertically aligned like the surrounding code does.

OK.

> > @@ -700,7 +707,7 @@ static int fb_preinit(int reset)
> >
> >      if (vo_dbpp) {
> > -        if (vo_dbpp != 15 && vo_dbpp != 16 && vo_dbpp != 24 && vo_dbpp
> > != 32) { +        if (vo_dbpp != 12 && vo_dbpp != 15 && vo_dbpp != 16 &&
> > vo_dbpp != 24 && vo_dbpp != 32) {
>
> Please break overly long lines.

OK.

Thanks,
Janusz

[1] http://patchwork.kernel.org/patch/72933/
[2] http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2010-March/064116.html
[3] http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2010-April/064198.html

Signed-off-by: Janusz Krzysztofik <[email-masked]>
---
diff -upr trunk.orig/fmt-conversion.c trunk/fmt-conversion.c
--- trunk.orig/fmt-conversion.c	2010-02-26 02:41:08.000000000 +0100
+++ trunk/fmt-conversion.c	2010-03-19 01:01:29.000000000 +0100
@@ -32,6 +32,8 @@ static const struct {
     {IMGFMT_BGR16LE, PIX_FMT_RGB565LE},
     {IMGFMT_BGR15BE, PIX_FMT_RGB555BE},
     {IMGFMT_BGR15LE, PIX_FMT_RGB555LE},
+    {IMGFMT_BGR12BE, PIX_FMT_RGB444BE},
+    {IMGFMT_BGR12LE, PIX_FMT_RGB444LE},
     {IMGFMT_BGR8,  PIX_FMT_RGB8},
     {IMGFMT_BGR4,  PIX_FMT_RGB4},
     {IMGFMT_BGR1,  PIX_FMT_MONOBLACK},
@@ -47,6 +49,8 @@ static const struct {
     {IMGFMT_RGB16LE, PIX_FMT_BGR565LE},
     {IMGFMT_RGB15BE, PIX_FMT_BGR555BE},
     {IMGFMT_RGB15LE, PIX_FMT_BGR555LE},
+    {IMGFMT_RGB12BE, PIX_FMT_BGR444BE},
+    {IMGFMT_RGB12LE, PIX_FMT_BGR444LE},
     {IMGFMT_RGB8,  PIX_FMT_BGR8},
     {IMGFMT_RGB4,  PIX_FMT_BGR4},
     {IMGFMT_BGR8,  PIX_FMT_PAL8},
diff -upr trunk.orig/libmenu/menu.c trunk/libmenu/menu.c
--- trunk.orig/libmenu/menu.c	2010-02-26 02:40:48.000000000 +0100
+++ trunk/libmenu/menu.c	2010-03-19 01:01:29.000000000 +0100
@@ -376,6 +376,9 @@ typedef void (*draw_alpha_f)(int w,int h
 
 inline static draw_alpha_f get_draw_alpha(uint32_t fmt) {
   switch(fmt) {
+  case IMGFMT_BGR12:
+  case IMGFMT_RGB12:
+    return vo_draw_alpha_rgb12;
   case IMGFMT_BGR15:
   case IMGFMT_RGB15:
     return vo_draw_alpha_rgb15;
diff -upr trunk.orig/libmpcodecs/img_format.c trunk/libmpcodecs/img_format.c
--- trunk.orig/libmpcodecs/img_format.c	2010-02-26 02:39:48.000000000 +0100
+++ trunk/libmpcodecs/img_format.c	2010-03-19 01:01:29.000000000 +0100
@@ -29,6 +29,7 @@ const char *vo_format_name(int format)
 	case IMGFMT_RGB4: return "RGB 4-bit";
 	case IMGFMT_RG4B: return "RGB 4-bit per byte";
 	case IMGFMT_RGB8: return "RGB 8-bit";
+	case IMGFMT_RGB12: return "RGB 12-bit";
 	case IMGFMT_RGB15: return "RGB 15-bit";
 	case IMGFMT_RGB16: return "RGB 16-bit";
 	case IMGFMT_RGB24: return "RGB 24-bit";
@@ -39,6 +40,7 @@ const char *vo_format_name(int format)
 	case IMGFMT_BGR4: return "BGR 4-bit";
 	case IMGFMT_BG4B: return "BGR 4-bit per byte";
 	case IMGFMT_BGR8: return "BGR 8-bit";
+	case IMGFMT_BGR12: return "BGR 12-bit";
 	case IMGFMT_BGR15: return "BGR 15-bit";
 	case IMGFMT_BGR16: return "BGR 16-bit";
 	case IMGFMT_BGR24: return "BGR 24-bit";
diff -upr trunk.orig/libmpcodecs/img_format.h trunk/libmpcodecs/img_format.h
--- trunk.orig/libmpcodecs/img_format.h	2010-02-26 02:39:48.000000000 +0100
+++ trunk/libmpcodecs/img_format.h	2010-03-19 01:01:29.000000000 +0100
@@ -29,6 +29,7 @@
 #define IMGFMT_RGB4  (IMGFMT_RGB|4)
 #define IMGFMT_RGB4_CHAR  (IMGFMT_RGB|4|128) // RGB4 with 1 pixel per byte
 #define IMGFMT_RGB8  (IMGFMT_RGB|8)
+#define IMGFMT_RGB12 (IMGFMT_RGB|12)
 #define IMGFMT_RGB15 (IMGFMT_RGB|15)
 #define IMGFMT_RGB16 (IMGFMT_RGB|16)
 #define IMGFMT_RGB24 (IMGFMT_RGB|24)
@@ -42,6 +43,7 @@
 #define IMGFMT_BGR4 (IMGFMT_BGR|4)
 #define IMGFMT_BGR4_CHAR (IMGFMT_BGR|4|128) // BGR4 with 1 pixel per byte
 #define IMGFMT_BGR8 (IMGFMT_BGR|8)
+#define IMGFMT_BGR12 (IMGFMT_BGR|12)
 #define IMGFMT_BGR15 (IMGFMT_BGR|15)
 #define IMGFMT_BGR16 (IMGFMT_BGR|16)
 #define IMGFMT_BGR24 (IMGFMT_BGR|24)
@@ -53,10 +55,14 @@
 #define IMGFMT_ARGB IMGFMT_BGR32
 #define IMGFMT_RGBA (IMGFMT_BGR32|64)
 #define IMGFMT_RGB48NE IMGFMT_RGB48BE
+#define IMGFMT_RGB12BE IMGFMT_RGB12
+#define IMGFMT_RGB12LE (IMGFMT_RGB12|64)
 #define IMGFMT_RGB15BE IMGFMT_RGB15
 #define IMGFMT_RGB15LE (IMGFMT_RGB15|64)
 #define IMGFMT_RGB16BE IMGFMT_RGB16
 #define IMGFMT_RGB16LE (IMGFMT_RGB16|64)
+#define IMGFMT_BGR12BE IMGFMT_BGR12
+#define IMGFMT_BGR12LE (IMGFMT_BGR12|64)
 #define IMGFMT_BGR15BE IMGFMT_BGR15
 #define IMGFMT_BGR15LE (IMGFMT_BGR15|64)
 #define IMGFMT_BGR16BE IMGFMT_BGR16
@@ -67,10 +73,14 @@
 #define IMGFMT_ARGB (IMGFMT_RGB32|64)
 #define IMGFMT_RGBA IMGFMT_RGB32
 #define IMGFMT_RGB48NE IMGFMT_RGB48LE
+#define IMGFMT_RGB12BE (IMGFMT_RGB12|64)
+#define IMGFMT_RGB12LE IMGFMT_RGB12
 #define IMGFMT_RGB15BE (IMGFMT_RGB15|64)
 #define IMGFMT_RGB15LE IMGFMT_RGB15
 #define IMGFMT_RGB16BE (IMGFMT_RGB16|64)
 #define IMGFMT_RGB16LE IMGFMT_RGB16
+#define IMGFMT_BGR12BE (IMGFMT_BGR12|64)
+#define IMGFMT_BGR12LE IMGFMT_BGR12
 #define IMGFMT_BGR15BE (IMGFMT_BGR15|64)
 #define IMGFMT_BGR15LE IMGFMT_BGR15
 #define IMGFMT_BGR16BE (IMGFMT_BGR16|64)
diff -upr trunk.orig/libmpcodecs/vf_1bpp.c trunk/libmpcodecs/vf_1bpp.c
--- trunk.orig/libmpcodecs/vf_1bpp.c	2010-02-26 02:39:43.000000000 +0100
+++ trunk/libmpcodecs/vf_1bpp.c	2010-03-19 01:01:29.000000000 +0100
@@ -45,6 +45,8 @@ static const unsigned int bgr_list[]={
     IMGFMT_444P,
 
     IMGFMT_YUY2,
+    IMGFMT_BGR12,
+    IMGFMT_RGB12,
     IMGFMT_BGR15,
     IMGFMT_RGB15,
     IMGFMT_BGR16,
@@ -150,6 +152,10 @@ static int put_image(struct vf_instance 
     case IMGFMT_YUY2:
 	convert(mpi,dmpi,0x8000,0x80ff,2);
 	break;
+    case IMGFMT_BGR12:
+    case IMGFMT_RGB12:
+	convert(mpi,dmpi,0,0x0fff,2);
+	break;
     case IMGFMT_BGR15:
     case IMGFMT_RGB15:
 	convert(mpi,dmpi,0,0x7fff,2);
diff -upr trunk.orig/libmpcodecs/vf_expand.c trunk/libmpcodecs/vf_expand.c
--- trunk.orig/libmpcodecs/vf_expand.c	2010-02-26 02:39:46.000000000 +0100
+++ trunk/libmpcodecs/vf_expand.c	2010-03-19 01:01:29.000000000 +0100
@@ -146,6 +146,10 @@ static void draw_func(int x0,int y0, int
 			vf->dmpi->stride[0]*y0+
 			(vf->dmpi->bpp>>3)*x0;
     switch(vf->dmpi->imgfmt){
+    case IMGFMT_BGR12:
+    case IMGFMT_RGB12:
+	vo_draw_alpha_rgb12(w,h,src,srca,stride,dst,vf->dmpi->stride[0]);
+	break;
     case IMGFMT_BGR15:
     case IMGFMT_RGB15:
 	vo_draw_alpha_rgb15(w,h,src,srca,stride,dst,vf->dmpi->stride[0]);
diff -upr trunk.orig/libmpcodecs/vf_rgbtest.c trunk/libmpcodecs/vf_rgbtest.c
--- trunk.orig/libmpcodecs/vf_rgbtest.c	2010-02-26 02:39:50.000000000 +0100
+++ trunk/libmpcodecs/vf_rgbtest.c	2010-03-19 01:01:29.000000000 +0100
@@ -37,11 +37,13 @@ struct vf_priv_s {
 
 static unsigned int getfmt(unsigned int outfmt){
     switch(outfmt){
+    case IMGFMT_RGB12:
     case IMGFMT_RGB15:
     case IMGFMT_RGB16:
     case IMGFMT_RGB24:
     case IMGFMT_RGBA:
     case IMGFMT_ARGB:
+    case IMGFMT_BGR12:
     case IMGFMT_BGR15:
     case IMGFMT_BGR16:
     case IMGFMT_BGR24:
@@ -54,6 +56,10 @@ static unsigned int getfmt(unsigned int 
 
 static void put_pixel(uint8_t *buf, int x, int y, int stride, int r, int g, int b, int fmt){
     switch(fmt){
+    case IMGFMT_BGR12: ((uint16_t*)(buf + y*stride))[x]= ((r>>4)<< 8) | ((g>>4)<<4) | (b>>4);
+    break;
+    case IMGFMT_RGB12: ((uint16_t*)(buf + y*stride))[x]= ((b>>4)<< 8) | ((g>>4)<<4) | (r>>4);
+    break;
     case IMGFMT_BGR15: ((uint16_t*)(buf + y*stride))[x]= ((r>>3)<<10) | ((g>>3)<<5) | (b>>3);
     break;
     case IMGFMT_RGB15: ((uint16_t*)(buf + y*stride))[x]= ((b>>3)<<10) | ((g>>3)<<5) | (r>>3);
diff -upr trunk.orig/libmpcodecs/vf_scale.c trunk/libmpcodecs/vf_scale.c
--- trunk.orig/libmpcodecs/vf_scale.c	2010-02-26 02:39:49.000000000 +0100
+++ trunk/libmpcodecs/vf_scale.c	2010-03-19 01:01:29.000000000 +0100
@@ -96,6 +96,8 @@ static const unsigned int outfmt_list[]=
     IMGFMT_RGB16,
     IMGFMT_BGR15,
     IMGFMT_RGB15,
+    IMGFMT_BGR12,
+    IMGFMT_RGB12,
     IMGFMT_Y800,
     IMGFMT_Y8,
     IMGFMT_BGR8,
diff -upr trunk.orig/libmpcodecs/vf_screenshot.c trunk/libmpcodecs/vf_screenshot.c
--- trunk.orig/libmpcodecs/vf_screenshot.c	2010-02-26 02:39:43.000000000 +0100
+++ trunk/libmpcodecs/vf_screenshot.c	2010-03-19 01:01:29.000000000 +0100
@@ -258,6 +258,7 @@ static int query_format(struct vf_instan
     case IMGFMT_BGR24:
     case IMGFMT_BGR16:
     case IMGFMT_BGR15:
+    case IMGFMT_BGR12:
     case IMGFMT_RGB32:
     case IMGFMT_RGB24:
     case IMGFMT_Y800:
diff -upr trunk.orig/libmpcodecs/vf_tile.c trunk/libmpcodecs/vf_tile.c
--- trunk.orig/libmpcodecs/vf_tile.c	2010-02-26 02:39:46.000000000 +0100
+++ trunk/libmpcodecs/vf_tile.c	2010-03-19 01:01:29.000000000 +0100
@@ -202,12 +202,14 @@ static void uninit(struct vf_instance *v
 static int query_format(struct vf_instance *vf, unsigned int fmt)
 {
 	switch (fmt) {
-        /* rgb 15 -> 32 bit */
+        /* rgb 12 -> 32 bit */
+        case IMGFMT_RGB12:
         case IMGFMT_RGB15:
 	case IMGFMT_RGB16:
 	case IMGFMT_RGB24:
         case IMGFMT_RGB32:
-        /* bgr 15 -> 32 bit */
+        /* bgr 12 -> 32 bit */
+	case IMGFMT_BGR12:
 	case IMGFMT_BGR15:
 	case IMGFMT_BGR16:
 	case IMGFMT_BGR24:
diff -upr trunk.orig/libvo/osd.c trunk/libvo/osd.c
--- trunk.orig/libvo/osd.c	2010-02-26 02:40:23.000000000 +0100
+++ trunk/libvo/osd.c	2010-03-19 01:01:29.000000000 +0100
@@ -329,6 +329,38 @@ void vo_draw_alpha_init(void){
 	}
 }
 
+void vo_draw_alpha_rgb12(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+    int y;
+    for(y=0;y<h;y++){
+        register unsigned short *dst = (unsigned short*) dstbase;
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+#ifdef FAST_OSD
+#ifdef FAST_OSD_TABLE
+                dst[x]=fast_osd_12bpp_table[src[x]];
+#else
+		register unsigned int a=src[x]>>4;
+                dst[x]=(a<<8)|(a<<4)|a;
+#endif
+#else
+                unsigned char r=dst[x]&0x0F;
+                unsigned char g=(dst[x]>>4)&0x0F;
+                unsigned char b=(dst[x]>>8)&0x0F;
+                r=(((r*srca[x])>>4)+src[x])>>4;
+                g=(((g*srca[x])>>4)+src[x])>>4;
+                b=(((b*srca[x])>>4)+src[x])>>4;
+                dst[x]=(b<<8)|(g<<4)|r;
+#endif
+            }
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+}
+
 void vo_draw_alpha_rgb15(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
     int y;
     for(y=0;y<h;y++){
diff -upr trunk.orig/libvo/osd.h trunk/libvo/osd.h
--- trunk.orig/libvo/osd.h	2010-02-26 02:40:23.000000000 +0100
+++ trunk/libvo/osd.h	2010-03-19 01:01:29.000000000 +0100
@@ -29,6 +29,7 @@ void vo_draw_alpha_yuy2(int w,  int h, u
 void vo_draw_alpha_uyvy(int w,  int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase, int dststride);
 void vo_draw_alpha_rgb24(int w, int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase, int dststride);
 void vo_draw_alpha_rgb32(int w, int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase, int dststride);
+void vo_draw_alpha_rgb12(int w, int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase, int dststride);
 void vo_draw_alpha_rgb15(int w, int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase, int dststride);
 void vo_draw_alpha_rgb16(int w, int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase, int dststride);
 
diff -upr trunk.orig/libvo/vo_directfb2.c trunk/libvo/vo_directfb2.c
--- trunk.orig/libvo/vo_directfb2.c	2010-02-26 02:40:25.000000000 +0100
+++ trunk/libvo/vo_directfb2.c	2010-03-19 01:01:29.000000000 +0100
@@ -324,9 +324,13 @@ static DFBSurfacePixelFormat convformat(
 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
             case IMGFMT_RGB15: return  DSPF_ARGB1555; break;
             case IMGFMT_BGR15: return  DSPF_ARGB1555; break;
+            case IMGFMT_RGB12: return  DSPF_ARGB4444; break;
+            case IMGFMT_BGR12: return  DSPF_ARGB4444; break;
 #else
             case IMGFMT_RGB15: return  DSPF_RGB15; break;
             case IMGFMT_BGR15: return  DSPF_RGB15; break;
+            case IMGFMT_RGB12: return  DSPF_RGB12; break;
+            case IMGFMT_BGR12: return  DSPF_RGB12; break;
 #endif
             case IMGFMT_YUY2:  return  DSPF_YUY2; break;
             case IMGFMT_UYVY:  return  DSPF_UYVY; break;
@@ -547,6 +551,8 @@ static int config(uint32_t s_width, uint
     		    case IMGFMT_BGR16:
             	    case IMGFMT_RGB15:
 	    	    case IMGFMT_BGR15:
+            	    case IMGFMT_RGB12:
+	    	    case IMGFMT_BGR12:
 					params.bpp=16;
 					break;
 		    default:		params.bpp=0;
@@ -671,8 +677,10 @@ static int config(uint32_t s_width, uint
 	            case DSPF_RGB16: bpp=16;break;
 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
     		    case DSPF_ARGB1555: bpp=15;break;
+    		    case DSPF_ARGB4444: bpp=12;break;
 #else
         	    case DSPF_RGB15: bpp=15;break;
+        	    case DSPF_RGB12: bpp=12;break;
 #endif
 		    case DSPF_RGB332 : bpp=8;break;
 		}
@@ -684,8 +692,10 @@ static int config(uint32_t s_width, uint
 	            case DSPF_RGB16:
 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
     		    case DSPF_ARGB1555:
+    		    case DSPF_ARGB4444:
 #else
         	    case DSPF_RGB15:
+        	    case DSPF_RGB12:
 #endif
 		    case DSPF_RGB332:
 				    mp_msg(MSGT_VO, MSGL_V,"DirectFB: Trying to recover via videomode change (VM).\n");
@@ -1493,6 +1503,13 @@ static void draw_alpha(int x0, int y0, i
 #endif
                         vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch);
                         break;
+#if DIRECTFBVERSION > DFB_VERSION(0,9,15)
+                case DSPF_ARGB4444:
+#else
+                case DSPF_RGB12:
+#endif
+                        vo_draw_alpha_rgb12(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch);
+                        break;
 
 		case DSPF_YUY2:
     			vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 2*x0,pitch);
diff -upr trunk.orig/libvo/vo_fbdev.c trunk/libvo/vo_fbdev.c
--- trunk.orig/libvo/vo_fbdev.c	2010-03-18 21:43:44.000000000 +0100
+++ trunk/libvo/vo_fbdev.c	2010-03-19 01:01:29.000000000 +0100
@@ -521,6 +521,13 @@ static void set_bpp(struct fb_var_screen
         p->green.offset = 5;
         p->blue.length  = 5;
         break;
+    case 12:
+        p->red.offset = 8;
+        p->green.length = 4;
+        p->red.length = 4;
+        p->green.offset = 4;
+        p->blue.length = 4;
+        break;
     }
 }
 
@@ -700,7 +707,7 @@ static int fb_preinit(int reset)
     }
 
     if (vo_dbpp) {
-        if (vo_dbpp != 15 && vo_dbpp != 16 && vo_dbpp != 24 && vo_dbpp != 32) {
+        if (vo_dbpp != 12 && vo_dbpp != 15 && vo_dbpp != 16 && vo_dbpp != 24 && vo_dbpp != 32) {
             mp_msg(MSGT_VO, MSGL_ERR, "can't switch to %d bpp\n", vo_dbpp);
             goto err_out;
         }
@@ -850,6 +857,9 @@ static int config(uint32_t width, uint32
     case 15:
         draw_alpha_p = vo_draw_alpha_rgb15;
         break;
+    case 12:
+        draw_alpha_p = vo_draw_alpha_rgb12;
+        break;
     default:
         return 1;
     }
diff -upr trunk.orig/libvo/vo_fbdev2.c trunk/libvo/vo_fbdev2.c
--- trunk.orig/libvo/vo_fbdev2.c	2010-03-05 16:07:05.000000000 +0100
+++ trunk/libvo/vo_fbdev2.c	2010-03-19 01:01:29.000000000 +0100
@@ -77,6 +77,13 @@ static void set_bpp(struct fb_var_screen
 			p->green.offset = 5;
 			p->blue.length = 5;
 			break;
+		case 12:
+			p->red.offset = 8;
+			p->green.length = 4;
+			p->red.length = 4;
+			p->green.offset = 4;
+			p->blue.length = 4;
+			break;
 	}
 }
 
@@ -247,6 +254,7 @@ static int config(uint32_t width, uint32
 		case 24: draw_alpha_p = vo_draw_alpha_rgb24; break;
 		case 16: draw_alpha_p = vo_draw_alpha_rgb16; break;
 		case 15: draw_alpha_p = vo_draw_alpha_rgb15; break;
+		case 12: draw_alpha_p = vo_draw_alpha_rgb12; break;
 		default: return 1;
 	}
 
diff -upr trunk.orig/libvo/vo_sdl.c trunk/libvo/vo_sdl.c
--- trunk.orig/libvo/vo_sdl.c	2010-02-26 02:40:23.000000000 +0100
+++ trunk/libvo/vo_sdl.c	2010-03-19 01:01:29.000000000 +0100
@@ -299,6 +299,10 @@ static void draw_alpha(int x0,int y0, in
         if(priv->dblit) {
             x0 *= priv->surface->format->BytesPerPixel;
 		switch(priv->format) {
+		case IMGFMT_RGB12:
+		case IMGFMT_BGR12:
+    			vo_draw_alpha_rgb12(w,h,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch);
+		break;
 		case IMGFMT_RGB15:
 		case IMGFMT_BGR15:
     			vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch);
@@ -320,6 +324,10 @@ static void draw_alpha(int x0,int y0, in
 		else {
             x0 *= priv->rgbsurface->format->BytesPerPixel;
 		switch(priv->format) {
+		case IMGFMT_RGB12:
+		case IMGFMT_BGR12:
+    			vo_draw_alpha_rgb12(w,h,src,srca,stride,((uint8_t *) 
priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch);
+		break;
 		case IMGFMT_RGB15:
 		case IMGFMT_BGR15:
     			vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) 
priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch);
@@ -741,12 +749,14 @@ config(uint32_t width, uint32_t height, 
 		case IMGFMT_YVYU:
             priv->mode = YUV;
             break;
+		case IMGFMT_BGR12:	
 		case IMGFMT_BGR15:
 		case IMGFMT_BGR16:
 		case IMGFMT_BGR24:
 		case IMGFMT_BGR32:
 			priv->mode = BGR;
 			break;
+        case IMGFMT_RGB12:	
         case IMGFMT_RGB15:
         case IMGFMT_RGB16:
         case IMGFMT_RGB24:
@@ -909,7 +919,14 @@ static int setup_surfaces(void)
 		// 24 bit: r:ff0000 g:ff00 b:ff
 		// 16 bit: r:1111100000000000b g:0000011111100000b b:0000000000011111b
 		// 15 bit: r:111110000000000b g:000001111100000b b:000000000011111b
+		// 12 bit: r:111100000000b g:000011110000b b:000000001111b
 		// FIXME: colorkey detect based on bpp, FIXME static bpp value, FIXME alpha value correct?
+	    case IMGFMT_RGB12:
+            priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, surfwidth, surfheight, 12, 0x000F, 0x00F0, 0x0F00, 0);
+	    break;	
+	    case IMGFMT_BGR12:
+            priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, surfwidth, surfheight, 12, 0x0F00, 0x00F0, 0x000F, 0);
+	    break;	
 	    case IMGFMT_RGB15:
             priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, surfwidth, surfheight, 15, 31, 992, 31744, 0);
 	    break;
@@ -1002,6 +1019,8 @@ static int draw_frame(uint8_t *src[])
 	    SDL_OVR_UNLOCK
             break;
 
+	case IMGFMT_RGB12:
+	case IMGFMT_BGR12:	
 	case IMGFMT_RGB15:
 	case IMGFMT_BGR15:
 	case IMGFMT_RGB16:
@@ -1334,6 +1353,8 @@ static void erase_rectangle(int x, int y
                 break;
         }
 
+        case IMGFMT_RGB12:
+        case IMGFMT_BGR12:
         case IMGFMT_RGB15:
         case IMGFMT_BGR15:
         case IMGFMT_RGB16:
@@ -1436,6 +1457,8 @@ static void flip_page (void)
 	struct sdl_priv_s *priv = &sdl_priv;
 
 	switch(priv->format) {
+	    case IMGFMT_RGB12:
+	    case IMGFMT_BGR12:	
 	    case IMGFMT_RGB15:
 	    case IMGFMT_BGR15:
 	    case IMGFMT_RGB16:
@@ -1490,6 +1513,8 @@ query_format(uint32_t format)
     case IMGFMT_YVYU:
         return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD |
             VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
+    case IMGFMT_RGB12:
+    case IMGFMT_BGR12:
     case IMGFMT_RGB15:
     case IMGFMT_BGR15:
     case IMGFMT_RGB16:
diff -upr trunk.orig/libvo/vo_x11.c trunk/libvo/vo_x11.c
--- trunk.orig/libvo/vo_x11.c	2010-02-26 02:40:25.000000000 +0100
+++ trunk/libvo/vo_x11.c	2010-03-19 01:01:29.000000000 +0100
@@ -146,6 +146,14 @@ static void draw_alpha_15(int x0, int y0
                         2 * image_width);
 }
 
+static void draw_alpha_12(int x0, int y0, int w, int h, unsigned char *src,
+                          unsigned char *srca, int stride)
+{
+    vo_draw_alpha_rgb12(w, h, src, srca, stride,
+                        ImageData + 2 * (y0 * image_width + x0),
+                        2 * image_width);
+}
+
 static void draw_alpha_null(int x0, int y0, int w, int h,
                             unsigned char *src, unsigned char *srca,
                             int stride)
@@ -285,6 +293,8 @@ const struct fmt2Xfmtentry_s {
   {IMGFMT_RGB8,  BO_NONNATIVE, 0x00000007, 0x00000038, 0x000000C0},
   {IMGFMT_BGR8,  BO_NATIVE,    0x000000E0, 0x0000001C, 0x00000003},
   {IMGFMT_BGR8,  BO_NONNATIVE, 0x000000E0, 0x0000001C, 0x00000003},
+  {IMGFMT_RGB12, BO_NATIVE,    0x0000000F, 0x000000F0, 0x00000F00},
+  {IMGFMT_BGR12, BO_NATIVE,    0x00000F00, 0x000000F0, 0x0000000F},
   {IMGFMT_RGB15, BO_NATIVE,    0x0000001F, 0x000003E0, 0x00007C00},
   {IMGFMT_BGR15, BO_NATIVE,    0x00007C00, 0x000003E0, 0x0000001F},
   {IMGFMT_RGB16, BO_NATIVE,    0x0000001F, 0x000007E0, 0x0000F800},
@@ -620,6 +630,7 @@ static int query_format(uint32_t format)
     switch (format)
     {
 //   case IMGFMT_BGR8:
+//   case IMGFMT_BGR12:
 //   case IMGFMT_BGR15:
 //   case IMGFMT_BGR16:
 //   case IMGFMT_BGR24:
diff -upr trunk.orig/m_option.c trunk/m_option.c
--- trunk.orig/m_option.c	2010-03-05 16:07:13.000000000 +0100
+++ trunk/m_option.c	2010-03-19 01:01:29.000000000 +0100
@@ -1080,6 +1080,7 @@ static struct {
   {"bgr32", IMGFMT_BGR32},
   {"bgr16", IMGFMT_BGR16},
   {"bgr15", IMGFMT_BGR15},
+  {"bgr12", IMGFMT_BGR12},
   {"bgr8", IMGFMT_BGR8},
   {"bgr4", IMGFMT_BGR4},
   {"bg4b", IMGFMT_BG4B},
@@ -1091,6 +1092,7 @@ static struct {
   {"rgb32", IMGFMT_RGB32},
   {"rgb16", IMGFMT_RGB16},
   {"rgb15", IMGFMT_RGB15},
+  {"rgb12", IMGFMT_RGB12},
   {"rgb8", IMGFMT_RGB8},
   {"rgb4", IMGFMT_RGB4},
   {"rg4b", IMGFMT_RG4B},

---

From: Peter Korsgaard <[email-masked]>
Date: Sat, 03 Apr 2010 18:10:51 +0200

>>>>> "Janusz" == Janusz Krzysztofik <[email-masked]> writes:

Hi,

 Janusz> First, you need a hardware that supports 12-bit graphics mode,
 Janusz> I guess. I'm not aware of any such machines/graphics adapters
 Janusz> except for Amstrad E3 (Delta), but I may be wrong.

The old Compaq Ipaqs also had 12bit LCDs - I have one in a drawer
somewhere.

http://h18000.www1.hp.com/products/quickspecs/10632_na/10632_na.HTML

-- 
Bye, Peter Korsgaard

---

From: Janusz Krzysztofik <[email-masked]>
Date: Sun, 4 Apr 2010 00:49:31 +0200

> http://h18000.www1.hp.com/products/quickspecs/10632_na/10632_na.HTML

Peter,

It looks promissing. Is your unit already running Linux? If yes, would you be 
able to compile and install software on it, ie. recent svn revision of 
mplayer?

Thanks,
Janusz

---

From: Peter Korsgaard <[email-masked]>
Date: Thu, 08 Apr 2010 22:31:47 +0200

>>>>> "Janusz" == Janusz Krzysztofik <[email-masked]> writes:

 Janusz> Peter,

 Janusz> It looks promissing. Is your unit already running Linux? If
 Janusz> yes, would you be able to compile and install software on it,
 Janusz> ie. recent svn revision of mplayer?

Sorry, I would have to dig it out of the closet and revive it. Back in
the day it ran familar (http://familiar.handhelds.org) on a 2.4
kernel. I'm leaving for holidays tomorrow, so I cannot promise anything
in the near future.

-- 
Bye, Peter Korsgaard