Here's a quick attempt at triple buffering. When the surface is flipped
the old front buffer is left idle until the next flip. So if Flip() 
doesn't get called faster than what the refresh rate is no tearing should
occur. No need for vsync. I tried it with CRTC2 and BES /w mplayer and it
seems to work. I've attached a patch to mplayer to make this work.

Does this improve things for anyone? Brian?

-- 
Ville Syrj�l�
[EMAIL PROTECTED]
http://www.sci.fi/~syrjala/
diff -urN DirectFB/include/directfb.h DirectFB/include/directfb.h
--- DirectFB/include/directfb.h Fri Dec 27 20:40:11 2002
+++ DirectFB/include/directfb.h Fri Jan  3 02:07:59 2003
@@ -407,7 +407,8 @@
 typedef enum {
      DLBM_FRONTONLY  = 0x00000000,      /* no backbuffer */
      DLBM_BACKVIDEO  = 0x00000001,      /* backbuffer in video memory */
-     DLBM_BACKSYSTEM = 0x00000002       /* backbuffer in system memory */
+     DLBM_BACKSYSTEM = 0x00000002,      /* backbuffer in system memory */
+     DLBM_TRIPLE     = 0x00000004
 } DFBDisplayLayerBufferMode;
 
 /*
@@ -472,7 +473,7 @@
                                            by line in the buffer. <br>The first
                                            field is followed by the second one
                                            in the buffer. */
-     DSCAPS_STATIC_ALLOC = 0x00000100   /* The amount of video or system memory
+     DSCAPS_STATIC_ALLOC = 0x00000100,  /* The amount of video or system memory
                                            allocated for the surface is never
                                            less than its initial value. This
                                            way a surface can be resized
@@ -482,6 +483,7 @@
                                            surfaces that need a guaranteed
                                            space in video memory after
                                            resizing. */
+     DSCAPS_TRIPLE       = 0x00000200
 } DFBSurfaceCapabilities;
 
 /*
diff -urN DirectFB/src/core/layers.c DirectFB/src/core/layers.c
--- DirectFB/src/core/layers.c  Sat Dec 28 04:18:46 2002
+++ DirectFB/src/core/layers.c  Fri Jan  3 02:39:33 2003
@@ -956,6 +956,7 @@
           case DLBM_FRONTONLY:
                return DFB_UNSUPPORTED;
 
+          case DLBM_TRIPLE:
           case DLBM_BACKVIDEO:
                return layer->funcs->FlipBuffers( layer,
                                                  layer->driver_data,
@@ -1544,6 +1545,9 @@
                case DLBM_FRONTONLY:
                     break;
 
+               case DLBM_TRIPLE:
+                    caps |= DSCAPS_TRIPLE;
+                    /* fall through */
                case DLBM_BACKVIDEO:
                     caps |= DSCAPS_FLIPPING;
                     break;
@@ -1581,6 +1585,9 @@
      
      if (shared->config.buffermode != config->buffermode) {
           switch (config->buffermode) {
+               case DLBM_TRIPLE:
+                    shared->surface->caps |= DSCAPS_TRIPLE;
+                    /* fall through */
                case DLBM_BACKVIDEO:
                     shared->surface->caps |= DSCAPS_FLIPPING;
                     ret = dfb_surface_reconfig( shared->surface,
diff -urN DirectFB/src/core/surfaces.c DirectFB/src/core/surfaces.c
--- DirectFB/src/core/surfaces.c        Sat Dec 28 04:18:46 2002
+++ DirectFB/src/core/surfaces.c        Fri Jan  3 02:40:46 2003
@@ -140,6 +140,16 @@
                fusion_object_destroy( &s->object );
                return ret;
           }
+          if (caps & DSCAPS_TRIPLE) {
+               ret = dfb_surface_allocate_buffer( s, policy, &s->back_buffer2 );
+               if (ret) {
+                    dfb_surface_deallocate_buffer( s, s->back_buffer );
+                    dfb_surface_deallocate_buffer( s, s->front_buffer );
+
+                    fusion_object_destroy( &s->object );
+                    return ret;
+               }
+          }
      }
      else
           s->back_buffer = s->front_buffer;
@@ -166,6 +176,9 @@
      if (policy == CSP_VIDEOONLY)
           return DFB_UNSUPPORTED;
 
+     if (caps & DSCAPS_TRIPLE)
+          return DFB_UNSUPPORTED;
+
      s = (CoreSurface*) fusion_object_create( dfb_gfxcard_surface_pool() );
 
      ret = dfb_surface_init( s, width, height, format, caps, palette );
@@ -283,6 +296,23 @@
                dfb_surfacemanager_unlock( surface->manager );
                return ret;
           }
+          if (surface->caps & DSCAPS_TRIPLE) {
+               ret = dfb_surface_reallocate_buffer( surface, surface->back_buffer2 );
+               if (ret) {
+                    surface->width  = old_width;
+                    surface->height = old_height;
+                    surface->format = old_format;
+
+                    dfb_surface_reallocate_buffer( surface, surface->back_buffer );
+                    dfb_surface_reallocate_buffer( surface, surface->front_buffer );
+
+                    skirmish_dismiss( &surface->front_lock );
+                    skirmish_dismiss( &surface->back_lock );
+
+                    dfb_surfacemanager_unlock( surface->manager );
+                    return ret;
+               }
+          }
      }
 
      dfb_surfacemanager_unlock( surface->manager );
@@ -316,6 +346,7 @@
      DFBResult      ret;
      SurfaceBuffer *old_front;
      SurfaceBuffer *old_back;
+     SurfaceBuffer *old_back2;
      bool           new_front = surface->front_buffer->policy != front_policy;
 
      if (surface->front_buffer->flags & SBF_FOREIGN_SYSTEM ||
@@ -331,6 +362,7 @@
 
      old_front = surface->front_buffer;
      old_back = surface->back_buffer;
+     old_back2 = surface->back_buffer2;
 
      if (new_front) {
           ret = dfb_surface_allocate_buffer( surface, front_policy, 
&surface->front_buffer );
@@ -353,6 +385,20 @@
                skirmish_dismiss( &surface->back_lock );
                return ret;
           }
+          if (surface->caps & DSCAPS_TRIPLE) {
+               ret = dfb_surface_allocate_buffer( surface, back_policy, 
+&surface->back_buffer2 );
+               if (ret) {
+                    dfb_surface_deallocate_buffer( surface, surface->back_buffer );
+                    if (new_front) {
+                         dfb_surface_deallocate_buffer( surface, 
+surface->front_buffer );
+                         surface->front_buffer = old_front;
+                    }
+
+                    skirmish_dismiss( &surface->front_lock );
+                    skirmish_dismiss( &surface->back_lock );
+                    return ret;
+               }
+          }
      }
      else {
           surface->back_buffer = surface->front_buffer;
@@ -361,8 +407,11 @@
      if (new_front)
           dfb_surface_deallocate_buffer( surface, old_front );
 
-     if (old_front != old_back)
+     if (old_front != old_back) {
           dfb_surface_deallocate_buffer ( surface, old_back );
+          if (surface->caps & DSCAPS_TRIPLE)
+               dfb_surface_deallocate_buffer ( surface, old_back2 );
+     }
 
      dfb_surface_notify_listeners( surface, CSNF_SIZEFORMAT |
                                    CSNF_SYSTEM | CSNF_VIDEO );
@@ -415,7 +464,12 @@
 
      tmp = surface->front_buffer;
      surface->front_buffer = surface->back_buffer;
-     surface->back_buffer = tmp;
+     if (surface->caps & DSCAPS_TRIPLE) {
+          surface->back_buffer = surface->back_buffer2;
+          surface->back_buffer2 = tmp;
+     }
+     else
+          surface->back_buffer = tmp;
 
      dfb_surfacemanager_unlock( surface->manager );
 
@@ -644,8 +698,11 @@
      dfb_surface_deallocate_buffer( surface, surface->front_buffer );
 
      /* deallocate second buffer if it's another one */
-     if (surface->back_buffer != surface->front_buffer)
+     if (surface->back_buffer != surface->front_buffer) {
           dfb_surface_deallocate_buffer( surface, surface->back_buffer );
+          if (surface->caps & DSCAPS_TRIPLE)
+               dfb_surface_deallocate_buffer( surface, surface->back_buffer2 );
+     }
 
      /* destroy the locks */
      skirmish_destroy( &surface->front_lock );
diff -urN DirectFB/src/core/surfaces.h DirectFB/src/core/surfaces.h
--- DirectFB/src/core/surfaces.h        Sat Dec 28 04:18:46 2002
+++ DirectFB/src/core/surfaces.h        Fri Jan  3 02:38:57 2003
@@ -150,11 +149,12 @@
 
      SurfaceBuffer         *back_buffer;   /* buffer for (reading&)writing
                                               (drawing/blitting destination) */
+     SurfaceBuffer         *back_buffer2;  /* buffer for (reading&)writing
+                                              (drawing/blitting destination) */
      FusionSkirmish         back_lock;     /* skirmish lock for back buffer,
                                               mutexes are outside of
                                               SurfaceBuffer because of flipping
                                               that just swaps the pointers */
-
      SurfaceManager        *manager;
 };
 
--- main/libvo/vo_dfbmga.c      Tue Dec  3 23:49:46 2002
+++ main/libvo/vo_dfbmga.c      Sat Jan  4 00:35:21 2003
@@ -272,7 +272,7 @@
           dlc.flags       = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | 
DLCONF_BUFFERMODE;
           dlc.width       = in_width;
           dlc.height      = in_height;
-          dlc.buffermode  = DLBM_BACKVIDEO;
+          dlc.buffermode  = DLBM_TRIPLE;
 
           if (bes->TestConfiguration( bes, &dlc, &failed ) != DFB_OK)
                return -1;
@@ -311,7 +311,7 @@
 
      if (use_crtc2) {
           dlc.flags      = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
-          dlc.buffermode = DLBM_BACKVIDEO;
+          dlc.buffermode = DLBM_TRIPLE;
 
           switch (dlc.pixelformat) {
           case DSPF_I420:
@@ -363,6 +363,8 @@
           drect.w = out_width;
           drect.h = out_height;
 
+          c2frame->Clear( c2frame, 0, 0, 0, 0 );
+          c2frame->Flip( c2frame, NULL, 0 );
           c2frame->Clear( c2frame, 0, 0, 0, 0 );
           c2frame->Flip( c2frame, NULL, 0 );
           c2frame->Clear( c2frame, 0, 0, 0, 0 );

Reply via email to