This patch adds YUV support to gFillRectangle(). Both packed and planar
formats are supported. The specified RGB color is converted to YCbCr so
it doesn't need any API changes. The color conversion formula was taken
from the v4l2 site. I didn't check the math myself since it seems to work.
I just needed this to make Clear() work for the CRTC2 layer when in YUV
mode. Any corrections or other comments?

-- 
Ville Syrj�l�
[EMAIL PROTECTED]
http://www.sci.fi/~syrjala/
diff -urN /home/villes/cvs/directfb/DirectFB/src/gfx/convert.h 
/media/0/writable/src/DirectFB/src/gfx/convert.h
--- /home/villes/cvs/directfb/DirectFB/src/gfx/convert.h        Thu Aug  8 02:31:10 
2002
+++ /media/0/writable/src/DirectFB/src/gfx/convert.h    Tue Aug 13 03:32:44 2002
@@ -33,6 +33,28 @@
 
 #include "misc/memcpy.h"
 
+#define Y_FROM_RGB(r,g,b)  (( 0.2290 * r +  \
+                              0.5670 * g +  \
+                              0.1440 * b) * \
+                            219 / 255 + 16)
+#define CB_FROM_RGB(r,g,b) ((-0.1687 * r -  \
+                              0.3313 * g +  \
+                              0.5000 * b) * \
+                            112 / 127 + 128)
+#define CR_FROM_RGB(r,g,b) (( 0.5000 * r -  \
+                              0.4187 * g -  \
+                              0.0813 * b) * \
+                            112 / 127 + 128)
+
+#define PIXEL_YUY2(y,u,v) ( ((y) << 24) | \
+                            ((u) << 16) | \
+                            ((y) << 8)  | \
+                             (v) )
+
+#define PIXEL_UYVY(y,u,v) ( ((u) << 24) | \
+                            ((y) << 16) | \
+                            ((v) << 8)  | \
+                             (y) )
 
 #define PIXEL_RGB332(r,g,b)    ( (((r)&0xE0)     ) | \
                                  (((g)&0xE0) >> 3) | \
diff -urN /home/villes/cvs/directfb/DirectFB/src/gfx/generic/generic.c 
/media/0/writable/src/DirectFB/src/gfx/generic/generic.c
--- /home/villes/cvs/directfb/DirectFB/src/gfx/generic/generic.c        Fri Aug  2 
22:01:51 2002
+++ /media/0/writable/src/DirectFB/src/gfx/generic/generic.c    Tue Aug 13 03:35:16 
+2002
@@ -89,6 +89,10 @@
 static void *Bop = NULL;
 static __u32 Cop = 0;
 
+static __u8 YCop  = 0;
+static __u8 CbCop = 0;
+static __u8 CrCop = 0;
+
 /*
  * color keys
  */
@@ -201,15 +205,15 @@
      Cop_to_Aop_32,
      Cop_to_Aop_32,
      Cop_to_Aop_8,
-     NULL,
+     Cop_to_Aop_32,
 #ifdef SUPPORT_RGB332
      Cop_to_Aop_8,
 #else     
      NULL,
 #endif
-     NULL,
-     NULL,
-     NULL,
+     Cop_to_Aop_32,
+     Cop_to_Aop_8,
+     Cop_to_Aop_8,
      Cop_to_Aop_8
 };
 
@@ -2515,10 +2519,62 @@
                Cop = PIXEL_RGB332( color.r, color.g, color.b );
                break;
 #endif
-          case DSPF_YUY2:
-          case DSPF_UYVY:
           case DSPF_I420:
+               if (accel == DFXL_FILLRECTANGLE) {
+                    YCop  = Y_FROM_RGB( color.r, color.g, color.b );
+                    CbCop = CB_FROM_RGB( color.r, color.g, color.b );
+                    CrCop = CR_FROM_RGB( color.r, color.g, color.b );
+                    break;
+               }
+               if (accel != DFXL_BLIT || src_format != dst_format ||
+                   state->blittingflags != DSBLIT_NOFX)
+               {
+                    ONCE("only copying blits supported for YUV in software");
+                    pthread_mutex_unlock( &generic_lock );
+                    return 0;
+               }
+               break;
           case DSPF_YV12:
+               if (accel == DFXL_FILLRECTANGLE) {
+                    YCop  = Y_FROM_RGB( color.r, color.g, color.b );
+                    CbCop = CR_FROM_RGB( color.r, color.g, color.b );
+                    CrCop = CB_FROM_RGB( color.r, color.g, color.b );
+                    break;
+               }
+               if (accel != DFXL_BLIT || src_format != dst_format ||
+                   state->blittingflags != DSBLIT_NOFX)
+               {
+                    ONCE("only copying blits supported for YUV in software");
+                    pthread_mutex_unlock( &generic_lock );
+                    return 0;
+               }
+               break;
+          case DSPF_YUY2:
+               if (accel == DFXL_FILLRECTANGLE) {
+                    __u8 y, cb, cr;
+                    y  = Y_FROM_RGB( color.r, color.g, color.b );
+                    cb = CB_FROM_RGB( color.r, color.g, color.b );
+                    cr = CR_FROM_RGB( color.r, color.g, color.b );
+                    Cop = PIXEL_YUY2( y, cb, cr );
+                    break;
+               }
+               if (accel != DFXL_BLIT || src_format != dst_format ||
+                   state->blittingflags != DSBLIT_NOFX)
+               {
+                    ONCE("only copying blits supported for YUV in software");
+                    pthread_mutex_unlock( &generic_lock );
+                    return 0;
+               }
+               break;
+          case DSPF_UYVY:
+               if (accel == DFXL_FILLRECTANGLE) {
+                    __u8 y, cb, cr;
+                    y  = Y_FROM_RGB( color.r, color.g, color.b );
+                    cb = CB_FROM_RGB( color.r, color.g, color.b );
+                    cr = CR_FROM_RGB( color.r, color.g, color.b );
+                    Cop = PIXEL_UYVY( y, cb, cr );
+                    break;
+               }
                if (accel != DFXL_BLIT || src_format != dst_format ||
                    state->blittingflags != DSBLIT_NOFX)
                {
@@ -3063,16 +3119,49 @@
 
 void gFillRectangle( DFBRectangle *rect )
 {
+     int height;
+
      CHECK_PIPELINE();
 
+     if (dst_format == DSPF_I420 || dst_format == DSPF_YV12)
+          Cop = YCop;
+
      Dlength = rect->w;
 
+     if (dst_format == DSPF_YUY2 || dst_format == DSPF_UYVY)
+          Dlength /= 2;
+
      Aop_xy( dst_org, rect->x, rect->y, dst_pitch );
-     
-     while (rect->h--) {
+
+     height = rect->h;
+     while (height--) {
           RUN_PIPELINE();
 
           Aop_next( dst_pitch );
+     }
+
+     if (dst_format == DSPF_I420 || dst_format == DSPF_YV12) {
+          Dlength = rect->w / 2;
+
+          Cop = CbCop;
+          Aop_xy( dst_org + dst_height * dst_pitch,
+                  rect->x/2, rect->y/2, dst_pitch/2 );
+          height = rect->h / 2;
+          while(height--) {
+               RUN_PIPELINE();
+
+               Aop_next( dst_pitch / 2);
+          }
+
+          Cop = CrCop;
+          Aop_xy( dst_org + dst_height * dst_pitch + dst_height * dst_pitch / 4,
+                  rect->x/2, rect->y/2, dst_pitch/2 );
+          height = rect->h / 2;
+          while(height--) {
+               RUN_PIPELINE();
+
+               Aop_next( dst_pitch / 2);
+          }
      }
 }
 

Reply via email to