]> git.sesse.net Git - vlc/blobdiff - plugins/directx/vout_directx.c
improved title and chapter navigation in BeOS GUI, added LCD type info view displayin...
[vlc] / plugins / directx / vout_directx.c
index 8f12e21814fe60518653b86d7c9ba4761cccbacb..5dfd71a4b81614f07107b430effa4749b5646b1d 100644 (file)
@@ -2,7 +2,7 @@
  * vout_directx.c: Windows DirectX video output display method
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: vout_directx.c,v 1.23 2002/02/24 20:51:09 gbazin Exp $
+ * $Id: vout_directx.c,v 1.36.2.2 2002/10/03 16:44:41 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
  *
  * If YUV overlay is not supported this plugin will use RGB offscreen video
  * surfaces that will be blitted onto the primary surface (display) to
- * effectively display the pictures. this fallback method enables us to display
- * video in window mode.
- * Another fallback method (which isn't implemented) would be take the
- * exclusive control of the screen so we could spare the blitting process and
- * decode directly to video memory. This should theoretically allow for better
- * performance (although on my system it is actually slower) but this is
- * restricted to fullscreen video.
+ * effectively display the pictures. This fallback method also enables us to
+ * display video in window mode.
  * 
  *****************************************************************************/
 #include <errno.h>                                                 /* ENOMEM */
@@ -63,7 +58,7 @@
  *****************************************************************************/
 #include <initguid.h>
 DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
-DEFINE_GUID( IID_IDirectDrawSurface3, 0xDA044E00,0x69B2,0x11D0,0xA1,0xD5,0x00,0xAA,0x00,0xB8,0xDF,0xBB );
+DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );
 
 /*****************************************************************************
  * Local prototypes.
@@ -85,9 +80,9 @@ static void DirectXCloseDDraw     ( vout_thread_t *p_vout );
 static int  DirectXCreateDisplay  ( vout_thread_t *p_vout );
 static void DirectXCloseDisplay   ( vout_thread_t *p_vout );
 static int  DirectXCreateSurface  ( vout_thread_t *p_vout,
-                                    LPDIRECTDRAWSURFACE3 *, int, int );
+                                    LPDIRECTDRAWSURFACE2 *, int, int, int );
 static void DirectXCloseSurface   ( vout_thread_t *p_vout,
-                                    LPDIRECTDRAWSURFACE3 );
+                                    LPDIRECTDRAWSURFACE2 );
 static int  DirectXCreateClipper  ( vout_thread_t *p_vout );
 static void DirectXGetDDrawCaps   ( vout_thread_t *p_vout );
 static int  DirectXGetSurfaceDesc ( picture_t *p_pic );
@@ -119,7 +114,7 @@ static int vout_Create( vout_thread_t *p_vout )
     if( p_vout->p_sys == NULL )
     {
         intf_ErrMsg( "vout error: can't create p_sys (%s)", strerror(ENOMEM) );
-        return( 1 );
+        return 1;
     }
 
     /* Initialisations */
@@ -133,33 +128,16 @@ static int vout_Create( vout_thread_t *p_vout )
     p_vout->p_sys->b_event_thread_die = 0;
     p_vout->p_sys->b_caps_overlay_clipping = 0;
     SetRectEmpty( &p_vout->p_sys->rect_display );
-    p_vout->p_sys->b_using_overlay =
-        !config_GetIntVariable( VOUT_NOOVERLAY_VAR );
+    p_vout->p_sys->b_using_overlay = config_GetIntVariable( "overlay" );
+    p_vout->p_sys->b_use_sysmem = config_GetIntVariable( "directx-use-sysmem");
+    p_vout->p_sys->b_hw_yuv = config_GetIntVariable( "directx-hw-yuv" );
 
-    p_vout->p_sys->b_cursor = 1;
-
-    p_vout->p_sys->b_cursor_autohidden = 0;
+    p_vout->p_sys->b_cursor_hidden = 0;
     p_vout->p_sys->i_lastmoved = mdate();
 
     /* Set main window's size */
-    if( p_vout->render.i_height * p_vout->render.i_aspect
-        >= p_vout->render.i_width * VOUT_ASPECT_FACTOR )
-    {
-        p_vout->p_sys->i_window_width = p_vout->render.i_height
-          * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
-        p_vout->p_sys->i_window_height = p_vout->render.i_height;
-    }
-    else
-    {
-        p_vout->p_sys->i_window_width = p_vout->render.i_width;
-        p_vout->p_sys->i_window_height = p_vout->render.i_width
-          * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
-    }
-
-#if 0
-    p_vout->p_sys->i_window_width = config_GetIntVariable( VOUT_WIDTH_VAR );
-    p_vout->p_sys->i_window_height = config_GetIntVariable( VOUT_HEIGHT_VAR );
-#endif
+    p_vout->p_sys->i_window_width = p_vout->i_window_width;
+    p_vout->p_sys->i_window_height = p_vout->i_window_height;
 
     /* Set locks and condition variables */
     vlc_mutex_init( &p_vout->p_sys->event_thread_lock );
@@ -180,67 +158,44 @@ static int vout_Create( vout_thread_t *p_vout )
     {
         intf_ErrMsg( "vout error: can't create DirectXEventThread" );
         intf_ErrMsg("vout error: %s", strerror(ENOMEM));
-        free( p_vout->p_sys );
-        return( 1 );
+        goto error;
     }
 
     /* We need to wait for the actual creation of the thread and window */
+    vlc_mutex_lock( &p_vout->p_sys->event_thread_lock );
     if( p_vout->p_sys->i_event_thread_status == THREAD_CREATE )
     {
-        vlc_mutex_lock( &p_vout->p_sys->event_thread_lock );
         vlc_cond_wait ( &p_vout->p_sys->event_thread_wait,
                         &p_vout->p_sys->event_thread_lock );
-        vlc_mutex_unlock( &p_vout->p_sys->event_thread_lock );
     }
+    vlc_mutex_unlock( &p_vout->p_sys->event_thread_lock );
     if( p_vout->p_sys->i_event_thread_status != THREAD_READY )
     {
         intf_ErrMsg( "vout error: DirectXEventThread failed" );
-        free( p_vout->p_sys );
-        return( 1 );
+        goto error;
     }
 
     intf_WarnMsg( 3, "vout: vout_Create DirectXEventThread running" );
 
-
     /* Initialise DirectDraw */
     if( DirectXInitDDraw( p_vout ) )
     {
         intf_ErrMsg( "vout error: can't initialise DirectDraw" );
-
-        /* Kill DirectXEventThread */
-        p_vout->p_sys->b_event_thread_die = 1;
-        /* we need to be sure DirectXEventThread won't stay stuck in
-         * GetMessage, so we send a fake message */
-        PostMessage( p_vout->p_sys->hwnd, WM_CHAR, (WPARAM)'^', 0);
-        vlc_thread_join( p_vout->p_sys->event_thread_id );
-
-        return ( 1 );
+        goto error;
     }
 
     /* Create the directx display */
     if( DirectXCreateDisplay( p_vout ) )
     {
         intf_ErrMsg( "vout error: can't initialise DirectDraw" );
-        DirectXCloseDDraw( p_vout );
-
-        /* Kill DirectXEventThread */
-        p_vout->p_sys->b_event_thread_die = 1;
-        /* we need to be sure DirectXEventThread won't stay stuck in
-         * GetMessage, so we send a fake message */
-        PostMessage( p_vout->p_sys->hwnd, WM_CHAR, (WPARAM)'^', 0);
-        vlc_thread_join( p_vout->p_sys->event_thread_id );
-
-        return ( 1 );
+        goto error;
     }
 
-    /* Attach the current thread input queue to the events thread qeue.
-     * This allows us to hide or show the cursor in vout_Manage() */
-    ShowCursor( TRUE ); ShowCursor( FALSE );           /* create input queue */
-    AttachThreadInput( GetCurrentThreadId(),
-                       GetWindowThreadProcessId( p_vout->p_sys->hwnd, NULL ),
-                       1 );
+    return 0;
 
-    return( 0 );
+ error:
+    vout_Destroy( p_vout );
+    return 1;
 }
 
 /*****************************************************************************
@@ -251,6 +206,7 @@ static int vout_Create( vout_thread_t *p_vout )
  *****************************************************************************/
 static int vout_Init( vout_thread_t *p_vout )
 {
+    int i_chroma_backup;
 
     /* Initialize the output structure.
      * Since DirectDraw can do rescaling for us, stick to the default
@@ -260,15 +216,66 @@ static int vout_Init( vout_thread_t *p_vout )
     p_vout->output.i_aspect = p_vout->render.i_aspect;
 
 #define MAX_DIRECTBUFFERS 1
+    /* Right now we use only 1 directbuffer because we don't want the
+     * video decoder to decode directly into direct buffers as they are
+     * created into video memory and video memory is _really_ slow */
+
+    /* Choose the chroma we will try first. */
+    switch( p_vout->render.i_chroma )
+    {
+        case FOURCC_YUY2:
+        case FOURCC_YUNV:
+            p_vout->output.i_chroma = FOURCC_YUY2;
+            break;
+        case FOURCC_UYVY:
+        case FOURCC_UYNV:
+        case FOURCC_Y422:
+            p_vout->output.i_chroma = FOURCC_UYVY;
+            break;
+        case FOURCC_YVYU:
+            p_vout->output.i_chroma = FOURCC_YVYU;
+            break;
+        default:
+            p_vout->output.i_chroma = FOURCC_YV12;
+            break;
+    }
 
     NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
 
+    i_chroma_backup = p_vout->output.i_chroma;
+
+    if( !I_OUTPUTPICTURES )
+    {
+        /* hmmm, it didn't work! Let's try commonly supported chromas */
+        p_vout->output.i_chroma = FOURCC_YV12;
+        NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
+        if( !I_OUTPUTPICTURES )
+        {
+            /* hmmm, it didn't work! Let's try commonly supported chromas */
+            p_vout->output.i_chroma = FOURCC_YUY2;
+            NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
+        }
+    }
+
+    if( !I_OUTPUTPICTURES )
+    {
+        /* If it still didn't work then don't try to use an overlay */
+        p_vout->output.i_chroma = i_chroma_backup;
+        p_vout->p_sys->b_using_overlay = 0;
+        NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
+    }
+
     /* Change the window title bar text */
     if( p_vout->p_sys->b_using_overlay )
         SetWindowText( p_vout->p_sys->hwnd,
-                       "VLC DirectX (using hardware overlay)" );
+                       VOUT_TITLE " (hardware YUV overlay DirectX output)" );
+    else if( p_vout->p_sys->b_hw_yuv )
+        SetWindowText( p_vout->p_sys->hwnd,
+                       VOUT_TITLE " (hardware YUV DirectX output)" );
+    else SetWindowText( p_vout->p_sys->hwnd,
+                        VOUT_TITLE " (software RGB DirectX output)" );
 
-    return( 0 );
+    return 0;
 }
 
 /*****************************************************************************
@@ -291,19 +298,26 @@ static void vout_End( vout_thread_t *p_vout )
 static void vout_Destroy( vout_thread_t *p_vout )
 {
     intf_WarnMsg( 3, "vout: vout_Destroy" );
+
     DirectXCloseDisplay( p_vout );
     DirectXCloseDDraw( p_vout );
 
     /* Kill DirectXEventThread */
+    vlc_mutex_lock( &p_vout->p_sys->event_thread_lock );
     p_vout->p_sys->b_event_thread_die = 1;
-    /* we need to be sure DirectXEventThread won't stay stuck in GetMessage,
-     * so we send a fake message */
-    if( p_vout->p_sys->i_event_thread_status == THREAD_READY &&
-        p_vout->p_sys->hwnd )
+
+    if( p_vout->p_sys->i_event_thread_status == THREAD_READY )
     {
-        PostMessage( p_vout->p_sys->hwnd, WM_CHAR, (WPARAM)'q', 0);
+        /* we need to be sure DirectXEventThread won't stay stuck in
+         * GetMessage, so we send a fake message */
+        if( p_vout->p_sys->hwnd )
+            PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);
+
+        vlc_mutex_unlock( &p_vout->p_sys->event_thread_lock );
         vlc_thread_join( p_vout->p_sys->event_thread_id );
     }
+    else
+        vlc_mutex_unlock( &p_vout->p_sys->event_thread_lock );
 
     if( p_vout->p_sys != NULL )
     {
@@ -394,33 +408,19 @@ static int vout_Manage( vout_thread_t *p_vout )
     /*
      * Pointer change
      */
-    if( ! p_vout->p_sys->b_cursor_autohidden &&
-        ( mdate() - p_vout->p_sys->i_lastmoved > 5000000 ) )
+    if( (!p_vout->p_sys->b_cursor_hidden) &&
+        ( (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 ) )
     {
         /* Hide the mouse automatically */
-        p_vout->p_sys->b_cursor_autohidden = 1;
-        ShowCursor( FALSE );
-    }
-
-#if 0
-    if( p_vout->i_changes & VOUT_CURSOR_CHANGE
-        || p_vout->p_sys->i_changes & VOUT_CURSOR_CHANGE )
-    {
-        p_vout->p_sys->b_cursor = ! p_vout->p_sys->b_cursor;
-
-        ShowCursor( p_vout->p_sys->b_cursor &&
-                     ! p_vout->p_sys->b_cursor_autohidden );
-
-        p_vout->i_changes &= ~VOUT_CURSOR_CHANGE;
-        p_vout->p_sys->i_changes &= ~VOUT_CURSOR_CHANGE;
+        p_vout->p_sys->b_cursor_hidden = 1;
+        PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
     }
-#endif
 
     /* Check if the event thread is still running */
     if( p_vout->p_sys->b_event_thread_die )
         return 1; /* exit */
 
-    return( 0 );
+    return 0;
 }
 
 /*****************************************************************************
@@ -454,26 +454,26 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
         /* We ask for the "NOTEARING" option */
         memset( &ddbltfx, 0, sizeof(DDBLTFX) );
         ddbltfx.dwSize = sizeof(DDBLTFX);
-        ddbltfx.dwDDFX = DDBLTFX_NOTEARING | DDBLT_ASYNC;
+        ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
 
         /* Blit video surface to display */
-        dxresult = IDirectDrawSurface3_Blt(p_vout->p_sys->p_display,
+        dxresult = IDirectDrawSurface2_Blt(p_vout->p_sys->p_display,
                                            &p_vout->p_sys->rect_dest_clipped,
                                            p_pic->p_sys->p_surface,
                                            &p_vout->p_sys->rect_src_clipped,
-                                           0, &ddbltfx );
+                                           DDBLT_ASYNC, &ddbltfx );
         if ( dxresult == DDERR_SURFACELOST )
         {
             /* Our surface can be lost so be sure
              * to check this and restore it if needed */
-            IDirectDrawSurface3_Restore( p_vout->p_sys->p_display );
+            IDirectDrawSurface2_Restore( p_vout->p_sys->p_display );
 
             /* Now that the surface has been restored try to display again */
-            dxresult = IDirectDrawSurface3_Blt(p_vout->p_sys->p_display,
+            dxresult = IDirectDrawSurface2_Blt(p_vout->p_sys->p_display,
                                            &p_vout->p_sys->rect_dest_clipped,
                                            p_pic->p_sys->p_surface,
                                            &p_vout->p_sys->rect_src_clipped,
-                                           0, &ddbltfx );
+                                           DDBLT_ASYNC, &ddbltfx );
         }
 
         if( dxresult != DD_OK )
@@ -486,18 +486,21 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
     else /* using overlay */
     {
 
-        /* Flip the overlay buffers */
-        dxresult = IDirectDrawSurface3_Flip( p_pic->p_sys->p_front_surface,
+        /* Flip the overlay buffers if we are using back buffers */
+        if( p_pic->p_sys->p_front_surface == p_pic->p_sys->p_surface )
+            return;
+
+        dxresult = IDirectDrawSurface2_Flip( p_pic->p_sys->p_front_surface,
                                              NULL, DDFLIP_WAIT );
         if ( dxresult == DDERR_SURFACELOST )
         {
             /* Our surface can be lost so be sure
              * to check this and restore it if needed */
-            IDirectDrawSurface3_Restore( p_vout->p_sys->p_display );
-            IDirectDrawSurface3_Restore( p_pic->p_sys->p_front_surface );
+            IDirectDrawSurface2_Restore( p_vout->p_sys->p_display );
+            IDirectDrawSurface2_Restore( p_pic->p_sys->p_front_surface );
 
             /* Now that the surface has been restored try to display again */
-            dxresult = IDirectDrawSurface3_Flip( p_pic->p_sys->p_front_surface,
+            dxresult = IDirectDrawSurface2_Flip( p_pic->p_sys->p_front_surface,
                                                  NULL, DDFLIP_WAIT );
             DirectXUpdateOverlay( p_vout );
         }
@@ -505,6 +508,7 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
         if( dxresult != DD_OK )
             intf_WarnMsg( 8, "vout: couldn't flip overlay surface" );
 
+
         if( !DirectXGetSurfaceDesc( p_pic ) )
         {
             /* AAARRGG */
@@ -546,7 +550,7 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
     if( p_vout->p_sys->hddraw_dll == NULL )
     {
         intf_WarnMsg( 3, "vout: DirectXInitDDraw failed loading ddraw.dll" );
-        return( 1 );
+        goto error;
     }
       
     OurDirectDrawCreate = 
@@ -554,9 +558,7 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
     if ( OurDirectDrawCreate == NULL )
     {
         intf_ErrMsg( "vout error: DirectXInitDDraw failed GetProcAddress" );
-        FreeLibrary( p_vout->p_sys->hddraw_dll );
-        p_vout->p_sys->hddraw_dll = NULL;
-        return( 1 );    
+        goto error;
     }
 
     /* Initialize DirectDraw now */
@@ -564,49 +566,44 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
     if( dxresult != DD_OK )
     {
         intf_ErrMsg( "vout error: DirectXInitDDraw can't initialize DDraw" );
-        p_vout->p_sys->p_ddobject = NULL;
-        FreeLibrary( p_vout->p_sys->hddraw_dll );
-        p_vout->p_sys->hddraw_dll = NULL;
-        return( 1 );
-    }
-
-    /* Set DirectDraw Cooperative level, ie what control we want over Windows
-     * display */
-    dxresult = IDirectDraw_SetCooperativeLevel( p_ddobject,
-                                           p_vout->p_sys->hwnd, DDSCL_NORMAL );
-    if( dxresult != DD_OK )
-    {
-        intf_ErrMsg( "vout error: can't set direct draw cooperative level." );
-        IDirectDraw_Release( p_ddobject );
-        p_vout->p_sys->p_ddobject = NULL;
-        FreeLibrary( p_vout->p_sys->hddraw_dll );
-        p_vout->p_sys->hddraw_dll = NULL;
-        return( 1 );
+        goto error;
     }
 
     /* Get the IDirectDraw2 interface */
     dxresult = IDirectDraw_QueryInterface( p_ddobject, &IID_IDirectDraw2,
                                         (LPVOID *)&p_vout->p_sys->p_ddobject );
+    /* Release the unused interface */
+    IDirectDraw_Release( p_ddobject );
     if( dxresult != DD_OK )
     {
         intf_ErrMsg( "vout error: can't get IDirectDraw2 interface." );
-        IDirectDraw_Release( p_ddobject );
-        p_vout->p_sys->p_ddobject = NULL;
-        FreeLibrary( p_vout->p_sys->hddraw_dll );
-        p_vout->p_sys->hddraw_dll = NULL;
-        return( 1 );
+        goto error;
     }
-    else
+
+    /* Set DirectDraw Cooperative level, ie what control we want over Windows
+     * display */
+    dxresult = IDirectDraw2_SetCooperativeLevel( p_vout->p_sys->p_ddobject,
+                                           p_vout->p_sys->hwnd, DDSCL_NORMAL );
+    if( dxresult != DD_OK )
     {
-        /* Release the unused interface */
-        IDirectDraw_Release( p_ddobject );
+        intf_ErrMsg( "vout error: can't set direct draw cooperative level." );
+        goto error;
     }
 
     /* Probe the capabilities of the hardware */
     DirectXGetDDrawCaps( p_vout );
 
     intf_WarnMsg( 3, "vout: End DirectXInitDDraw" );
-    return( 0 );
+    return 0;
+
+ error:
+    if( p_vout->p_sys->p_ddobject )
+        IDirectDraw2_Release( p_vout->p_sys->p_ddobject );
+    if( p_vout->p_sys->hddraw_dll )
+        FreeLibrary( p_vout->p_sys->hddraw_dll );
+    p_vout->p_sys->hddraw_dll = NULL;
+    p_vout->p_sys->p_ddobject = NULL;
+    return 1;
 }
 
 /*****************************************************************************
@@ -637,26 +634,19 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
     if( dxresult != DD_OK )
     {
         intf_ErrMsg( "vout error: can't get direct draw primary surface." );
-        p_vout->p_sys->p_display = NULL;
-        return( 1 );
+        return 1;
     }
 
     dxresult = IDirectDrawSurface_QueryInterface( p_display,
-                                         &IID_IDirectDrawSurface3,
+                                         &IID_IDirectDrawSurface2,
                                          (LPVOID *)&p_vout->p_sys->p_display );
+    /* Release the old interface */
+    IDirectDrawSurface_Release( p_display );
     if ( dxresult != DD_OK )
     {
-        intf_ErrMsg( "vout error: can't get IDirectDrawSurface3 interface." );
-        IDirectDrawSurface_Release( p_display );
-        p_vout->p_sys->p_display = NULL;
-        return( 1 );
+        intf_ErrMsg( "vout error: can't get IDirectDrawSurface2 interface." );
+        return 1;
     }
-    else
-    {
-        /* Release the old interface */
-        IDirectDrawSurface_Release( p_display );
-    }
-
 
     /* The clipper will be used only in non-overlay mode */
     DirectXCreateClipper( p_vout );
@@ -666,7 +656,7 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
     /* compute the colorkey pixel value from the RGB value we've got */
     memset( &pixel_format, 0, sizeof( DDPIXELFORMAT ));
     pixel_format.dwSize = sizeof( DDPIXELFORMAT );
-    dxresult = IDirectDrawSurface3_GetPixelFormat( p_vout->p_sys->p_display,
+    dxresult = IDirectDrawSurface2_GetPixelFormat( p_vout->p_sys->p_display,
                                                    &pixel_format );
     if( dxresult != DD_OK )
         intf_WarnMsg( 3, "vout: DirectXUpdateOverlay GetPixelFormat failed" );
@@ -675,7 +665,7 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
                                         & pixel_format.dwRBitMask);
 #endif
 
-    return( 0 );
+    return 0;
 }
 
 
@@ -699,8 +689,7 @@ static int DirectXCreateClipper( vout_thread_t *p_vout )
     if( dxresult != DD_OK )
     {
         intf_WarnMsg( 3, "vout: DirectXCreateClipper can't create clipper." );
-        p_vout->p_sys->p_clipper = NULL;
-        return( 1 );
+        goto error;
     }
 
     /* associate the clipper to the window */
@@ -710,9 +699,7 @@ static int DirectXCreateClipper( vout_thread_t *p_vout )
     {
         intf_WarnMsg( 3,
             "vout: DirectXCreateClipper can't attach clipper to window." );
-        IDirectDrawSurface_Release( p_vout->p_sys->p_clipper );
-        p_vout->p_sys->p_clipper = NULL;
-        return( 1 );
+        goto error;
     }
 
     /* associate the clipper with the surface */
@@ -722,12 +709,16 @@ static int DirectXCreateClipper( vout_thread_t *p_vout )
     {
         intf_WarnMsg( 3,
             "vout: DirectXCreateClipper can't attach clipper to surface." );
-        IDirectDrawSurface_Release( p_vout->p_sys->p_clipper );
-        p_vout->p_sys->p_clipper = NULL;
-        return( 1 );
+        goto error;
     }    
 
-    return( 0 );
+    return 0;
+
+ error:
+    if( p_vout->p_sys->p_clipper )
+        IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
+    p_vout->p_sys->p_clipper = NULL;
+    return 1;
 }
 
 /*****************************************************************************
@@ -741,15 +732,14 @@ static int DirectXCreateClipper( vout_thread_t *p_vout )
  * need to do any blitting to the main display...)
  *****************************************************************************/
 static int DirectXCreateSurface( vout_thread_t *p_vout,
-                                 LPDIRECTDRAWSURFACE3 *pp_surface_final,
-                                 int i_chroma, int b_overlay )
+                                 LPDIRECTDRAWSURFACE2 *pp_surface_final,
+                                 int i_chroma, int b_overlay,
+                                 int i_backbuffers )
 {
     HRESULT dxresult;
     LPDIRECTDRAWSURFACE p_surface;
     DDSURFACEDESC ddsd;
 
-    intf_WarnMsg( 3, "vout: DirectXCreateSurface" );
-
     /* Create the video surface */
     if( b_overlay )
     {
@@ -769,26 +759,21 @@ static int DirectXCreateSurface( vout_thread_t *p_vout,
         ddsd.dwFlags = DDSD_CAPS |
                        DDSD_HEIGHT |
                        DDSD_WIDTH |
-                       DDSD_BACKBUFFERCOUNT |
                        DDSD_PIXELFORMAT;
+        ddsd.dwFlags |= (i_backbuffers ? DDSD_BACKBUFFERCOUNT : 0);
         ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY |
-                              DDSCAPS_COMPLEX |
-                              DDSCAPS_FLIP |
                               DDSCAPS_VIDEOMEMORY;
+        ddsd.ddsCaps.dwCaps |= (i_backbuffers ? DDSCAPS_COMPLEX | DDSCAPS_FLIP
+                                : 0 );
         ddsd.dwHeight = p_vout->render.i_height;
         ddsd.dwWidth = p_vout->render.i_width;
-        ddsd.dwBackBufferCount = 1;                       /* One back buffer */
+        ddsd.dwBackBufferCount = i_backbuffers;
 
         dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
                                                &ddsd,
                                                &p_surface, NULL );
-        if( dxresult == DD_OK )
-        {
-            intf_WarnMsg( 3,"vout: DirectX YUV overlay created successfully" );
-        }
-        else
+        if( dxresult != DD_OK )
         {
-            intf_ErrMsg( "vout error: can't create YUV overlay surface." );
             *pp_surface_final = NULL;
             return 0;
         }
@@ -796,40 +781,50 @@ static int DirectXCreateSurface( vout_thread_t *p_vout,
 
     if( !b_overlay )
     {
-        /* Now try to create a plain RGB surface. */
+        boolean_t b_rgb_surface = ( i_chroma == FOURCC_RGB2 ) ||
+            ( i_chroma == FOURCC_RV15 ) || ( i_chroma == FOURCC_RV16 ) ||
+            ( i_chroma == FOURCC_RV24 ) || ( i_chroma == FOURCC_RV32 );
+
         memset( &ddsd, 0, sizeof( DDSURFACEDESC ) );
         ddsd.dwSize = sizeof(DDSURFACEDESC);
+        ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
         ddsd.dwFlags = DDSD_HEIGHT |
                        DDSD_WIDTH |
                        DDSD_CAPS;
-        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
-                              DDSCAPS_SYSTEMMEMORY;
+        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
         ddsd.dwHeight = p_vout->render.i_height;
         ddsd.dwWidth = p_vout->render.i_width;
 
+        if( p_vout->p_sys->b_use_sysmem )
+            ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
+        else
+            ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
+
+        if( !b_rgb_surface )
+        {
+            ddsd.dwFlags |= DDSD_PIXELFORMAT;
+            ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
+            ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
+        }
+
         dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
                                                &ddsd,
                                                &p_surface, NULL );
-        if( dxresult == DD_OK )
-        {
-            intf_WarnMsg( 3,"vout: DirectX RGB surface created successfully" );
-        }
-        else
+        if( dxresult != DD_OK )
         {
-            intf_ErrMsg( "vout error: can't create RGB surface." );
             *pp_surface_final = NULL;
             return 0;
         }
     }
-      
+
     /* Now that the surface is created, try to get a newer DirectX interface */
     dxresult = IDirectDrawSurface_QueryInterface( p_surface,
-                                     &IID_IDirectDrawSurface3,
+                                     &IID_IDirectDrawSurface2,
                                      (LPVOID *)pp_surface_final );
     IDirectDrawSurface_Release( p_surface );    /* Release the old interface */
     if ( dxresult != DD_OK )
     {
-        intf_ErrMsg( "vout error: can't get IDirectDrawSurface3 interface." );
+        intf_ErrMsg( "vout error: can't get IDirectDrawSurface2 interface." );
         *pp_surface_final = NULL;
         return 0;
     }
@@ -837,7 +832,6 @@ static int DirectXCreateSurface( vout_thread_t *p_vout,
     return 1;
 }
 
-
 /*****************************************************************************
  * DirectXUpdateOverlay: Move or resize overlay surface on video display.
  *****************************************************************************
@@ -853,10 +847,7 @@ void DirectXUpdateOverlay( vout_thread_t *p_vout )
 
     if( p_vout->p_sys->p_current_surface == NULL ||
         !p_vout->p_sys->b_using_overlay )
-    {
-        intf_WarnMsg( 5, "vout: DirectXUpdateOverlay no overlay !!" );
         return;
-    }
 
     /* The new window dimensions should already have been computed by the
      * caller of this function */
@@ -871,7 +862,7 @@ void DirectXUpdateOverlay( vout_thread_t *p_vout )
     if( !p_vout->p_sys->b_caps_overlay_clipping )
         dwFlags |= DDOVER_KEYDESTOVERRIDE;
 
-    dxresult = IDirectDrawSurface3_UpdateOverlay(
+    dxresult = IDirectDrawSurface2_UpdateOverlay(
                                          p_vout->p_sys->p_current_surface,
                                          &p_vout->p_sys->rect_src_clipped,
                                          p_vout->p_sys->p_display,
@@ -919,14 +910,14 @@ static void DirectXCloseDisplay( vout_thread_t *p_vout )
     if( p_vout->p_sys->p_clipper != NULL )
     {
         intf_WarnMsg( 3, "vout: DirectXCloseDisplay clipper" );
-        IDirectDraw2_Release( p_vout->p_sys->p_clipper );
+        IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
         p_vout->p_sys->p_clipper = NULL;
     }
 
     if( p_vout->p_sys->p_display != NULL )
     {
         intf_WarnMsg( 3, "vout: DirectXCloseDisplay display" );
-        IDirectDraw2_Release( p_vout->p_sys->p_display );
+        IDirectDrawSurface2_Release( p_vout->p_sys->p_display );
         p_vout->p_sys->p_display = NULL;
     }
 }
@@ -937,12 +928,12 @@ static void DirectXCloseDisplay( vout_thread_t *p_vout )
  * This function returns all resources allocated for the surface.
  *****************************************************************************/
 static void DirectXCloseSurface( vout_thread_t *p_vout,
-                                 LPDIRECTDRAWSURFACE3 p_surface )
+                                 LPDIRECTDRAWSURFACE2 p_surface )
 {
     intf_WarnMsg( 3, "vout: DirectXCloseSurface" );
     if( p_surface != NULL )
     {
-        IDirectDraw2_Release( p_surface );
+        IDirectDrawSurface2_Release( p_surface );
     }
 }
 
@@ -955,56 +946,43 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic,
                           int i_num_pics )
 {
     int i;
-    LPDIRECTDRAWSURFACE3 p_surface;
-
-#if 0
-    /* We couldn't use an YUV overlay so we need to indicate to video_output
-     * which format we are falling back to */
-    switch( )
-    {
-        case 8: /* FIXME: set the palette */
-            p_vout->output.i_chroma = FOURCC_BI_RGB; break;
-        case 15:
-            p_vout->output.i_chroma = FOURCC_RV15; break;
-        case 16:
-            p_vout->output.i_chroma = FOURCC_RV16; break;
-        case 24:
-            p_vout->output.i_chroma = FOURCC_BI_BITFIELDS; break;
-        case 32:
-            p_vout->output.i_chroma = FOURCC_BI_BITFIELDS; break;
-        default:
-            intf_ErrMsg( "vout error: unknown screen depth" );
-            return( 0 );
-    }
-#endif
+    boolean_t b_result_ok;
+    LPDIRECTDRAWSURFACE2 p_surface;
 
     intf_WarnMsg( 3, "vout: NewPictureVec" );
 
     I_OUTPUTPICTURES = 0;
 
-    /* chroma asked for */
-    p_vout->output.i_chroma = p_vout->render.i_chroma;
-
-    /* hack */
-#if 1
-    if( p_vout->render.i_chroma == FOURCC_I420 )
-        p_vout->output.i_chroma = FOURCC_YV12;
-#endif
-
-    /* First we try to create an overlay surface.
-     * It looks like with most hardware it's not possible to create several
-     * overlay surfaces, and even if it was I bet it would be slower anyway to
-     * use them as direct buffers because they usually reside in video memory
-     * which is quite slow.
-     * So the overlay surface (with a back-buffer) that we create won't be used
-     * to decode directly into it but instead picture buffers in system memory
-     * will be blitted to it. */
+    /* First we try to use an YUV overlay surface.
+     * The overlay surface that we create won't be used to decode directly
+     * into it because accessing video memory directly is way to slow (remember
+     * that pictures are decoded macroblock per macroblock). Instead the video
+     * will be decoded in picture buffers in system memory which will then be
+     * memcpy() to the overlay surface. */
     if( p_vout->p_sys->b_using_overlay )
     {
-        if( DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma,
-                                  p_vout->p_sys->b_using_overlay ) )
+        /* Triple buffering rocks! it doesn't have any processing overhead
+         * (you don't have to wait for the vsync) and provides for a very nice
+         * video quality (no tearing). */
+
+        b_result_ok = DirectXCreateSurface( p_vout, &p_surface,
+                                            p_vout->output.i_chroma,
+                                            p_vout->p_sys->b_using_overlay,
+                                            2 /* number of backbuffers */ );
+
+        if( !b_result_ok )
+            /* Try to reduce the number of backbuffers */
+            b_result_ok = DirectXCreateSurface( p_vout, &p_surface,
+                                                p_vout->output.i_chroma,
+                                                p_vout->p_sys->b_using_overlay,
+                                                0 /* number of backbuffers */);
+
+        if( b_result_ok )
         {
             DDSCAPS dds_caps;
+            picture_t front_pic;
+            picture_sys_t front_pic_sys;
+            front_pic.p_sys = &front_pic_sys;
 
             /* Allocate internal structure */
             p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
@@ -1018,9 +996,9 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic,
             p_pic[0].p_sys->p_front_surface = p_surface;
 
             /* Get the back buffer */
-            memset( &dds_caps, 0, sizeof( DDSCAPS ));
+            memset( &dds_caps, 0, sizeof( DDSCAPS ) );
             dds_caps.dwCaps = DDSCAPS_BACKBUFFER;
-            if( DD_OK != IDirectDrawSurface3_GetAttachedSurface(
+            if( DD_OK != IDirectDrawSurface2_GetAttachedSurface(
                                                 p_surface, &dds_caps,
                                                 &p_pic[0].p_sys->p_surface ) )
             {
@@ -1031,42 +1009,100 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic,
             }
 
 
-            p_vout->p_sys->p_current_surface= p_pic[0].p_sys->p_front_surface;
+            p_vout->p_sys->p_current_surface = front_pic.p_sys->p_surface =
+                p_pic[0].p_sys->p_front_surface;
+
+            /* reset the front buffer memory */
+            if( DirectXGetSurfaceDesc( &front_pic ) &&
+                UpdatePictureStruct( p_vout, &front_pic,
+                                     p_vout->output.i_chroma ) )
+            {
+                int i,j;
+                for( i = 0; i < front_pic.i_planes; i++ )
+                    for( j = 0; j < front_pic.p[i].i_lines; j++)
+                        memset( front_pic.p[i].p_pixels + j *
+                                front_pic.p[i].i_pitch, 127,
+                                front_pic.p[i].i_visible_bytes );
+            }
+
             DirectXUpdateOverlay( p_vout );
             I_OUTPUTPICTURES = 1;
+            intf_WarnMsg( 3,"vout: DirectX YUV overlay created successfully" );
         }
-        else p_vout->p_sys->b_using_overlay = 0;
     }
 
-    /* As we can't have overlays, will try to create plain RBG surfaces in
-     * system memory. These surfaces will then be blitted onto the primary
-     * surface (display) so they can be displayed */
+    /* As we can't have an overlay, we'll try to create a plain offscreen
+     * surface. This surface will reside in video memory because there's a
+     * better chance then that we'll be able to use some kind of hardware
+     * acceleration like rescaling, blitting or YUV->RGB conversions.
+     * We then only need to blit this surface onto the main display when we
+     * want to display it */
     if( !p_vout->p_sys->b_using_overlay )
     {
-        /* FixMe */
-        p_vout->output.i_chroma = FOURCC_RV16;
+        b_result_ok = 0;
 
-        for( i = 0; i < i_num_pics; i++ )
+        if( p_vout->p_sys->b_hw_yuv )
+            b_result_ok = DirectXCreateSurface( p_vout, &p_surface,
+                                                p_vout->output.i_chroma,
+                                                p_vout->p_sys->b_using_overlay,
+                                                0 /* no back buffers */ );
+
+        if( !p_vout->p_sys->b_hw_yuv || !b_result_ok )
         {
-            if( DirectXCreateSurface( p_vout, &p_surface,
-                                      p_vout->output.i_chroma,
-                                      p_vout->p_sys->b_using_overlay ) )
+            /* Our last choice is to use a plain RGB surface */
+            DDPIXELFORMAT ddpfPixelFormat;
+
+            ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+            IDirectDrawSurface2_GetPixelFormat( p_vout->p_sys->p_display,
+                                                &ddpfPixelFormat );
+
+            if( ddpfPixelFormat.dwFlags & DDPF_RGB )
             {
-                /* Allocate internal structure */
-                p_pic[i].p_sys = malloc( sizeof( picture_sys_t ) );
-                if( p_pic[i].p_sys == NULL )
+                switch( ddpfPixelFormat.dwRGBBitCount )
                 {
-                    DirectXCloseSurface( p_vout, p_surface );
-                    FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
-                    I_OUTPUTPICTURES = 0;
-                    return -1;
+                case 8: /* FIXME: set the palette */
+                    p_vout->output.i_chroma = FOURCC_RGB2; break;
+                case 15:
+                    p_vout->output.i_chroma = FOURCC_RV15; break;
+                case 16:
+                    p_vout->output.i_chroma = FOURCC_RV16; break;
+                case 24:
+                    p_vout->output.i_chroma = FOURCC_RV24; break;
+                case 32:
+                    p_vout->output.i_chroma = FOURCC_RV32; break;
+                default:
+                    intf_ErrMsg( "vout error: unknown screen depth" );
+                    return 0;
                 }
-                p_pic[i].p_sys->p_surface = p_surface;
-                p_pic[i].p_sys->p_front_surface = NULL;
-                I_OUTPUTPICTURES++;
+                p_vout->output.i_rmask = ddpfPixelFormat.dwRBitMask;
+                p_vout->output.i_gmask = ddpfPixelFormat.dwGBitMask;
+                p_vout->output.i_bmask = ddpfPixelFormat.dwBBitMask;
+            }
 
+            p_vout->p_sys->b_hw_yuv = 0;
+
+            b_result_ok = DirectXCreateSurface( p_vout, &p_surface,
+                                                p_vout->output.i_chroma,
+                                                p_vout->p_sys->b_using_overlay,
+                                                0 /* no back buffers */ );
+        }
+
+        if( b_result_ok )
+        {
+            /* Allocate internal structure */
+            p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
+            if( p_pic[0].p_sys == NULL )
+            {
+                DirectXCloseSurface( p_vout, p_surface );
+                return -1;
             }
-            else break;
+            p_pic[0].p_sys->p_surface = p_pic[0].p_sys->p_front_surface
+                = p_surface;
+
+            I_OUTPUTPICTURES = 1;
+
+            intf_WarnMsg( 3, "vout: DirectX plain surface created "
+                             "successfully" );
         }
     }
 
@@ -1116,13 +1152,7 @@ static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic,
 
     for( i = 0; i < i_num_pics; i++ )
     {
-#if 0
-        if( p_pic->p_sys->p_front_surface && 
-            ( p_pic->p_sys->p_surface != p_pic->p_sys->p_front_surface ) )
-            DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_front_surface );
-#endif
-
-        DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_surface );
+        DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_front_surface );
 
         for( i = 0; i < i_num_pics; i++ )
         {
@@ -1143,12 +1173,44 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic,
     switch( p_vout->output.i_chroma )
     {
 
+        case FOURCC_RGB2:
+        case FOURCC_RV15:
+        case FOURCC_RV16:
+        case FOURCC_RV24:
+        case FOURCC_RV32:
+            p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
+            p_pic->p->i_lines = p_vout->output.i_height;
+            p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
+            p_pic->p->b_margin = 0;
+            p_pic->i_planes = 1;
+            switch( p_vout->output.i_chroma )
+            {
+                case FOURCC_RGB2:
+                    p_pic->p->i_pixel_bytes = 1;
+                    break;
+                case FOURCC_RV15:
+                case FOURCC_RV16:
+                    p_pic->p->i_pixel_bytes = 2;
+                    break;
+                case FOURCC_RV24:
+                case FOURCC_RV32:
+                    p_pic->p->i_pixel_bytes = 4;
+                    break;
+                default:
+                    return -1;
+            }
+            p_pic->p->i_visible_bytes = p_vout->output.i_width *
+              p_pic->p->i_pixel_bytes;
+            break;
+
         case FOURCC_YV12:
 
             p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
             p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
             p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
             p_pic->p[Y_PLANE].i_pixel_bytes = 1;
+            p_pic->p[Y_PLANE].i_visible_bytes = p_vout->output.i_width *
+              p_pic->p[Y_PLANE].i_pixel_bytes;
             p_pic->p[Y_PLANE].b_margin = 0;
 
             p_pic->V_PIXELS =  p_pic->Y_PIXELS
@@ -1156,6 +1218,8 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic,
             p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
             p_pic->p[V_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
             p_pic->p[V_PLANE].i_pixel_bytes = 1;
+            p_pic->p[V_PLANE].i_visible_bytes = p_vout->output.i_width *
+              p_pic->p[V_PLANE].i_pixel_bytes;
             p_pic->p[V_PLANE].b_margin = 0;
 
             p_pic->U_PIXELS = p_pic->V_PIXELS
@@ -1163,47 +1227,21 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic,
             p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
             p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
             p_pic->p[U_PLANE].i_pixel_bytes = 1;
+            p_pic->p[U_PLANE].i_visible_bytes = p_vout->output.i_width *
+              p_pic->p[U_PLANE].i_pixel_bytes;
             p_pic->p[U_PLANE].b_margin = 0;
 
             p_pic->i_planes = 3;
             break;
 
-        case FOURCC_RV16:
-
-            p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
-            p_pic->p->i_lines = p_vout->output.i_height;
-            p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
-            p_pic->p->i_pixel_bytes = 2;
-            p_pic->p->b_margin = 0;
-
-            p_pic->p->i_red_mask   = 0x001f;
-            p_pic->p->i_green_mask = 0x03e0;
-            p_pic->p->i_blue_mask  = 0x7c00;
-
-            p_pic->i_planes = 1;
-            break;
-
-        case FOURCC_RV15:
-
-            p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
-            p_pic->p->i_lines = p_vout->output.i_height;
-            p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
-            p_pic->p->i_pixel_bytes = 2;
-            p_pic->p->b_margin = 0;
-
-            p_pic->p->i_red_mask   = 0x001f;
-            p_pic->p->i_green_mask = 0x07e0;
-            p_pic->p->i_blue_mask  = 0xf800;
-
-            p_pic->i_planes = 1;
-            break;
-
-        case FOURCC_I420:
+        case FOURCC_IYUV:
 
             p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
             p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
             p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
             p_pic->p[Y_PLANE].i_pixel_bytes = 1;
+            p_pic->p[Y_PLANE].i_visible_bytes = p_vout->output.i_width *
+              p_pic->p[Y_PLANE].i_pixel_bytes;
             p_pic->p[Y_PLANE].b_margin = 0;
 
             p_pic->U_PIXELS = p_pic->Y_PIXELS
@@ -1211,45 +1249,34 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic,
             p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
             p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
             p_pic->p[U_PLANE].i_pixel_bytes = 1;
+            p_pic->p[U_PLANE].i_visible_bytes = p_vout->output.i_width *
+              p_pic->p[U_PLANE].i_pixel_bytes;
             p_pic->p[U_PLANE].b_margin = 0;
 
-            p_pic->V_PIXELS = p_pic->U_PIXELS
+            p_pic->V_PIXELS =  p_pic->U_PIXELS
               + p_pic->p[U_PLANE].i_lines * p_pic->p[U_PLANE].i_pitch;
             p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
-            p_pic->p[V_PLANE].i_pitch = p_pic->p[U_PLANE].i_pitch;
+            p_pic->p[V_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
             p_pic->p[V_PLANE].i_pixel_bytes = 1;
+            p_pic->p[V_PLANE].i_visible_bytes = p_vout->output.i_width *
+              p_pic->p[V_PLANE].i_pixel_bytes;
             p_pic->p[V_PLANE].b_margin = 0;
 
             p_pic->i_planes = 3;
             break;
 
-#if 0
-        case FOURCC_Y211:
-
-            p_pic->p->p_pixels = p_pic->p_sys->p_image->data
-                                  + p_pic->p_sys->p_image->offsets[0];
-            p_pic->p->i_lines = p_vout->output.i_height;
-            /* XXX: this just looks so plain wrong... check it out ! */
-            p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0] / 4;
-            p_pic->p->i_pixel_bytes = 4;
-            p_pic->p->b_margin = 0;
-
-            p_pic->i_planes = 1;
-            break;
-
         case FOURCC_YUY2:
-        case FOURCC_UYVY:
 
-            p_pic->p->p_pixels = p_pic->p_sys->p_image->data
-                                  + p_pic->p_sys->p_image->offsets[0];
+            p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
             p_pic->p->i_lines = p_vout->output.i_height;
-            p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0];
-            p_pic->p->i_pixel_bytes = 4;
-            p_pic->p->b_margin = 0;
+            p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
+            p_pic->p->i_pixel_bytes = 2;
+            p_pic->p->i_visible_bytes = p_vout->output.i_width *
+              p_pic->p->i_pixel_bytes;
+            p_pic->p->b_margin = 1;
 
             p_pic->i_planes = 1;
             break;
-#endif
 
         default:
             /* Not supported */
@@ -1322,12 +1349,12 @@ static void DirectXGetDDrawCaps( vout_thread_t *p_vout )
  *****************************************************************************/
 static int DirectXGetSurfaceDesc( picture_t *p_pic )
 {
-    HRESULT         dxresult;
+    HRESULT dxresult;
 
     /* Lock the surface to get a valid pointer to the picture buffer */
     memset( &p_pic->p_sys->ddsd, 0, sizeof( DDSURFACEDESC ));
     p_pic->p_sys->ddsd.dwSize = sizeof(DDSURFACEDESC);
-    dxresult = IDirectDrawSurface3_Lock( p_pic->p_sys->p_surface,
+    dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface,
                                          NULL, &p_pic->p_sys->ddsd,
                                          DDLOCK_NOSYSLOCK | DDLOCK_WAIT,
                                          NULL );
@@ -1335,8 +1362,8 @@ static int DirectXGetSurfaceDesc( picture_t *p_pic )
     {
         /* Your surface can be lost so be sure
          * to check this and restore it if needed */
-        dxresult = IDirectDrawSurface3_Restore( p_pic->p_sys->p_surface );
-        dxresult = IDirectDrawSurface3_Lock( p_pic->p_sys->p_surface, NULL,
+        dxresult = IDirectDrawSurface2_Restore( p_pic->p_sys->p_surface );
+        dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface, NULL,
                                              &p_pic->p_sys->ddsd,
                                              DDLOCK_NOSYSLOCK | DDLOCK_WAIT,
                                              NULL);
@@ -1348,7 +1375,7 @@ static int DirectXGetSurfaceDesc( picture_t *p_pic )
     }
 
     /* Unlock the Surface */
-    dxresult = IDirectDrawSurface3_Unlock( p_pic->p_sys->p_surface, NULL );
+    dxresult = IDirectDrawSurface2_Unlock( p_pic->p_sys->p_surface, NULL );
 
     return 1;
 }