Ok here's a new triple buffering patch.

What's different to the previous patch:
- I left DSCAPS_FLIPPING as a double buffer only cap. The previous patch
had DSCAPS_TRIPLE imply DSCAPS_FLIPPING. Not sure which way is better
though.

- fbdev support. It's pretty much _untested_ as of yet. I've been running
XDirectFB w/ desktop-buffer-mode=frontonly and mplayer w/
single,double,triple buffering for a few days without problems but I
haven't tested the fbdev double and triple buffering and changing between
buffer modes.

- I paid more attention to buffer allocation,deallocation etc.

- I like this one a whole lot more :) I think it could be commited to cvs
if the fbdev part doesn't break somehow. Comments, testing and code review
are welcome.

***

I've also attached few patches to mplayer. First one implements new
command lined options -triple and -notriple. Second one is for dfbmga and
include alut44 changes, single, double and triple buffering changes and
some general cleanups.

- If you use -triple you shouldn't need -vsync.
- With -double you need -vsync to avoid tearing.
- Without -double and -triple you get single buffering and obviosly -vsync
is needed to avoid tearing.

CRTC2 seems to like triple buffering very much but BES isn't happy with
it. -double -vsync is much better for BES.

-- 
Ville Syrj�l�
[EMAIL PROTECTED]
http://www.sci.fi/~syrjala/
diff -urN DirectFB/include/directfb.h DirectFB/include/directfb.h
--- DirectFB/include/directfb.h 2003-03-20 21:15:20.000000000 +0200
+++ DirectFB/include/directfb.h 2003-03-21 22:14:47.000000000 +0200
@@ -409,7 +409,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       /* triple buffering */
 } DFBDisplayLayerBufferMode;
 
 /*
@@ -474,7 +475,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
@@ -484,6 +485,7 @@
                                            surfaces that need a guaranteed
                                            space in video memory after
                                            resizing. */
+     DSCAPS_TRIPLE       = 0x00000200   /* Surface is triple buffered */
 } DFBSurfaceCapabilities;
 
 /*
diff -urN DirectFB/src/core/fbdev/fbdev.c DirectFB/src/core/fbdev/fbdev.c
--- DirectFB/src/core/fbdev/fbdev.c     2003-03-20 21:15:21.000000000 +0200
+++ DirectFB/src/core/fbdev/fbdev.c     2003-03-21 22:15:10.000000000 +0200
@@ -224,7 +224,7 @@
 #ifdef SUPPORT_RGB332
 static DFBResult dfb_fbdev_set_rgb332_palette();
 #endif
-static DFBResult dfb_fbdev_pan( int buffer );
+static DFBResult dfb_fbdev_pan( int offset );
 static DFBResult dfb_fbdev_set_mode( DisplayLayer          *layer,
                                      VideoMode             *mode,
                                      DFBDisplayLayerConfig *config );
@@ -967,8 +967,8 @@
 
      if ((flags & DSFLIP_WAITFORSYNC) && !dfb_config->pollvsync_after)
           dfb_layer_wait_vsync( layer );
-     
-     ret = dfb_fbdev_pan( surface->back_buffer->video.offset ? 1 : 0 );
+
+     ret = dfb_fbdev_pan( surface->back_buffer->video.offset );
      if (ret)
           return ret;
 
@@ -1172,7 +1172,9 @@
      DFBSurfaceCapabilities  caps = DSCAPS_VIDEOONLY;
 
      /* determine further capabilities */
-     if (config->buffermode != DLBM_FRONTONLY)
+     if (config->buffermode == DLBM_TRIPLE)
+          caps |= DSCAPS_TRIPLE;
+     else if (config->buffermode != DLBM_FRONTONLY)
           caps |= DSCAPS_FLIPPING;
 
      /* allocate surface object */
@@ -1181,7 +1183,7 @@
           return DFB_FAILURE;
 
      /* reallocation just needs an allocated buffer structure */
-     surface->back_buffer  =
+     surface->idle_buffer = surface->back_buffer =
      surface->front_buffer = shcalloc( 1, sizeof(SurfaceBuffer) );
 
      if (!surface->front_buffer) {
@@ -1325,19 +1327,19 @@
 /*
  * pans display (flips buffer) using fbdev ioctl
  */
-static DFBResult dfb_fbdev_pan( int buffer )
+static DFBResult dfb_fbdev_pan( int offset )
 {
      struct fb_var_screeninfo var;
 
      var = dfb_fbdev->shared->current_var;
 
-     if (var.yres_virtual < var.yres*(buffer+1)) {
+     if (var.yres_virtual < offset + var.yres) {
           BUG( "panning buffer out of range" );
           return DFB_BUG;
      }
 
      var.xoffset = 0;
-     var.yoffset = var.yres * buffer;
+     var.yoffset = offset;
 
      dfb_gfxcard_sync();
 
@@ -1380,8 +1382,10 @@
      var.yoffset = 0;
 
      if (config) {
-          if (config->buffermode == DLBM_BACKVIDEO)
-               vyres <<= 1;
+          if (config->buffermode == DLBM_TRIPLE)
+               vyres *= 3;
+          else if (config->buffermode == DLBM_BACKVIDEO)
+               vyres *= 2;
 
           var.bits_per_pixel = DFB_BYTES_PER_PIXEL(config->pixelformat) * 8;
 
@@ -1558,7 +1562,8 @@
 
           switch (config->buffermode) {
                case DLBM_FRONTONLY:
-                    surface->caps &= ~DSCAPS_FLIPPING;
+                    surface->caps &= ~(DSCAPS_FLIPPING | DSCAPS_TRIPLE);
+
                     if (surface->back_buffer != surface->front_buffer) {
                          if (surface->back_buffer->system.addr)
                               shfree( surface->back_buffer->system.addr );
@@ -1567,9 +1572,50 @@
 
                          surface->back_buffer = surface->front_buffer;
                     }
+
+                    if (surface->idle_buffer != surface->front_buffer) {
+                         if (surface->idle_buffer->system.addr)
+                              shfree( surface->idle_buffer->system.addr );
+
+                         shfree( surface->idle_buffer );
+
+                         surface->idle_buffer = surface->front_buffer;
+                    }
                     break;
                case DLBM_BACKVIDEO:
                     surface->caps |= DSCAPS_FLIPPING;
+                    surface->caps &= ~DSCAPS_TRIPLE;
+
+                    if (surface->back_buffer == surface->front_buffer) {
+                         surface->back_buffer = shcalloc( 1, sizeof(SurfaceBuffer) );
+                    }
+                    else {
+                         if (surface->back_buffer->system.addr) {
+                              shfree( surface->back_buffer->system.addr );
+                              surface->back_buffer->system.addr = NULL;
+                         }
+
+                         surface->back_buffer->system.health = CSH_INVALID;
+                    }
+                    surface->back_buffer->surface = surface;
+                    surface->back_buffer->policy = CSP_VIDEOONLY;
+                    surface->back_buffer->video.health = CSH_STORED;
+                    surface->back_buffer->video.pitch = fix.line_length;
+                    surface->back_buffer->video.offset =
+                                   surface->back_buffer->video.pitch * var.yres;
+
+                    if (surface->idle_buffer != surface->front_buffer) {
+                         if (surface->idle_buffer->system.addr)
+                              shfree( surface->idle_buffer->system.addr );
+
+                         shfree( surface->idle_buffer );
+
+                         surface->idle_buffer = surface->front_buffer;
+                    }
+                    break;
+               case DLBM_TRIPLE:
+                    surface->caps |= DSCAPS_FLIPPING | DSCAPS_TRIPLE;
+
                     if (surface->back_buffer == surface->front_buffer) {
                          surface->back_buffer = shcalloc( 1, sizeof(SurfaceBuffer) );
                     }
@@ -1587,9 +1633,29 @@
                     surface->back_buffer->video.pitch = fix.line_length;
                     surface->back_buffer->video.offset =
                                    surface->back_buffer->video.pitch * var.yres;
+
+                    if (surface->idle_buffer == surface->front_buffer) {
+                         surface->idle_buffer = shcalloc( 1, sizeof(SurfaceBuffer) );
+                    }
+                    else {
+                         if (surface->idle_buffer->system.addr) {
+                              shfree( surface->idle_buffer->system.addr );
+                              surface->idle_buffer->system.addr = NULL;
+                         }
+
+                         surface->idle_buffer->system.health = CSH_INVALID;
+                    }
+                    surface->idle_buffer->surface = surface;
+                    surface->idle_buffer->policy = CSP_VIDEOONLY;
+                    surface->idle_buffer->video.health = CSH_STORED;
+                    surface->idle_buffer->video.pitch = fix.line_length;
+                    surface->idle_buffer->video.offset =
+                                   surface->idle_buffer->video.pitch * var.yres * 2;
                     break;
                case DLBM_BACKSYSTEM:
                     surface->caps |= DSCAPS_FLIPPING;
+                    surface->caps &= ~DSCAPS_TRIPLE;
+
                     if (surface->back_buffer == surface->front_buffer) {
                          surface->back_buffer = shcalloc( 1, sizeof(SurfaceBuffer) );
                     }
@@ -1605,6 +1671,15 @@
 
                     surface->back_buffer->system.addr =
                          shmalloc( surface->back_buffer->system.pitch * var.yres );
+
+                    if (surface->idle_buffer != surface->front_buffer) {
+                         if (surface->idle_buffer->system.addr)
+                              shfree( surface->idle_buffer->system.addr );
+
+                         shfree( surface->idle_buffer );
+
+                         surface->idle_buffer = surface->front_buffer;
+                    }
                     break;
           }
 
diff -urN DirectFB/src/core/input.c DirectFB/src/core/input.c
--- DirectFB/src/core/input.c   2003-02-18 22:49:04.000000000 +0200
+++ DirectFB/src/core/input.c   2003-03-21 22:14:47.000000000 +0200
@@ -1315,7 +1315,7 @@
      } while (errno == EEXIST);
 
      if (dfb_surface_soft_lock( surface, DSLF_READ, &data, &pitch,
-                                (surface->caps & DSCAPS_FLIPPING) )) {
+                                surface->caps & (DSCAPS_FLIPPING | DSCAPS_TRIPLE) )) {
           close( fd );
           return;
      }
@@ -1356,7 +1356,8 @@
           ((__u8*)data) += pitch;
      }
 
-     dfb_surface_unlock( surface, (surface->caps & DSCAPS_FLIPPING) );
+     dfb_surface_unlock( surface,
+                         surface->caps & (DSCAPS_FLIPPING | DSCAPS_TRIPLE) );
 
      close( fd );
 }
diff -urN DirectFB/src/core/layers.c DirectFB/src/core/layers.c
--- DirectFB/src/core/layers.c  2003-03-19 13:32:15.000000000 +0200
+++ DirectFB/src/core/layers.c  2003-03-21 22:14:47.000000000 +0200
@@ -1042,6 +1042,7 @@
           case DLBM_FRONTONLY:
                return DFB_UNSUPPORTED;
 
+          case DLBM_TRIPLE:
           case DLBM_BACKVIDEO:
                return layer->funcs->FlipBuffers( layer,
                                                  layer->driver_data,
@@ -1808,6 +1809,10 @@
                case DLBM_FRONTONLY:
                     break;
 
+               case DLBM_TRIPLE:
+                    caps |= DSCAPS_TRIPLE;
+                    break;
+
                case DLBM_BACKVIDEO:
                     caps |= DSCAPS_FLIPPING;
                     break;
@@ -1851,18 +1856,26 @@
      
      if (shared->config.buffermode != config->buffermode) {
           switch (config->buffermode) {
+               case DLBM_TRIPLE:
+                    shared->surface->caps |= DSCAPS_TRIPLE;
+                    shared->surface->caps &= ~DSCAPS_FLIPPING;
+                    ret = dfb_surface_reconfig( shared->surface,
+                                                CSP_VIDEOONLY, CSP_VIDEOONLY );
+                    break;
                case DLBM_BACKVIDEO:
                     shared->surface->caps |= DSCAPS_FLIPPING;
+                    shared->surface->caps &= ~DSCAPS_TRIPLE;
                     ret = dfb_surface_reconfig( shared->surface,
                                                 CSP_VIDEOONLY, CSP_VIDEOONLY );
                     break;
                case DLBM_BACKSYSTEM:
                     shared->surface->caps |= DSCAPS_FLIPPING;
+                    shared->surface->caps &= ~DSCAPS_TRIPLE;
                     ret = dfb_surface_reconfig( shared->surface,
                                                 CSP_VIDEOONLY, CSP_SYSTEMONLY );
                     break;
                case DLBM_FRONTONLY:
-                    shared->surface->caps &= ~DSCAPS_FLIPPING;
+                    shared->surface->caps &= ~(DSCAPS_FLIPPING | DSCAPS_TRIPLE);
                     ret = dfb_surface_reconfig( shared->surface,
                                                 CSP_VIDEOONLY, CSP_VIDEOONLY );
                     break;
diff -urN DirectFB/src/core/sdl/primary.c DirectFB/src/core/sdl/primary.c
--- DirectFB/src/core/sdl/primary.c     2003-01-29 17:41:45.000000000 +0200
+++ DirectFB/src/core/sdl/primary.c     2003-03-21 22:14:47.000000000 +0200
@@ -273,6 +273,9 @@
 /*     if (config->buffermode == DLBM_FRONTONLY)
           fail |= DLCONF_BUFFERMODE;*/
 
+     if (config->buffermode == DLBM_TRIPLE)
+          fail |= DLCONF_BUFFERMODE;
+
      if (failed)
           *failed = fail;
 
@@ -293,6 +296,9 @@
 
      flags = SDL_HWSURFACE;
 
+     if (config->buffermode == DLBM_TRIPLE)
+          return DFB_UNSUPPORTED;
+
      if (config->buffermode != DLBM_FRONTONLY)
           flags |= SDL_DOUBLEBUF;
 
diff -urN DirectFB/src/core/surfaces.c DirectFB/src/core/surfaces.c
--- DirectFB/src/core/surfaces.c        2003-03-20 21:15:21.000000000 +0200
+++ DirectFB/src/core/surfaces.c        2003-03-21 22:14:47.000000000 +0200
@@ -132,7 +132,7 @@
           return ret;
      }
 
-     if (caps & DSCAPS_FLIPPING) {
+     if (caps & (DSCAPS_FLIPPING | DSCAPS_TRIPLE)) {
           ret = dfb_surface_allocate_buffer( s, policy, &s->back_buffer );
           if (ret) {
                dfb_surface_deallocate_buffer( s, s->front_buffer );
@@ -144,6 +144,18 @@
      else
           s->back_buffer = s->front_buffer;
 
+     if (caps & DSCAPS_TRIPLE) {
+          ret = dfb_surface_allocate_buffer( s, policy, &s->idle_buffer );
+          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->idle_buffer = s->front_buffer;
 
      fusion_object_activate( &s->object );
      
@@ -198,6 +210,8 @@
      else
           s->back_buffer = s->front_buffer;
 
+     /* No triple buffering */
+     s->idle_buffer = s->front_buffer;
 
      fusion_object_activate( &s->object );
      
@@ -268,7 +282,7 @@
           return ret;
      }
 
-     if (surface->caps & DSCAPS_FLIPPING) {
+     if (surface->caps & (DSCAPS_FLIPPING | DSCAPS_TRIPLE)) {
           ret = dfb_surface_reallocate_buffer( surface, surface->back_buffer );
           if (ret) {
                surface->width  = old_width;
@@ -285,6 +299,24 @@
           }
      }
 
+     if (surface->caps & DSCAPS_TRIPLE) {
+          ret = dfb_surface_reallocate_buffer( surface, surface->idle_buffer );
+          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 );
 
      if (DFB_PIXELFORMAT_IS_INDEXED( format ) && !surface->palette) {
@@ -317,6 +349,7 @@
      DFBResult      ret;
      SurfaceBuffer *old_front;
      SurfaceBuffer *old_back;
+     SurfaceBuffer *old_idle;
      bool           new_front = surface->front_buffer->policy != front_policy;
 
      if (surface->front_buffer->flags & SBF_FOREIGN_SYSTEM ||
@@ -332,6 +365,7 @@
 
      old_front = surface->front_buffer;
      old_back = surface->back_buffer;
+     old_idle = surface->idle_buffer;
 
      if (new_front) {
           ret = dfb_surface_allocate_buffer( surface, front_policy, 
&surface->front_buffer );
@@ -342,7 +376,7 @@
           }
      }
 
-     if (surface->caps & DSCAPS_FLIPPING) {
+     if (surface->caps & (DSCAPS_FLIPPING | DSCAPS_TRIPLE)) {
           ret = dfb_surface_allocate_buffer( surface, back_policy, 
&surface->back_buffer );
           if (ret) {
                if (new_front) {
@@ -355,9 +389,27 @@
                return ret;
           }
      }
-     else {
+     else
           surface->back_buffer = surface->front_buffer;
+
+     if (surface->caps & DSCAPS_TRIPLE) {
+          ret = dfb_surface_allocate_buffer( surface, back_policy, 
&surface->idle_buffer );
+          if (ret) {
+               dfb_surface_deallocate_buffer( surface, surface->back_buffer );
+               surface->back_buffer = old_back;
+
+               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->idle_buffer = surface->front_buffer;
 
      if (new_front)
           dfb_surface_deallocate_buffer( surface, old_front );
@@ -365,6 +417,9 @@
      if (old_front != old_back)
           dfb_surface_deallocate_buffer ( surface, old_back );
 
+     if (old_front != old_idle)
+          dfb_surface_deallocate_buffer ( surface, old_idle );
+
      dfb_surface_notify_listeners( surface, CSNF_SIZEFORMAT |
                                    CSNF_SYSTEM | CSNF_VIDEO );
 
@@ -414,9 +469,19 @@
      skirmish_prevail( &surface->front_lock );
      skirmish_prevail( &surface->back_lock );
 
-     tmp = surface->front_buffer;
-     surface->front_buffer = surface->back_buffer;
-     surface->back_buffer = tmp;
+     if (surface->caps & DSCAPS_TRIPLE) {
+          tmp = surface->front_buffer;
+          surface->front_buffer = surface->back_buffer;
+          surface->back_buffer = surface->idle_buffer;
+          surface->idle_buffer = tmp;
+     } else {
+          tmp = surface->front_buffer;
+          surface->front_buffer = surface->back_buffer;
+          surface->back_buffer = tmp;
+
+          /* To avoid problems with buffer deallocation */
+          surface->idle_buffer = surface->front_buffer;
+     }
 
      dfb_surfacemanager_unlock( surface->manager );
 
@@ -648,6 +713,10 @@
      if (surface->back_buffer != surface->front_buffer)
           dfb_surface_deallocate_buffer( surface, surface->back_buffer );
 
+     /* deallocate third buffer if it's another one */
+     if (surface->idle_buffer != surface->front_buffer)
+          dfb_surface_deallocate_buffer( surface, surface->idle_buffer );
+
      /* destroy the locks */
      skirmish_destroy( &surface->front_lock );
      skirmish_destroy( &surface->back_lock );
diff -urN DirectFB/src/core/surfaces.h DirectFB/src/core/surfaces.h
--- DirectFB/src/core/surfaces.h        2002-12-27 21:39:12.000000000 +0200
+++ DirectFB/src/core/surfaces.h        2003-03-21 22:14:47.000000000 +0200
@@ -154,6 +154,7 @@
                                               mutexes are outside of
                                               SurfaceBuffer because of flipping
                                               that just swaps the pointers */
+     SurfaceBuffer         *idle_buffer;   /* triple buffering */
 
      SurfaceManager        *manager;
 };
diff -urN DirectFB/src/core/windows.c DirectFB/src/core/windows.c
--- DirectFB/src/core/windows.c 2003-03-19 13:32:15.000000000 +0200
+++ DirectFB/src/core/windows.c 2003-03-21 22:14:47.000000000 +0200
@@ -1461,7 +1461,7 @@
      update_region( stack, state, stack->num_windows - 1,
                     region->x1, region->y1, region->x2, region->y2 );
 
-     if (surface->caps & DSCAPS_FLIPPING) {
+     if (surface->caps & (DSCAPS_FLIPPING | DSCAPS_TRIPLE)) {
           if (region->x1 == 0 &&
               region->y1 == 0 &&
               region->x2 == surface->width - 1 &&
diff -urN DirectFB/src/display/idirectfbsurface.c 
DirectFB/src/display/idirectfbsurface.c
--- DirectFB/src/display/idirectfbsurface.c     2002-11-21 17:50:54.000000000 +0200
+++ DirectFB/src/display/idirectfbsurface.c     2003-03-21 22:14:47.000000000 +0200
@@ -333,7 +333,7 @@
      if (data->locked)
           return DFB_LOCKED;
 
-     if (!(data->caps & DSCAPS_FLIPPING))
+     if (!(data->caps & (DSCAPS_FLIPPING | DSCAPS_TRIPLE)))
           return DFB_UNSUPPORTED;
 
      if (!data->area.current.w || !data->area.current.h)
diff -urN DirectFB/src/display/idirectfbsurface_layer.c 
DirectFB/src/display/idirectfbsurface_layer.c
--- DirectFB/src/display/idirectfbsurface_layer.c       2002-11-18 20:42:43.000000000 
+0200
+++ DirectFB/src/display/idirectfbsurface_layer.c       2003-03-21 22:14:47.000000000 
+0200
@@ -91,7 +91,7 @@
      if (data->base.locked)
           return DFB_LOCKED;
 
-     if (!(data->base.caps & DSCAPS_FLIPPING))
+     if (!(data->base.caps & (DSCAPS_FLIPPING | DSCAPS_TRIPLE)))
           return DFB_UNSUPPORTED;
 
      if (!data->base.area.current.w || !data->base.area.current.h)
diff -urN DirectFB/src/idirectfb.c DirectFB/src/idirectfb.c
--- DirectFB/src/idirectfb.c    2003-03-20 21:15:21.000000000 +0200
+++ DirectFB/src/idirectfb.c    2003-03-21 22:14:47.000000000 +0200
@@ -419,6 +419,9 @@
                     CoreWindow            *window;
                     DFBWindowCapabilities  window_caps = DWCAPS_NONE;
 
+                    if (caps & DSCAPS_TRIPLE)
+                         return DFB_UNSUPOORTED;
+
                     if (! (desc->flags & DSDESC_WIDTH))
                          width = data->primary.width;
 
@@ -478,7 +481,11 @@
                case DFSCL_EXCLUSIVE:
                     config.flags |= DLCONF_BUFFERMODE;
 
-                    if (caps & DSCAPS_FLIPPING) {
+                    if (caps & DSCAPS_TRIPLE) {
+                         if (caps & DSCAPS_SYSTEMONLY)
+                              return DFB_UNSUPPORTED;
+                         config.buffermode = DLBM_TRIPLE;
+                    } else if (caps & DSCAPS_FLIPPING) {
                          if (caps & DSCAPS_SYSTEMONLY)
                               config.buffermode = DLBM_BACKSYSTEM;
                          else
@@ -531,6 +538,8 @@
           }
      }
 
+     if (caps & DSCAPS_TRIPLE)
+          return DFB_UNSUPPORTED;
 
      if (caps & DSCAPS_VIDEOONLY)
           policy = CSP_VIDEOONLY;
diff -urN DirectFB/src/misc/conf.c DirectFB/src/misc/conf.c
--- DirectFB/src/misc/conf.c    2003-03-20 21:15:21.000000000 +0200
+++ DirectFB/src/misc/conf.c    2003-03-21 22:14:47.000000000 +0200
@@ -139,8 +139,9 @@
     "     videoonly:  Window surface is always stored in video memory.\n"
     "\n"
     " Desktop buffer mode:\n"
-    "  desktop-buffer-mode=(auto|backvideo|backsystem|frontonly)\n"
+    "  desktop-buffer-mode=(auto|triple|backvideo|backsystem|frontonly)\n"
     "     auto:       DirectFB decides depending on hardware.\n"
+    "     triple:     Triple buffering (video only).\n"
     "     backvideo:  Front and back buffer are video only.\n"
     "     backsystem: Back buffer is system only.\n"
     "     frontonly:  There is no back buffer.\n"
@@ -539,6 +540,9 @@
                if (strcmp( value, "auto" ) == 0) {
                     dfb_config->buffer_mode = -1;
                } else
+               if (strcmp( value, "triple" ) == 0) {
+                    dfb_config->buffer_mode = DLBM_TRIPLE;
+               } else
                if (strcmp( value, "backvideo" ) == 0) {
                     dfb_config->buffer_mode = DLBM_BACKVIDEO;
                } else
diff -urN DirectFB/tools/dfbdump.c DirectFB/tools/dfbdump.c
--- DirectFB/tools/dfbdump.c    2003-03-20 21:15:21.000000000 +0200
+++ DirectFB/tools/dfbdump.c    2003-03-21 22:14:47.000000000 +0200
@@ -121,7 +121,8 @@
      }
 
      mem = DFB_BYTES_PER_LINE( surface->format, surface->width ) *
-           surface->height * ((surface->caps & DSCAPS_FLIPPING) ? 2 : 1);
+           surface->height * ((surface->caps & DSCAPS_TRIPLE) ? 3 :
+                              (surface->caps & DSCAPS_FLIPPING) ? 2 : 1);
 
      if (mem < 1024)
           mem = 1024;
@@ -139,6 +140,9 @@
      if (surface->caps & DSCAPS_FLIPPING)
           printf( "flipping     " );
 
+     if (surface->caps & DSCAPS_TRIPLE)
+          printf( "triple       " );
+
      if (surface->caps & DSCAPS_INTERLACED)
           printf( "interlaced   " );
 
diff -urN main/Gui/cfg.c main/Gui/cfg.c
--- main/Gui/cfg.c      2003-03-22 02:10:10.000000000 +0200
+++ main/Gui/cfg.c      2003-03-22 02:12:43.000000000 +0200
@@ -80,6 +80,7 @@
  { "vo_driver",&video_driver_list,CONF_TYPE_STRING_LIST,0,0,0,NULL },
  { "vo_panscan",&vo_panscan,CONF_TYPE_FLOAT,CONF_RANGE,0.0,1.0,NULL },
  { "vo_doublebuffering",&vo_doublebuffering,CONF_TYPE_FLAG,0,0,1,NULL },
+ { "vo_triplebuffering",&vo_triplebuffering,CONF_TYPE_FLAG,0,0,1,NULL },
  { "vo_direct_render",&vo_directrendering,CONF_TYPE_FLAG,0,0,1,NULL },
 #ifdef HAVE_DXR3
  { "vo_dxr3_device",&gtkDXR3Device,CONF_TYPE_STRING,0,0,0,NULL },
diff -urN main/Gui/mplayer/gtk/opts.c main/Gui/mplayer/gtk/opts.c
--- main/Gui/mplayer/gtk/opts.c 2003-03-22 02:10:10.000000000 +0200
+++ main/Gui/mplayer/gtk/opts.c 2003-03-22 02:14:32.000000000 +0200
@@ -53,6 +53,7 @@
 static GtkWidget * CBExtraStereo;
 static GtkWidget * CBNormalize;
 static GtkWidget * CBDoubleBuffer;
+static GtkWidget * CBTripleBuffer;
 static GtkWidget * CBDR;
 static GtkWidget * CBFramedrop;
 static GtkWidget * CBHFramedrop;
@@ -221,6 +222,7 @@
 
 // -- 2. page
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( CBDoubleBuffer ),vo_doublebuffering 
);
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( CBTripleBuffer ),vo_triplebuffering 
);
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( CBDR ),vo_directrendering );
 
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( CBFramedrop ),FALSE );
@@ -529,6 +531,7 @@
 
        // -- 2. page
        vo_doublebuffering=gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( 
CBDoubleBuffer ) );
+       vo_triplebuffering=gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( 
CBTripleBuffer ) );
        vo_directrendering=gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( CBDR ) );
 
         frame_dropping=0;
@@ -903,6 +906,7 @@
     gtk_widget_set_usize( vbox5,250,-2 );
 
   CBDoubleBuffer=AddCheckButton( MSGTR_PREFERENCES_DoubleBuffer,vbox5 );
+  CBTripleBuffer=AddCheckButton( MSGTR_PREFERENCES_TripleBuffer,vbox5 );
   CBDR=AddCheckButton( MSGTR_PREFERENCES_DirectRender,vbox5 );
   CBFramedrop=AddCheckButton( MSGTR_PREFERENCES_FrameDrop,vbox5 );
   CBHFramedrop=AddCheckButton( MSGTR_PREFERENCES_HFrameDrop,vbox5 );
@@ -1267,6 +1271,7 @@
   gtk_signal_connect( GTK_OBJECT( CBSurround ),"toggled",GTK_SIGNAL_FUNC( 
on_CBSurround_toggled ),NULL );
   gtk_signal_connect( GTK_OBJECT( CBExtraStereo ),"toggled",GTK_SIGNAL_FUNC( 
on_CBExtraStereo_toggled ),NULL );
   gtk_signal_connect( GTK_OBJECT( CBDoubleBuffer ),"toggled",GTK_SIGNAL_FUNC( 
on_CBDoubleBuffer_toggled ),NULL );
+  gtk_signal_connect( GTK_OBJECT( CBTripleBuffer ),"toggled",GTK_SIGNAL_FUNC( 
on_CBTripleBuffer_toggled ),NULL );
   gtk_signal_connect( GTK_OBJECT( CBDR ),"toggled",GTK_SIGNAL_FUNC( on_CBDR_toggled 
),NULL );
   gtk_signal_connect( GTK_OBJECT( CBFramedrop ),"toggled",GTK_SIGNAL_FUNC( 
on_CBFramedrop_toggled ),NULL );
   gtk_signal_connect( GTK_OBJECT( CBHFramedrop ),"toggled",GTK_SIGNAL_FUNC( 
on_CBHFramedrop_toggled ),NULL );
diff -urN main/cfg-mplayer.h main/cfg-mplayer.h
--- main/cfg-mplayer.h  2003-02-08 22:52:25.000000000 +0200
+++ main/cfg-mplayer.h  2003-03-22 02:16:31.000000000 +0200
@@ -52,6 +52,7 @@
 #endif
 
 extern int vo_doublebuffering;
+extern int vo_triplebuffering;
 extern int vo_vsync;
 extern int vo_fsmode;
 extern int vo_dbpp;
@@ -273,6 +274,9 @@
        // double buffering:  (mga/xmga, xv, vidix, vesa, fbdev)
        {"double", &vo_doublebuffering, CONF_TYPE_FLAG, 0, 0, 1, NULL},
        {"nodouble", &vo_doublebuffering, CONF_TYPE_FLAG, 0, 1, 0, NULL},
+       // triple buffering
+       {"triple", &vo_triplebuffering, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+       {"notriple", &vo_triplebuffering, CONF_TYPE_FLAG, 0, 1, 0, NULL},
        // wait for v-sync (vesa)
        {"vsync", &vo_vsync, CONF_TYPE_FLAG, 0, 0, 1, NULL},
        {"novsync", &vo_vsync, CONF_TYPE_FLAG, 0, 1, 0, NULL},
diff -urN main/help/help_mp-en.h main/help/help_mp-en.h
--- main/help/help_mp-en.h      2003-03-22 02:10:10.000000000 +0200
+++ main/help/help_mp-en.h      2003-03-22 02:17:07.000000000 +0200
@@ -513,6 +513,7 @@
 #define MSGTR_PREFERENCES_Coefficient "Coefficient:"
 #define MSGTR_PREFERENCES_AudioDelay "Audio delay"
 #define MSGTR_PREFERENCES_DoubleBuffer "Enable double buffering"
+#define MSGTR_PREFERENCES_TripleBuffer "Enable triple buffering"
 #define MSGTR_PREFERENCES_DirectRender "Enable direct rendering"
 #define MSGTR_PREFERENCES_FrameDrop "Enable frame dropping"
 #define MSGTR_PREFERENCES_HFrameDrop "Enable HARD frame dropping (dangerous)"
diff -urN main/libvo/video_out.c main/libvo/video_out.c
--- main/libvo/video_out.c      2003-03-13 23:13:13.000000000 +0200
+++ main/libvo/video_out.c      2003-03-22 02:15:34.000000000 +0200
@@ -35,6 +35,7 @@
 
 int vo_grabpointer = 1;
 int vo_doublebuffering = 0;
+int vo_triplebuffering = 0;
 int vo_vsync = 0;
 int vo_fs = 0;
 int vo_fsmode = 0;
diff -urN main/libvo/video_out.h main/libvo/video_out.h
--- main/libvo/video_out.h      2003-03-13 23:13:13.000000000 +0200
+++ main/libvo/video_out.h      2003-03-22 02:17:27.000000000 +0200
@@ -189,6 +189,7 @@
 
 extern int vo_grabpointer;
 extern int vo_doublebuffering;
+extern int vo_triplebuffering;
 extern int vo_directrendering;
 extern int vo_vsync;
 extern int vo_fs;
diff -urN main/mencoder.c main/mencoder.c
--- main/mencoder.c     2003-03-19 18:32:22.000000000 +0200
+++ main/mencoder.c     2003-03-22 02:15:15.000000000 +0200
@@ -79,6 +79,7 @@
 #include "osdep/timer.h"
 
 int vo_doublebuffering=0;
+int vo_triplebuffering=0;
 int vo_directrendering=0;
 int vo_config_count=0;
 
diff -urN main/libvo/vo_dfbmga.c main/libvo/vo_dfbmga.c
--- main/libvo/vo_dfbmga.c      2003-02-19 18:01:46.000000000 +0200
+++ main/libvo/vo_dfbmga.c      2003-03-22 02:46:23.000000000 +0200
@@ -68,6 +68,7 @@
 static IDirectFBSurface *bufs[3];
 
 static IDirectFBSurface *frame;
+static IDirectFBSurface *besframe;
 static IDirectFBSurface *c2frame;
 static IDirectFBSurface *subframe;
 
@@ -79,9 +80,6 @@
 static IDirectFBInputDevice  *keyboard;
 static IDirectFBEventBuffer  *buffer;
 
-static unsigned int frame_pixel_size;
-static unsigned int subframe_pixel_size;
-
 static int inited = 0;
 
 static int blit_done;
@@ -96,11 +94,20 @@
 static int osd_changed;
 static int osd_dirty;
 static int osd_current;
+static int osd_max;
 
 /******************************
-*          vo_directfb       *
+*          vo_dfbmga         *
 ******************************/
 
+#if DIRECTFBVERSION < 917
+ #define DSPF_ALUT44 DSPF_LUT8
+#endif
+
+#if DIRECTFBVERSION < 916
+ #define DSPF_ARGB1555 DSPF_RGB15
+#endif
+
 /* command line/config file options */
 #ifdef HAVE_FBDEV
  extern char *fb_dev_name;
@@ -127,13 +134,8 @@
          return "RGB24";
      case DSPF_RGB16:
          return "RGB16";
-#if DIRECTFBVERSION > 915
      case DSPF_ARGB1555:
          return "ARGB1555";
-#else
-     case DSPF_RGB15:
-         return "RGB15";
-#endif
      case DSPF_YUY2:
          return "YUY2";
      case DSPF_UYVY:
@@ -142,8 +144,8 @@
          return "YV12";
      case DSPF_I420:
          return "I420";
-     case DSPF_LUT8:
-         return "LUT8";
+     case DSPF_ALUT44:
+         return "ALUT44";
      default:
          return "Unknown pixel format";
      }
@@ -164,11 +166,7 @@
          return DSPF_RGB16;
      case IMGFMT_RGB15:
      case IMGFMT_BGR15:
-#if DIRECTFBVERSION > 915
          return DSPF_ARGB1555;
-#else
-         return DSPF_RGB15;
-#endif
      case IMGFMT_YUY2:
          return DSPF_YUY2;
      case IMGFMT_UYVY:
@@ -219,13 +217,17 @@
 {
      DFBResult res;
 
+     bes = NULL;
+     crtc2 = NULL;
+
      /* Some defaults */
      use_bes = 0;
      use_crtc2 = 1;
      use_spic = 1;
-     use_input = 1;
      field_parity = -1;
 
+     use_input = getenv( "DISPLAY" ) ? 0 : 1;
+
      if (vo_subdevice) {
           int opt_no = 0;
           while (*vo_subdevice != '\0') {
@@ -242,7 +244,7 @@
                     vo_subdevice += 4;
                     opt_no = 0;
                } else if (!strncmp(vo_subdevice, "input", 5)) {
-                    use_spic = !opt_no;
+                    use_input = !opt_no;
                     vo_subdevice += 5;
                     opt_no = 0;
                } else if (!strncmp(vo_subdevice, "fieldparity=", 12)) {
@@ -354,6 +356,7 @@
      uint32_t out_width;
      uint32_t out_height;
 
+     besframe = NULL;
      c2frame = NULL;
      spic = NULL;
      subframe = NULL;
@@ -367,31 +370,7 @@
 
      dlc.pixelformat   = imgfmt_to_pixelformat( format );
 
-     if (use_bes) {
-          /* Draw to BES surface */
-          dlc.flags       = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | 
DLCONF_BUFFERMODE;
-          dlc.width       = in_width;
-          dlc.height      = in_height;
-          dlc.buffermode  = DLBM_BACKVIDEO;
-
-          if (bes->TestConfiguration( bes, &dlc, &failed ) != DFB_OK) {
-               mp_msg( MSGT_VO, MSGL_ERR,
-                       "vo_dfbmga: Invalid BES configuration!\n" );
-               return -1;
-          }
-          bes->SetConfiguration( bes, &dlc );
-          bes->GetSurface( bes, &frame );
-
-          aspect_save_screenres( 10000, 10000 );
-          aspect( &out_width, &out_height, A_ZOOM );
-          bes->SetScreenLocation( bes,
-                                  (1.0f - (float) out_width  / 10000.0f) / 2.0f,
-                                  (1.0f - (float) out_height / 10000.0f) / 2.0f,
-                                  (float) out_width  / 10000.0f,
-                                  (float) out_height / 10000.0f );
-          bufs[0] = frame;
-          num_bufs = 1;
-     } else {
+     {
           /* Draw to a temporary surface */
           DFBSurfaceDescription dsc;
 
@@ -401,6 +380,12 @@
           dsc.height      = in_height;
           dsc.pixelformat = dlc.pixelformat;
 
+          /* Don't waste video memory since we don't need stretchblit */
+          if (use_bes) {
+               dsc.flags |= DSDESC_CAPS;
+               dsc.caps   = DSCAPS_SYSTEMONLY;
+          }
+
           for (num_bufs = 0; num_bufs < 3; num_bufs++) {
                if ((res = dfb->CreateSurface( dfb, &dsc, &bufs[num_bufs] )) != 
DFB_OK) {
                     if (num_bufs == 0) {
@@ -409,20 +394,87 @@
                                  DirectFBErrorString( res ) );
                          return -1;
                     }
+                    break;
                }
           }
           frame = bufs[0];
           current_buf = 0;
           current_ip_buf = 0;
      }
+     frame->GetPixelFormat( frame, &frame_format );
+     mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Video surface %dx%d %s\n",
+             in_width, in_height,
+             pixelformat_name( frame_format ) );
+
+
+     /*
+      * BES
+      */
+     if (use_bes) {
+          dlc.flags       = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | 
DLCONF_BUFFERMODE;
+          dlc.width       = in_width;
+          dlc.height      = in_height;
+
+          if (use_crtc2) {
+               dlc.buffermode = DLBM_FRONTONLY;
+               osd_max = 1;
+          } else if (vo_triplebuffering) {
+               dlc.buffermode = DLBM_TRIPLE;
+               osd_max = 4;
+          } else if (vo_doublebuffering) {
+               dlc.buffermode = DLBM_BACKVIDEO;
+               osd_max = 2;
+          } else {
+               dlc.buffermode = DLBM_FRONTONLY;
+               osd_max = 1;
+          }
+
+          if (bes->TestConfiguration( bes, &dlc, &failed ) != DFB_OK) {
+               mp_msg( MSGT_VO, MSGL_ERR,
+                       "vo_dfbmga: Invalid BES configuration!\n" );
+               return -1;
+          }
+          bes->SetConfiguration( bes, &dlc );
+          bes->GetSurface( bes, &besframe );
+          besframe->SetBlittingFlags( besframe, DSBLIT_NOFX );
 
+          aspect_save_screenres( 10000, 10000 );
+          aspect( &out_width, &out_height, A_ZOOM );
+          bes->SetScreenLocation( bes,
+                                  (1.0f - (float) out_width  / 10000.0f) / 2.0f,
+                                  (1.0f - (float) out_height / 10000.0f) / 2.0f,
+                                  (float) out_width  / 10000.0f,
+                                  (float) out_height / 10000.0f );
+
+          besframe->Clear( besframe, 0, 0, 0, 0xff );
+          besframe->Flip( besframe, NULL, 0 );
+          besframe->Clear( besframe, 0, 0, 0, 0xff );
+          besframe->Flip( besframe, NULL, 0 );
+          besframe->Clear( besframe, 0, 0, 0, 0xff );
+
+          mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: BES surface %dx%d %s\n", dlc.width, 
dlc.height, pixelformat_name( dlc.pixelformat ) );
+     }
+
+     /*
+      * CRTC2
+      */
      if (use_crtc2) {
-          dlc.flags      = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
-          dlc.buffermode = DLBM_BACKVIDEO;
+          dlc.flags      = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS;
+
+          if (vo_triplebuffering) {
+               dlc.buffermode = DLBM_TRIPLE;
+               osd_max = 4;
+          } else if (vo_doublebuffering) {
+               dlc.buffermode = DLBM_BACKVIDEO;
+               osd_max = 2;
+          } else {
+               dlc.buffermode = DLBM_FRONTONLY;
+               osd_max = 1;
+          }
 
+          dlc.options = DLOP_FLICKER_FILTERING;
 #if DIRECTFBVERSION > 916
           if (field_parity != -1) {
-               dlc.flags   |= DLCONF_OPTIONS;
                dlc.options  = DLOP_FIELD_PARITY;
           }
 #endif
@@ -457,6 +509,7 @@
 #endif
 
           crtc2->GetSurface( crtc2, &c2frame );
+          c2frame->SetBlittingFlags( c2frame, DSBLIT_NOFX );
 
           c2frame->GetSize( c2frame, &screen_width, &screen_height );
 
@@ -489,21 +542,17 @@
           c2frame->Clear( c2frame, 0, 0, 0, 0xff );
           c2frame->Flip( c2frame, NULL, 0 );
           c2frame->Clear( c2frame, 0, 0, 0, 0xff );
+          c2frame->Flip( c2frame, NULL, 0 );
+          c2frame->Clear( c2frame, 0, 0, 0, 0xff );
 
           mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC2 surface %dx%d %s\n", 
dlc.width, dlc.height, pixelformat_name( dlc.pixelformat ) );
      } else {
-          screen_width  = in_width;
-          screen_height = in_height;
           use_spic      = 0;
      }
 
-     frame->GetPixelFormat( frame, &frame_format );
-     frame_pixel_size = DFB_BYTES_PER_PIXEL( frame_format );
-     mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Video surface %dx%d %s (%s)\n",
-             in_width, in_height,
-             pixelformat_name( frame_format ),
-             use_bes ? "BES" : "offscreen" );
-
+     /*
+      * Sub-picture
+      */
      if (use_spic) {
           /* Draw OSD to sub-picture surface */
           IDirectFBPalette *palette;
@@ -523,8 +572,19 @@
           spic->SetOpacity( spic, 0 );
 
           dlc.flags       = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
-          dlc.pixelformat = DSPF_LUT8;
-          dlc.buffermode  = DLBM_BACKVIDEO;
+          dlc.pixelformat = DSPF_ALUT44;
+
+          if (vo_triplebuffering) {
+               dlc.buffermode = DLBM_TRIPLE;
+               osd_max = 4;
+          } else if (vo_doublebuffering) {
+               dlc.buffermode = DLBM_BACKVIDEO;
+               osd_max = 2;
+          } else {
+               dlc.buffermode = DLBM_FRONTONLY;
+               osd_max = 1;
+          }
+
 #if DIRECTFBVERSION > 916
           dlc.flags      |= DLCONF_OPTIONS;
           dlc.options     = DLOP_ALPHACHANNEL;
@@ -548,20 +608,21 @@
           }
           palette->Release( palette );
 
-          subframe->Clear( subframe, 0, 0, 0, 0xff );
+          subframe->Clear( subframe, 0, 0, 0, 0 );
+          subframe->Flip( subframe, NULL, 0 );
+          subframe->Clear( subframe, 0, 0, 0, 0 );
           subframe->Flip( subframe, NULL, 0 );
-          subframe->Clear( subframe, 0, 0, 0, 0xff );
+          subframe->Clear( subframe, 0, 0, 0, 0 );
      } else if (use_crtc2) {
           /* Draw OSD to CRTC2 surface */
           subframe = c2frame;
      } else {
           /* Draw OSD to BES surface */
-          subframe = frame;
+          subframe = besframe;
      }
 
      subframe->GetSize( subframe, &sub_width, &sub_height );
      subframe->GetPixelFormat( subframe, &subframe_format );
-     subframe_pixel_size = DFB_BYTES_PER_PIXEL( subframe_format );
      mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Sub-picture surface %dx%d %s (%s)\n",
              sub_width, sub_height,
              pixelformat_name( subframe_format ),
@@ -610,12 +671,12 @@
 }
 
 static void
-vo_draw_alpha_lut8( int w, int h,
-                    unsigned char* src,
-                    unsigned char *srca,
-                    int srcstride,
-                    unsigned char* dst,
-                    int dststride )
+vo_draw_alpha_alut44( int w, int h,
+                      unsigned char* src,
+                      unsigned char *srca,
+                      int srcstride,
+                      unsigned char* dst,
+                      int dststride )
 {
      int x;
 
@@ -652,54 +713,50 @@
                osd_dirty |= osd_current;
      }
 
-     if (subframe->Lock( subframe, DSLF_WRITE, &dst, &pitch ) != DFB_OK)
+     if (subframe->Lock( subframe, DSLF_READ | DSLF_WRITE, &dst, &pitch ) != DFB_OK)
           return;
 
      switch (subframe_format) {
-     case DSPF_LUT8:
-          vo_draw_alpha_lut8( w, h, src, srca, stride,
-                              ((uint8_t *) dst) + pitch * y0 + subframe_pixel_size * 
x0,
-                              pitch );
+     case DSPF_ALUT44:
+          vo_draw_alpha_alut44( w, h, src, srca, stride,
+                                ((uint8_t *) dst) + pitch * y0 + x0,
+                                pitch );
           break;
      case DSPF_RGB32:
      case DSPF_ARGB:
          vo_draw_alpha_rgb32( w, h, src, srca, stride,
-                              (( uint8_t *) dst) + pitch * y0 + subframe_pixel_size * 
x0,
+                              (( uint8_t *) dst) + pitch * y0 + 4 * x0,
                                pitch );
          break;
      case DSPF_RGB24:
          vo_draw_alpha_rgb24( w, h, src, srca, stride,
-                              ((uint8_t *) dst) + pitch * y0 + subframe_pixel_size * 
x0,
+                              ((uint8_t *) dst) + pitch * y0 + 3 * x0,
                                pitch );
          break;
      case DSPF_RGB16:
          vo_draw_alpha_rgb16( w, h, src, srca, stride,
-                              ((uint8_t *) dst) + pitch * y0 + subframe_pixel_size * 
x0,
+                              ((uint8_t *) dst) + pitch * y0 + 2 * x0,
                                pitch );
          break;
-#if DIRECTFBVERSION > 915
      case DSPF_ARGB1555:
-#else
-     case DSPF_RGB15:
-#endif
          vo_draw_alpha_rgb15( w, h, src, srca, stride,
-                              ((uint8_t *) dst) + pitch * y0 + subframe_pixel_size * 
x0,
+                              ((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 + subframe_pixel_size * 
x0,
+                             ((uint8_t *) dst) + pitch * y0 + 2 * x0,
                               pitch );
          break;
      case DSPF_UYVY:
          vo_draw_alpha_yuy2( w, h, src, srca, stride,
-                             ((uint8_t *) dst) + pitch * y0 + subframe_pixel_size * 
x0 + 1,
+                             ((uint8_t *) dst) + pitch * y0 + 2 * x0 + 1,
                               pitch );
          break;
      case DSPF_I420:
      case DSPF_YV12:
          vo_draw_alpha_yv12( w, h, src, srca, stride,
-                             ((uint8_t *) dst) + pitch * y0 + subframe_pixel_size * 
x0,
+                             ((uint8_t *) dst) + pitch * y0 + x0,
                               pitch );
          break;
      default:
@@ -756,16 +813,26 @@
 static void
 blit_to_screen( void )
 {
-     /* Flip BES */
-     if (use_bes)
-          frame->Flip( frame, NULL, 0 );
+     IDirectFBSurface *blitsrc = frame;
+     int waitvsync = vo_vsync && !vo_doublebuffering && !vo_triplebuffering;
 
-     /* Blit from BES/temp to CRTC2 */
-     c2frame->SetBlittingFlags( c2frame, DSBLIT_NOFX );
-     if (stretch)
-          c2frame->StretchBlit( c2frame, frame, NULL, &drect );
-     else
-          c2frame->Blit( c2frame, frame, NULL, drect.x, drect.y );
+     if (use_bes) {
+          if (waitvsync && !use_crtc2)
+               bes->WaitForSync( bes );
+
+          besframe->Blit( besframe, blitsrc, NULL, 0, 0 );
+          blitsrc = besframe;
+     }
+
+     if (use_crtc2) {
+          if (waitvsync)
+               crtc2->WaitForSync( crtc2 );
+
+          if (stretch)
+               c2frame->StretchBlit( c2frame, blitsrc, NULL, &drect );
+          else
+               c2frame->Blit( c2frame, blitsrc, NULL, drect.x, drect.y );
+     }
 }
 
 static void
@@ -778,7 +845,7 @@
      
      if (osd_dirty & osd_current) {
           if (use_spic) {
-               subframe->Clear( subframe, 0, 0, 0, 0xff );
+               subframe->Clear( subframe, 0, 0, 0, 0 );
           } else if (use_crtc2) {
                /* Clear black bars around the picture */
                subframe->SetColor( subframe, 0, 0, 0, 0xff );
@@ -798,36 +865,39 @@
           osd_dirty &= ~osd_current;
      }
 
-     if (use_crtc2) {
-          blit_to_screen();
-          blit_done = 1;
-     }
+     blit_to_screen();
+     blit_done = 1;
 
      vo_draw_text( sub_width, sub_height, draw_alpha );
 
-     if (use_spic && osd_changed) {
+     if (use_spic && osd_changed &&
+         (vo_doublebuffering || vo_triplebuffering)) {
           subframe->Flip( subframe, NULL, 0 );
-          osd_current ^= 3;
+          osd_current <<= 1;
+          if (osd_current > osd_max)
+               osd_current = 1;
      }
 }
 
 static void
 flip_page( void )
 {
-     if (!use_crtc2) {
-          /* Flip BES */
-          frame->Flip( frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : 0 );
-     } else {
-          if (!blit_done)
-               blit_to_screen();
+     if (!blit_done)
+          blit_to_screen();
 
-          /* Flip CRTC2 */
-          c2frame->Flip( c2frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : 0 );
-          if (!use_spic)
-               osd_current ^= 3;
-          blit_done = 0;
+     if (vo_doublebuffering || vo_triplebuffering) {
+          if (use_crtc2)
+               c2frame->Flip( c2frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : 0 );
+          else
+               besframe->Flip( besframe, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : 0 );
+          if (!use_spic) {
+               osd_current <<= 1;
+               if (osd_current > osd_max)
+                    osd_current = 1;
+          }
      }
-
+     
+     blit_done = 0;
      current_buf = vo_directrendering ? 0 : (current_buf + 1) % num_bufs;
 }
 
@@ -845,18 +915,23 @@
                frame->Release( frame );
           bufs[num_bufs] = NULL;
      }
-     if (use_bes) {
+     if (bes) {
+          if (besframe)
+               besframe->Release( besframe );
           bes->SetOpacity( bes, 0 );
           bes->Release( bes );
+          besframe = NULL;
+          bes = NULL;
      }
-     if (use_crtc2) {
+     if (crtc2) {
           if (c2frame)
                c2frame->Release( c2frame );
           crtc2->SetOpacity( crtc2, 0 );
           crtc2->Release( crtc2 );
           c2frame = NULL;
+          crtc2 = NULL;
      }
-     if (use_spic && spic) {
+     if (spic) {
           if (subframe)
                subframe->Release( subframe );
           spic->SetOpacity( spic, 0 );

Reply via email to