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 );