Hello all,

I don't have any RGB overlay, and YUV2 orvelays seem broken, so I set out
to improve YV12 support for xmame.

The patch in this mail does three things:

* It adds a -yv12 switch to force yv12 overlays.
* It **hugely** improves the aspect of yv12 rendering, and, for 16bits
  games, the speed of yv12 rendering.
* it adds support for -scale 2 in yv12 rendering (only -scale 2. It has
  the effect of rendering perfect colors. Other values of -scale are
  useless and unsupported.)


Note however that yv12 functions are still only in x11_window.c. Hacking 
blit.h is way too complicated for me, I won't touch that thing.

The patch is against pre8, but as x11_window.c was not modified by pre9,
it should work as well in the latest version.

Regards,

        �ric Brunet
diff -ru xmame-0.61.1-pr8-vanilla/src/unix/video-drivers/x11_window.c 
xmame-0.61.1-pr8/src/unix/video-drivers/x11_window.c
--- xmame-0.61.1-pr8-vanilla/src/unix/video-drivers/x11_window.c        Thu Oct 17 
16:56:55 2002
+++ xmame-0.61.1-pr8/src/unix/video-drivers/x11_window.c        Thu Oct 31 10:33:48 
+2002
@@ -32,8 +32,10 @@
 #ifdef USE_XV
 static void x11_window_update_16_to_YUY2 (struct mame_bitmap *bitmap);
 static void x11_window_update_16_to_YV12 (struct mame_bitmap *bitmap);
+static void x11_window_update_16_to_YV12_perfect (struct mame_bitmap *bitmap);
 static void x11_window_update_32_to_YUY2_direct (struct mame_bitmap *bitmap);
 static void x11_window_update_32_to_YV12_direct (struct mame_bitmap *bitmap);
+static void x11_window_update_32_to_YV12_direct_perfect (struct mame_bitmap *bitmap);
 static void x11_window_make_yuv_lookup();
 #endif
 static void x11_window_update_8_to_8bpp (struct mame_bitmap *bitmap);
@@ -62,6 +64,7 @@
 static int xv_bpp=0;
 static long xv_format=0;
 static long xv_yuv=0;
+static long xv_yv12=0;
 static int *xv_yuvlookup=NULL;
 #define XV_YUY2 0x32595559
 #define XV_YV12 0x32315659
@@ -122,6 +125,9 @@
    { "yuv",            NULL,                   rc_bool,        &xv_yuv,
      "0",              0,                      0,              NULL,
      "Force YUV mode (for video cards with broken RGB overlays)" },
+   { "yv12",           NULL,                   rc_bool,        &xv_yv12,
+     "0",              0,                      0,              NULL,
+     "Force YV12 mode (for video cards with broken RGB overlays)" },
 #endif
         { "xsync",             "xs",                   rc_bool,        &use_xsync,
      "1",              0,                      0,              NULL,
@@ -773,6 +779,7 @@
          /* Create an XV MITSHM image. */
          {
             fprintf (stderr_file, "MIT-SHM & XV Extensions Available. trying to 
use... ");
+           if (xv_yv12) xv_yuv=1;
             XSetErrorHandler (test_mit_shm);
             if(xv_yuv==0)
             {
@@ -789,9 +796,9 @@
                xv_bluemask=0xff;
                xv_bpp=32;
                xv_format=XV_YUY2;
-               if(!(FindXvPort(display, xv_format, &xv_port)))
+               if(xv_yv12 || !(FindXvPort(display, xv_format, &xv_port)))
                {
-                  fprintf(stderr,"\nYUY2 not available - trying YV12... ");
+                  if (!xv_yv12) fprintf(stderr,"\nYUY2 not available - trying YV12... 
+");
                   xv_format=XV_YV12;
                   if(!(FindXvPort(display, xv_format, &xv_port)))
                   {
@@ -932,7 +939,19 @@
                break;
             case XV_YV12:
                ClearYV12(xvimage);
-               x11_window_update_display_func = x11_window_update_32_to_YV12_direct;
+              if (widthscale == 1 && heightscale == 1)
+                      x11_window_update_display_func
+                              = x11_window_update_32_to_YV12_direct;
+              else if (widthscale ==2 && heightscale == 2)
+                      x11_window_update_display_func
+                              = x11_window_update_32_to_YV12_direct_perfect;
+              else {
+                      fprintf(stderr_file, "\nScaling different from 1 or 2"
+                                      " is useless and unsupported\n");
+                      return OSD_NOT_OK;
+              }
+
+
                break;
          }
       }
@@ -954,7 +973,17 @@
                break;
             case XV_YV12:
                ClearYV12(xvimage);
-               x11_window_update_display_func = x11_window_update_16_to_YV12;
+                      if (widthscale == 1 && heightscale == 1)
+                      x11_window_update_display_func
+                              = x11_window_update_16_to_YV12;
+              else if (widthscale ==2 && heightscale == 2)
+                      x11_window_update_display_func
+                              = x11_window_update_16_to_YV12_perfect;
+              else {
+                      fprintf(stderr_file, "\nScaling different from 1 or 2"
+                                      " is useless and unsupported\n");
+                      return OSD_NOT_OK;
+              }
                break;
          }
       }
@@ -1393,6 +1422,15 @@
 #define RMASK 0xff0000
 #define GMASK 0x00ff00
 #define BMASK 0x0000ff
+
+#define RGB2YUV(r,g,b,y,u,v) \
+                (y) =  ( 9797*(r) + 19237*(g) +  3734*(b) ) >> 15;\
+                (u) =  (18492*((b)-(y)) >> 15) + 128;\
+                (v) =  (23372*((r)-(y)) >> 15) + 128;
+       /* (v) =        (( 16385*(r) - 13721*(g) -  2664*(b) ) >> 15) + 128
+          (u) =        (( -5528*(r) - 10856*(g) + 16385*(b) ) >> 15) + 128;\
+        */
+       
 static void x11_window_make_yuv_lookup()
 {
    int i,r,g,b,y,u,v,n;
@@ -1413,9 +1451,7 @@
         g=(g&GMASK)>>8;
         b=(b&BMASK);
 
-        y = (( 9897*r + 19235*g + 3736*b ) >> 15) & 255;
-        u = ((( -5537*r - 10878*g + 16384*b ) >> 15) + 128) & 255;
-        v = ((( 16384*r - 13730*g -2664*b ) >> 15 ) + 128) & 255;
+       RGB2YUV(r,g,b,y,u,v);
 
         /* Storing this data in YUYV order simplifies using the data for
            YUY2, both with and without smoothing... */
@@ -1427,36 +1463,140 @@
 /* Hacked into place, until I integrate YV12 support into the blit core... */
 static void x11_window_update_16_to_YV12(struct mame_bitmap *bitmap)
 {
-   int _x,_y,r,g,b;
+   int _x,_y;
    unsigned char *dest_y;
    unsigned char *dest_u;
    unsigned char *dest_v;
    unsigned short *src;
-   int *indirect=current_palette->lookup;
+   unsigned short *src2;
+   int u,v,y,u2,v2,y2,u3,v3,y3,u4,v4,y4;     /* 12 */
+   int *indirect=current_palette->lookup;    /* 34 */
+
+   for(_y=visual.min_y;_y<=visual.max_y;_y+=2)
+   {
+      src=bitmap->line[_y] ;
+      src+= visual.min_x;
+      src2=bitmap->line[_y+1];
+      src2+= visual.min_x;
 
-   for(_y=visual.min_y;_y<=visual.max_y;++_y)
-   {
-      src=bitmap->line[_y];
-      src+=visual.min_x;
       dest_y=xvimage->data+xvimage->offsets[0]+(xvimage->width*(_y-visual.min_y));
       
dest_v=xvimage->data+xvimage->offsets[1]+((xvimage->width/2)*((_y-visual.min_y)/2));
       
dest_u=xvimage->data+xvimage->offsets[2]+((xvimage->width/2)*((_y-visual.min_y)/2));
-      for(_x=visual.min_x;_x<=visual.max_x;++_x)
+      for(_x=visual.min_x;_x<=visual.max_x;_x+=2)
       {
-         r=g=b=*src++;
-         if(indirect)
-           r=g=b=indirect[r];
-
-         r&=RMASK;  r>>=16; /*   red is << 8 */
-         g&=GMASK;  g>>=8; /* green is << 3 */
-         b&=BMASK;  b>>=0; /*  blue is >> 3 */
+       if (indirect) {
+                v = xv_yuvlookup[*src++];
+                y = (v>>8)  & 0xff;
+                u = (v>>16) & 0xff;
+                v = (v)     & 0xff;
+
+                v2 = xv_yuvlookup[*src++];
+                y2 = (v2>>8)  & 0xff;
+                u2 = (v2>>16) & 0xff;
+                v2 = (v2)     & 0xff;
+
+                v3 = xv_yuvlookup[*src2++];
+                y3 = (v3>>8)  & 0xff;
+                u3 = (v3>>16) & 0xff;
+                v3 = (v3)     & 0xff;
+
+                v4 = xv_yuvlookup[*src2++];
+                y4 = (v4>>8)  & 0xff;
+                u4 = (v4>>16) & 0xff;
+                v4 = (v4)     & 0xff;
+        } else { /* Can this really happen ? */
+                int r,g,b;
+                b = *src++;
+                r = (b>>16) & 0xFF;
+                g = (b>>8)  & 0xFF;
+                b = (b)     & 0xFF;
+                RGB2YUV(r,g,b,y,u,v);
+
+                b = *src++;
+                r = (b>>16) & 0xFF;
+                g = (b>>8)  & 0xFF;
+                b = (b)     & 0xFF;
+                RGB2YUV(r,g,b,y2,u2,v2);
+
+                b = *src2++;
+                r = (b>>16) & 0xFF;
+                g = (b>>8)  & 0xFF;
+                b = (b)     & 0xFF;
+                RGB2YUV(r,g,b,y3,u3,v3);
+
+                b = *src2++;
+                r = (b>>16) & 0xFF;
+                g = (b>>8)  & 0xFF;
+                b = (b)     & 0xFF;
+                RGB2YUV(r,g,b,y4,u4,v4);
+        }
+        
+         *dest_y = y;
+        *(dest_y++ + xvimage->width) = y3;
+         *dest_y = y2;
+        *(dest_y++ + xvimage->width) = y4;
+
+        *dest_u++ = (u+u2+u3+u4)/4;
+        *dest_v++ = (v+v2+v3+v4)/4;
+
+        /* I thought that the following would be better, but it is not
+         * the case. The color gets blurred 
+        if (y || y2 || y3 || y4) {
+                *dest_u++ = (u*y+u2*y2+u3*y3+u4*y4)/(y+y2+y3+y4);
+                *dest_v++ = (v*y+v2*y2+v3*y3+v4*y4)/(y+y2+y3+y4);
+        } else {
+                *dest_u++ =128;
+                *dest_v++ =128;
+        }
+        */
+      }
+   }
+}
 
-         *dest_y++ = (( 9897*r + 19235*g + 3736*b ) >> 15);
-         if(((_x&1)==1) && ((_y&1)==1))
-         {
-            *dest_u++ = (( -5537*r - 10878*g + 16384*b ) >> 15) + 128;
-            *dest_v++ = (( 16384*r - 13730*g -2664*b ) >> 15 ) + 128;
-         }
+static void x11_window_update_16_to_YV12_perfect(struct mame_bitmap *bitmap)
+{      /* this one is used when scale==2 */
+   unsigned int _x,_y,r;
+   unsigned char *dest_y;
+   unsigned char *dest_u;
+   unsigned char *dest_v;
+   unsigned short *src;
+   unsigned short *src2;
+   int u,v,y;
+   int *indirect=current_palette->lookup;
+
+   for(_y=visual.min_y;_y<=visual.max_y;_y++)
+   {
+      src=bitmap->line[_y];
+      src += visual.min_x;
+      src2=bitmap->line[_y+1];
+      src2 += visual.min_x;
+
+      dest_y=xvimage->data+xvimage->offsets[0]+2*(xvimage->width*(_y-visual.min_y));
+      dest_v=xvimage->data+xvimage->offsets[1]+((xvimage->width/2)*(_y-visual.min_y));
+      dest_u=xvimage->data+xvimage->offsets[2]+((xvimage->width/2)*(_y-visual.min_y));
+      for(_x=visual.min_x;_x<=visual.max_x;_x++)
+      {
+        if (indirect) {
+               v= xv_yuvlookup[*src++];
+               y = (v>>8)  & 0xff;
+               u = (v>>16) & 0xff;
+               v = (v)     & 0xff;
+        } else { /* Can this really happen ? */
+                int r,g,b;
+                b = *src++;
+                r = (b>>16) & 0xFF;
+                g = (b>>8)  & 0xFF;
+                b = (b)     & 0xFF;
+                RGB2YUV(r,g,b,y,u,v);
+        }
+                
+
+        *(dest_y+xvimage->width)=y;
+        *dest_y++=y;
+        *(dest_y+xvimage->width)=y;
+        *dest_y++=y;
+        *dest_u++ = u;
+        *dest_v++ = v;
       }
    }
 }
@@ -1468,28 +1608,91 @@
    unsigned char *dest_u;
    unsigned char *dest_v;
    unsigned int *src;
+   unsigned int *src2;
+   int u,v,y,u2,v2,y2,u3,v3,y3,u4,v4,y4;     /* 12 */
+                                             /* 34 */
 
-   for(_y=visual.min_y;_y<=visual.max_y;++_y)
+   for(_y=visual.min_y;_y<=visual.max_y;_y+=2)
    {
       src=bitmap->line[_y];
       src+=visual.min_x;
+      src2=bitmap->line[_y+1];
+      src2 += visual.min_x;
+
       dest_y=xvimage->data+xvimage->offsets[0]+(xvimage->width*(_y-visual.min_y));
       
dest_v=xvimage->data+xvimage->offsets[1]+((xvimage->width/2)*((_y-visual.min_y)/2));
       
dest_u=xvimage->data+xvimage->offsets[2]+((xvimage->width/2)*((_y-visual.min_y)/2));
-      for(_x=visual.min_x;_x<=visual.max_x;++_x)
+      for(_x=visual.min_x;_x<=visual.max_x;_x+=2)
       {
-         r=g=b=*src++;
+        b = *src++;
+        r = (b>>16) & 0xFF;
+        g = (b>>8)  & 0xFF;
+        b = (b)     & 0xFF;
+        RGB2YUV(r,g,b,y,u,v);
+
+        b = *src++;
+        r = (b>>16) & 0xFF;
+        g = (b>>8)  & 0xFF;
+        b = (b)     & 0xFF;
+        RGB2YUV(r,g,b,y2,u2,v2);
+
+        b = *src2++;
+        r = (b>>16) & 0xFF;
+        g = (b>>8)  & 0xFF;
+        b = (b)     & 0xFF;
+        RGB2YUV(r,g,b,y3,u3,v3);
+
+        b = *src2++;
+        r = (b>>16) & 0xFF;
+        g = (b>>8)  & 0xFF;
+        b = (b)     & 0xFF;
+        RGB2YUV(r,g,b,y4,u4,v4);
+        
+         *dest_y = y;
+        *(dest_y++ + xvimage->width) = y3;
+         *dest_y = y2;
+        *(dest_y++ + xvimage->width) = y4;
 
-         r&=RMASK;  r>>=16;
-         g&=GMASK;  g>>=8;
-         b&=BMASK;  b>>=0;
+        *dest_u++ = (u+u2+u3+u4)/4;
+        *dest_v++ = (v+v2+v3+v4)/4;
+      }
+   }
+}
 
-         *dest_y++ = (( 9897*r + 19235*g + 3736*b ) >> 15);
-         if(((_x&1)==1) && ((_y&1)==1))
-         {
-            *dest_u++ = (( -5537*r - 10878*g + 16384*b ) >> 15) + 128;
-            *dest_v++ = (( 16384*r - 13730*g -2664*b ) >> 15 ) + 128;
-         }
+static void x11_window_update_32_to_YV12_direct_perfect(struct mame_bitmap *bitmap)
+{ /* This one is used when scale == 2 */
+   int _x,_y,r,g,b;
+   unsigned char *dest_y;
+   unsigned char *dest_u;
+   unsigned char *dest_v;
+   unsigned int *src;
+   unsigned int *src2;
+   int u,v,y;
+
+   for(_y=visual.min_y;_y<=visual.max_y;_y++)
+   {
+      src  =  bitmap->line[_y];
+      src  += visual.min_x;
+      src2 =  bitmap->line[_y+1];
+      src2 += visual.min_x;
+
+      dest_y=xvimage->data+xvimage->offsets[0]+2*(xvimage->width*(_y-visual.min_y));
+      dest_v=xvimage->data+xvimage->offsets[1]+((xvimage->width/2)*(_y-visual.min_y));
+      dest_u=xvimage->data+xvimage->offsets[2]+((xvimage->width/2)*(_y-visual.min_y));
+      for(_x=visual.min_x;_x<=visual.max_x;_x++)
+      {
+        b = *src++;
+        r = (b>>16) & 0xFF;
+        g = (b>>8)  & 0xFF;
+        b = (b)     & 0xFF;
+        RGB2YUV(r,g,b,y,u,v);
+
+        *(dest_y+xvimage->width) = y;
+        *dest_y++ = y;
+        *(dest_y+xvimage->width) = y;
+        *dest_y++ = y;
+        *dest_u++ = u;
+        *dest_v++ = v;
       }
    }
 }

Reply via email to