Attached are some patches that improve field parity and triple buffering 
in the matrox driver.

I've moved the buffer flipping completely to the kernel which should make 
it less probable that the hardware flips the buffers when we're not 
looking. The other major benefit is that field parity no longer causes the 
Flip() call to block. The application will continue without further 
delays. This is especially nice with mplayer since it's single threaded.

The field parity part is obviously for CRTC2 but the patch makes triple 
buffering more robust on BES too.

One patch is for matroxfb obviously and one for DirectFB.

The third patch is for mplayer and it makes dfbmga use the field parity 
information from the codec. That should make it possible to watch 
soft-telecined stuff on the TV with near perfect field order.

Oh and if you try this use CVS DirectFB since there was a problem with 
dynamic field parity changes. I fixed it yeasterday (or was it the day 
before that). Anyways everyone who likes this field parity stuff should 
definately try these patches ;)

-- 
Ville Syrjälä
[EMAIL PROTECTED]
http://www.sci.fi/~syrjala/
diff -urN matrox.6/matroxfb_base.c matrox/matroxfb_base.c
--- matrox.6/matroxfb_base.c    2005-10-26 00:29:13.000000000 +0300
+++ matrox/matroxfb_base.c      2005-10-26 00:52:39.000000000 +0300
@@ -122,6 +122,7 @@
 #endif
 
 static void matroxfb_unregister_device(struct matrox_fb_info* minfo);
+static void matroxfb_set_address(WPMINFO struct matrox_address *address);
 
 /* --------------------------------------------------------------------- */
 
@@ -218,6 +219,12 @@
        if (status & 0x200) {
                mga_outl(M_ICLEAR, 0x200);
                ACCESS_FBINFO(crtc2.vsync.cnt)++;
+               ACCESS_FBINFO(crtc2.vsync.field) = (mga_inl(0x3C48) >> 24) & 1;
+               if (ACCESS_FBINFO(crtc2.pan) &&
+                   ACCESS_FBINFO(crtc2.address.field) != 
ACCESS_FBINFO(crtc2.vsync.field)) {
+                       ACCESS_FBINFO(crtc2.pan) = 0;
+                       matroxfb_set_address(PMINFO 
&ACCESS_FBINFO(crtc2.address));
+               }
                wake_up_interruptible(&ACCESS_FBINFO(crtc2.vsync.wait));
                handled = 1;
        }
@@ -300,6 +307,71 @@
        return 0;
 }
 
+static void matroxfb_set_address(WPMINFO struct matrox_address *address)
+{
+       switch (address->device) {
+       case MATROX_ADDRESS_DEVICE_BES:
+               mga_outl(0x3D00, address->offset[0]);
+               mga_outl(0x3D04, address->offset[1]);
+               mga_outl(0x3D10, address->offset[2]);
+               mga_outl(0x3D14, address->offset[3]);
+               if (ACCESS_FBINFO(devflags.accelerator) == 
FB_ACCEL_MATROX_MGAG400) {
+                       mga_outl(0x3D60, address->offset[4]);
+                       mga_outl(0x3D64, address->offset[5]);
+               }
+               mga_inl(0x3D00);
+               break;
+       case MATROX_ADDRESS_DEVICE_CRTC2:
+               mga_outl(0x3C28, address->offset[0]);
+               mga_outl(0x3C2C, address->offset[1]);
+               mga_outl(0x3C30, address->offset[2]);
+               mga_outl(0x3C34, address->offset[3]);
+               mga_outl(0x3C38, address->offset[4]);
+               mga_outl(0x3C3C, address->offset[5]);
+               mga_inl(0x3C28);
+               break;
+       }
+}
+
+int matroxfb_address(WPMINFO struct matrox_address *address) 
+{
+       if (address->device == MATROX_ADDRESS_DEVICE_CRTC2 &&
+           ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) {
+               int vbl;
+
+               /* Interrupts are always needed to update vsync.cnt. */
+               vbl = !matroxfb_enable_irq(PMINFO 0) && address->field == 
ACCESS_FBINFO(crtc2.vsync.field);
+
+               if (vbl) {
+                       ACCESS_FBINFO(crtc2.address) = *address;
+                       ACCESS_FBINFO(crtc2.pan) = 1;
+               } else {
+                       ACCESS_FBINFO(crtc2.pan) = 0;
+                       matroxfb_set_address(PMINFO address);
+               }
+
+               address->field = ACCESS_FBINFO(crtc2.vsync.field);
+               address->count = ACCESS_FBINFO(crtc2.vsync.cnt);
+
+               return 0;
+       } else if (address->device == MATROX_ADDRESS_DEVICE_BES &&
+                  (ACCESS_FBINFO(devflags.accelerator) == 
FB_ACCEL_MATROX_MGAG400 ||
+                   ACCESS_FBINFO(devflags.accelerator) == 
FB_ACCEL_MATROX_MGAG200)) {
+
+               /* Interrupts are always needed to update vsync.cnt. */
+               matroxfb_enable_irq(PMINFO 0);
+
+               matroxfb_set_address(PMINFO address);
+
+               address->field = -1; /* N/A */
+               address->count = ACCESS_FBINFO(crtc1.vsync.cnt);
+
+               return 0;
+       }
+
+       return -ENODEV;
+}
+
 /* --------------------------------------------------------------------- */
 
 static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
@@ -868,6 +940,8 @@
        .name    = "Panellink output",
 };
 
+#define MATROXFB_ADDRESS _IOWR('n', 0xFC, struct matrox_address)
+
 static int matroxfb_ioctl(struct inode *inode, struct file *file,
                          unsigned int cmd, unsigned long arg,
                          struct fb_info *info)
@@ -1161,6 +1235,23 @@
                                up_read(&ACCESS_FBINFO(altout).lock);
                                return err;
                        }
+               case MATROXFB_ADDRESS:
+                       {
+                               struct matrox_address address;
+                               int err;
+
+                               if (copy_from_user(&address, argp, 
sizeof(address)))
+                                       return -EFAULT;
+
+                               err = matroxfb_address(PMINFO &address);
+                               if (err)
+                                       return err;
+
+                               if (copy_to_user(argp, &address, 
sizeof(address)))
+                                       return -EFAULT;
+
+                               return 0;
+                       }
        }
        return -ENOTTY;
 }
diff -urN matrox.6/matroxfb_base.h matrox/matroxfb_base.h
--- matrox.6/matroxfb_base.h    2005-10-26 00:29:13.000000000 +0300
+++ matrox/matroxfb_base.h      2005-10-26 01:16:59.000000000 +0300
@@ -364,6 +364,17 @@
 struct matrox_vsync {
        wait_queue_head_t       wait;
        unsigned int            cnt;
+       unsigned int            field;
+};
+
+#define MATROX_ADDRESS_DEVICE_CRTC1    0
+#define MATROX_ADDRESS_DEVICE_BES      1       
+#define MATROX_ADDRESS_DEVICE_CRTC2    2
+struct matrox_address {
+       u32 device;
+       u32 field;
+       u32 count;
+       u32 offset[6];
 };
 
 struct matrox_fb_info {
@@ -397,6 +408,8 @@
                int             mnp;
        struct matroxfb_dh_fb_info*     info;
        struct rw_semaphore     lock;
+               int             pan;
+               struct matrox_address address;
                              } crtc2;
        struct {
        struct rw_semaphore     lock;
Index: matrox.h
===================================================================
RCS file: /cvs/directfb/DirectFB/gfxdrivers/matrox/matrox.h,v
retrieving revision 1.38
diff -u -r1.38 matrox.h
--- matrox.h    26 Oct 2005 06:33:46 -0000      1.38
+++ matrox.h    27 Oct 2005 16:39:59 -0000
@@ -149,4 +149,16 @@
      return ret;
 }
 
+#define MATROX_ADDRESS_DEVICE_CRTC1     0
+#define MATROX_ADDRESS_DEVICE_BES       1
+#define MATROX_ADDRESS_DEVICE_CRTC2     2
+struct matrox_address
+{
+     __u32 device;
+     __u32 field;
+     __u32 count;
+     __u32 offset[6];
+};
+#define MATROXFB_ADDRESS _IOWR('n', 0xFC, struct matrox_address)
+
 #endif
Index: matrox_bes.c
===================================================================
RCS file: /cvs/directfb/DirectFB/gfxdrivers/matrox/matrox_bes.c,v
retrieving revision 1.58
diff -u -r1.58 matrox_bes.c
--- matrox_bes.c        26 Oct 2005 07:23:16 -0000      1.58
+++ matrox_bes.c        27 Oct 2005 16:40:00 -0000
@@ -54,6 +54,7 @@
 
 #include <direct/mem.h>
 
+#include <fbdev/fbdev.h>
 
 #include "regs.h"
 #include "mmio.h"
@@ -61,6 +62,7 @@
 
 typedef struct {
      CoreLayerRegionConfig config;
+     __u32 last_count;
 
      /* Stored registers */
      struct {
@@ -260,6 +262,8 @@
      {
           bes_calc_regs( mdrv, mbes, config, surface );
           bes_set_regs( mdrv, mbes, true );
+
+          mbes->last_count = 0;
      }
 
      /* set color key */
@@ -316,10 +320,36 @@
      MatroxDriverData   *mdrv = (MatroxDriverData*) driver_data;
      MatroxBesLayerData *mbes = (MatroxBesLayerData*) layer_data;
 
+#if 0
      bes_calc_regs( mdrv, mbes, &mbes->config, surface );
      bes_set_regs( mdrv, mbes, flags & DSFLIP_ONSYNC );
 
      dfb_surface_flip_buffers( surface, false );
+#else
+     {
+          FBDev                 *dfb_fbdev = dfb_system_data();
+          struct matrox_address  address;
+
+          bes_calc_regs( mdrv, mbes, &mbes->config, surface );
+
+          address.device    = MATROX_ADDRESS_DEVICE_BES;
+          address.field     = -1;
+          address.count     = mbes->last_count + 1;
+          address.offset[0] = mbes->regs.besA1ORG;
+          address.offset[1] = mbes->regs.besA2ORG;
+          address.offset[2] = mbes->regs.besA1CORG;
+          address.offset[3] = mbes->regs.besA2CORG;
+          address.offset[4] = mbes->regs.besA1C3ORG;
+          address.offset[5] = mbes->regs.besA2C3ORG;
+
+          if (ioctl( dfb_fbdev->fd, MATROXFB_ADDRESS, &address ))
+               D_ERROR( "DirectFB/Matrox/BES Address ioctl() failed!\n" );
+
+          dfb_surface_flip_buffers( surface, address.count == mbes->last_count 
);
+
+          mbes->last_count = address.count;
+     }
+#endif
 
      if (flags & DSFLIP_WAIT)
           dfb_screen_wait_vsync( mdrv->primary );
Index: matrox_crtc2.c
===================================================================
RCS file: /cvs/directfb/DirectFB/gfxdrivers/matrox/matrox_crtc2.c,v
retrieving revision 1.31
diff -u -r1.31 matrox_crtc2.c
--- matrox_crtc2.c      26 Oct 2005 07:26:16 -0000      1.31
+++ matrox_crtc2.c      27 Oct 2005 16:40:00 -0000
@@ -61,7 +61,10 @@
 typedef struct {
      CoreLayerRegionConfig config;
      DFBColorAdjustment    adj;
-     int                   field;
+     __u32                 parity;
+     __u32                 last_parity;
+     __u32                 last_field;
+     __u32                 last_count;
 
      /* Stored registers */
      struct {
@@ -247,7 +250,7 @@
      mcrtc2->config = *config;
 
      if (updated & CLRCF_PARITY)
-          mcrtc2->field = !config->parity;
+          mcrtc2->parity = !config->parity;
 
      if (updated & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT |
                     CLRCF_SURFACE_CAPS | CLRCF_ALPHA_RAMP | CLRCF_SURFACE)) {
@@ -257,6 +260,10 @@
           ret = crtc2_enable_output( mdrv, mcrtc2 );
           if (ret)
                return ret;
+
+          mcrtc2->last_parity = 1;
+          mcrtc2->last_field = 0;
+          mcrtc2->last_count = 0;
      }
 
      return DFB_OK;
@@ -286,6 +293,7 @@
 {
      MatroxDriverData     *mdrv    = (MatroxDriverData*) driver_data;
      MatroxCrtc2LayerData *mcrtc2  = (MatroxCrtc2LayerData*) layer_data;
+#if 0
      volatile __u8        *mmio    = mdrv->mmio_base;
 
      crtc2_calc_buffer( mdrv, mcrtc2, surface );
@@ -293,7 +301,7 @@
      if (mcrtc2->config.options & DLOP_FIELD_PARITY) {
           int field = (mga_in32( mmio, C2VCOUNT ) & C2FIELD) ? 1 : 0;
 
-          while (field == mcrtc2->field) {
+          while (field == mcrtc2->parity) {
                dfb_screen_wait_vsync( mdrv->secondary );
 
                field = (mga_in32( mmio, C2VCOUNT ) & C2FIELD) ? 1 : 0;
@@ -302,6 +310,38 @@
      crtc2_set_buffer( mdrv, mcrtc2 );
 
      dfb_surface_flip_buffers( surface, false );
+#else
+     {
+          FBDev                 *dfb_fbdev = dfb_system_data();
+          struct matrox_address  address;
+          __u32                  diff;
+
+          crtc2_calc_buffer( mdrv, mcrtc2, surface );
+
+          address.device    = MATROX_ADDRESS_DEVICE_CRTC2;
+          address.field     = (mcrtc2->config.options & DLOP_FIELD_PARITY) ? 
mcrtc2->parity : -1;
+          address.count     = mcrtc2->last_count + 2;
+          address.offset[0] = mcrtc2->regs.c2STARTADD0;
+          address.offset[1] = mcrtc2->regs.c2STARTADD1;
+          address.offset[2] = mcrtc2->regs.c2PL2STARTADD0;
+          address.offset[3] = mcrtc2->regs.c2PL2STARTADD1;
+          address.offset[4] = mcrtc2->regs.c2PL3STARTADD0;
+          address.offset[5] = mcrtc2->regs.c2PL3STARTADD1;
+
+          if (ioctl( dfb_fbdev->fd, MATROXFB_ADDRESS, &address ))
+               D_ERROR( "DirectFB/Matrox/CRTC2 Address ioctl() failed!\n" );
+
+          diff = address.count >= mcrtc2->last_count ?
+               address.count - mcrtc2->last_count :
+               0xFFFFFFFF - mcrtc2->last_count + address.count;
+
+          dfb_surface_flip_buffers( surface, diff == 0 || (diff == 1 && 
mcrtc2->last_field == mcrtc2->last_parity) );
+
+          mcrtc2->last_count = address.count;
+          mcrtc2->last_field = address.field;
+          mcrtc2->last_parity = (mcrtc2->config.options & DLOP_FIELD_PARITY) ? 
mcrtc2->parity : !address.field;
+     }
+#endif
 
      if (flags & DSFLIP_WAIT)
           dfb_screen_wait_vsync( mdrv->secondary );
Index: libvo/vo_dfbmga.c
===================================================================
RCS file: /cvsroot/mplayer/main/libvo/vo_dfbmga.c,v
retrieving revision 1.29
diff -u -r1.29 vo_dfbmga.c
--- libvo/vo_dfbmga.c   26 Oct 2005 07:41:41 -0000      1.29
+++ libvo/vo_dfbmga.c   26 Oct 2005 07:44:57 -0000
@@ -106,6 +106,8 @@
 
 static int is_g200;
 
+static int top_field_first;
+
 /******************************
 *          vo_dfbmga         *
 ******************************/
@@ -313,6 +315,9 @@
                     } else if (!strncmp(vo_subdevice, "bottom", 6)) {
                          field_parity = 1;
                          vo_subdevice += 6;
+                    } else if (!strncmp(vo_subdevice, "auto", 4)) {
+                         field_parity = 2;
+                         vo_subdevice += 4;
                     } else {
                          show_help = 1;
                          break;
@@ -372,9 +377,10 @@
                        "    single   Use single buffering\n"
                        "    double   Use double buffering\n"
                        "    triple   Use triple buffering\n"
-                       "  fieldparity=(top|bottom)\n"
+                       "  fieldparity=(top|bottom|auto)\n"
                        "    top      Top field first\n"
                        "    bottom   Bottom field first\n"
+                       "    auto     Automatic\n"
                        "  tvnorm=(pal|ntsc|auto)\n"
                        "    pal      Force PAL\n"
                        "    ntsc     Force NTSC\n"
@@ -712,6 +718,9 @@
           case 1:
                mp_msg( MSGT_VO, MSGL_INFO, "Bottom field first\n");
                break;
+          case 2:
+               mp_msg( MSGT_VO, MSGL_INFO, "Automatic\n");
+               break;
           }
 
           switch (dlc.pixelformat) {
@@ -745,7 +754,7 @@
           }
 
 #if DIRECTFBVERSION > 916
-          if (field_parity != -1)
+          if (field_parity == 0 || field_parity == 1)
                crtc2->SetFieldParity( crtc2, field_parity );
 #endif
 
@@ -1165,9 +1174,13 @@
                blit_to_screen();
 
      if (flipping) {
-          if (use_crtc2)
+          if (use_crtc2) {
+#if DIRECTFBVERSION > 916
+               if (field_parity == 2)
+                    crtc2->SetFieldParity( crtc2, !top_field_first );
+#endif
                c2frame->Flip( c2frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : 
DSFLIP_ONSYNC );
-          else
+          } else
                besframe->Flip( besframe, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : 
DSFLIP_ONSYNC );
 
           if (!use_spic) {
@@ -1284,6 +1297,8 @@
 static uint32_t
 draw_image( mp_image_t *mpi )
 {
+     top_field_first = mpi->fields & MP_IMGFIELD_TOP_FIRST;
+
      if (mpi->flags & MP_IMGFLAG_DIRECT) {
           current_buf = (int) mpi->priv;
           return VO_TRUE;
_______________________________________________
directfb-dev mailing list
[email protected]
http://mail.directfb.org/cgi-bin/mailman/listinfo/directfb-dev

Reply via email to