]> git.sesse.net Git - vlc/blobdiff - plugins/directx/vout_directx.c
* introduced a memalign wrapper that will align the memory manually if
[vlc] / plugins / directx / vout_directx.c
index bc6d3b74fba38f2bf93fa9946a50f2724dc1dfbc..c7ea2596306c0cd254ffd753b18d91d3f374711e 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * vout_directx.c: Windows DirectX video output display method
  *****************************************************************************
- * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: vout_directx.c,v 1.3 2001/06/08 20:03:15 sam Exp $
+ * Copyright (C) 2001 VideoLAN
+ * $Id: vout_directx.c,v 1.30 2002/04/05 01:05:22 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
-#define MODULE_NAME directx
-#include "modules_inner.h"
-
-/* This is a list of what needs to be fixed:
- *
- * When the option: "Display full screen when dragging window" is enabled in
- * Windows display properties, the overlay surface coordinates won't be updated
- * (but it won't crash anymore ;-) I know where the problem is in the code, but * I just don't know yet of a nice way to fix it.
- *
- * When you move part of the video window outside the physical display, the
- * overlay surface coordinates are not updated anymore. This comes from the
- * directdraw UpdateOverlay function which doesn't like negative coordinates.
- *
- * For now, this plugin only works when YUV overlay is supported (which it
- * should be nowadays on most of the video cards under Windows)...
- *
- * The overlay doesn't use double-buffering.
- *
- * Port this plugin to Video Output IV
- */
-
 /*****************************************************************************
- * Preamble
+ * Preamble:
  *
+ * This plugin will use YUV overlay if supported, using overlay will result in
+ * the best video quality (hardware interpolation when rescaling the picture)
+ * and the fastest display as it requires less processing.
+ *
+ * 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.
+ * 
  *****************************************************************************/
-#include "defs.h"
-
 #include <errno.h>                                                 /* ENOMEM */
 #include <stdlib.h>                                                /* free() */
 #include <string.h>                                            /* strerror() */
 
-#include <windows.h>
-#include <windowsx.h>
-#include <directx.h>
+#include <videolan/vlc.h>
+
+#include <ddraw.h>
 
-#include "config.h"
-#include "common.h"
-#include "threads.h"
-#include "mtime.h"
-#include "tests.h"
 #include "netutils.h"
 
 #include "video.h"
 #include "video_output.h"
 
-#include "intf_msg.h"
 #include "interface.h"
-#include "main.h"
 
-#include "modules.h"
-#include "modules_export.h"
+#include "vout_directx.h"
 
 /*****************************************************************************
- * vout_sys_t: video output DirectX method descriptor
- *****************************************************************************
- * This structure is part of the video output thread descriptor.
- * It describes the DirectX specific properties of an output thread.
+ * DirectDraw GUIDs.
+ * Defining them here allows us to get rid of the dxguid library during
+ * the linking stage.
  *****************************************************************************/
-typedef struct vout_sys_s
-{
-
-    LPDIRECTDRAW         p_ddobject;                    /* DirectDraw object */
-    LPDIRECTDRAWSURFACE  p_display;                        /* display device */
-    LPDIRECTDRAWSURFACE  p_overlay;                        /* overlay device */
-    LPDIRECTDRAWCLIPPER  p_clipper;                               /* clipper */
-    HBRUSH               hbrush;           /* window backgound brush (color) */
-    HWND                 hwnd;                  /* Handle of the main window */
-
-    int         i_image_width;                  /* size of the decoded image */
-    int         i_image_height;
-    int         i_window_width;               /* size of the displayed image */
-    int         i_window_height;
-
-    int         i_colorkey;          /* colorkey used to display the overlay */
-    boolean_t   b_display_enabled;
-    boolean_t   b_overlay;
-    boolean_t   b_cursor;
-
-    boolean_t   b_cursor_autohidden;
-    mtime_t     i_lastmoved;
-
-    char       *p_windx_buf[2];                        /* Buffer information */
-
-} vout_sys_t;
+#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 );
 
 /*****************************************************************************
  * Local prototypes.
  *****************************************************************************/
-static int  vout_Probe     ( probedata_t *p_data );
-static int  vout_Create    ( struct vout_thread_s * );
-static int  vout_Init      ( struct vout_thread_s * );
-static void vout_End       ( struct vout_thread_s * );
-static void vout_Destroy   ( struct vout_thread_s * );
-static int  vout_Manage    ( struct vout_thread_s * );
-static void vout_Display   ( struct vout_thread_s * );
-static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green,
-                             u16 *blue, u16 *transp );
-
-static int  WinDXCreateWindow     ( vout_thread_t *p_vout );
-static int  WinDXInitDDraw        ( vout_thread_t *p_vout );
-static int  WinDXCreateDisplay    ( vout_thread_t *p_vout );
-static int  WinDXCreateYUVOverlay ( vout_thread_t *p_vout );
-static int  WinDXUpdateOverlay    ( vout_thread_t *p_vout );
-static void WinDXCloseDDraw       ( vout_thread_t *p_vout );
-static void WinDXCloseWindow      ( vout_thread_t *p_vout );
-static void WinDXCloseDisplay     ( vout_thread_t *p_vout );
-static void WinDXCloseYUVOverlay  ( vout_thread_t *p_vout );
+static int  vout_Create    ( vout_thread_t * );
+static void vout_Destroy   ( vout_thread_t * );
+static int  vout_Init      ( vout_thread_t * );
+static void vout_End       ( vout_thread_t * );
+static int  vout_Manage    ( vout_thread_t * );
+static void vout_Render    ( vout_thread_t *, picture_t * );
+static void vout_Display   ( vout_thread_t *, picture_t * );
+
+static int  NewPictureVec  ( vout_thread_t *, picture_t *, int );
+static void FreePictureVec ( vout_thread_t *, picture_t *, int );
+static int  UpdatePictureStruct( vout_thread_t *, picture_t *, int );
+
+static int  DirectXInitDDraw      ( vout_thread_t *p_vout );
+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 );
+static void DirectXCloseSurface   ( vout_thread_t *p_vout,
+                                    LPDIRECTDRAWSURFACE3 );
+static int  DirectXCreateClipper  ( vout_thread_t *p_vout );
+static void DirectXGetDDrawCaps   ( vout_thread_t *p_vout );
+static int  DirectXGetSurfaceDesc ( picture_t *p_pic );
 
 /*****************************************************************************
  * Functions exported as capabilities. They are declared as static so that
@@ -136,30 +98,13 @@ static void WinDXCloseYUVOverlay  ( vout_thread_t *p_vout );
  *****************************************************************************/
 void _M( vout_getfunctions )( function_list_t * p_function_list )
 {
-    p_function_list->pf_probe = vout_Probe;
     p_function_list->functions.vout.pf_create     = vout_Create;
     p_function_list->functions.vout.pf_init       = vout_Init;
     p_function_list->functions.vout.pf_end        = vout_End;
     p_function_list->functions.vout.pf_destroy    = vout_Destroy;
     p_function_list->functions.vout.pf_manage     = vout_Manage;
+    p_function_list->functions.vout.pf_render     = vout_Render;
     p_function_list->functions.vout.pf_display    = vout_Display;
-    p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
-}
-
-/*****************************************************************************
- * vout_Probe: probe the video driver and return a score
- *****************************************************************************
- * This function tries to initialize Windows DirectX and returns a score to
- * the plugin manager so that it can select the best plugin.
- *****************************************************************************/
-static int vout_Probe( probedata_t *p_data )
-{
-    if( TestMethod( VOUT_METHOD_VAR, "directx" ) )
-    {
-        return( 999 );
-    }
-
-    return( 400 );
 }
 
 /*****************************************************************************
@@ -180,69 +125,132 @@ static int vout_Create( vout_thread_t *p_vout )
     /* Initialisations */
     p_vout->p_sys->p_ddobject = NULL;
     p_vout->p_sys->p_display = NULL;
-    p_vout->p_sys->p_overlay = NULL;
+    p_vout->p_sys->p_current_surface = NULL;
     p_vout->p_sys->p_clipper = NULL;
-    p_vout->p_sys->hbrush = INVALID_HANDLE_VALUE;
-    p_vout->p_sys->hwnd = INVALID_HANDLE_VALUE;
+    p_vout->p_sys->hbrush = NULL;
+    p_vout->p_sys->hwnd = NULL;
+    p_vout->p_sys->i_changes = 0;
+    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( "nooverlay" );
 
-    p_vout->p_sys->b_cursor = 1; /* TODO should be done with a main_GetInt.. */
+    p_vout->p_sys->b_cursor = 1;
 
     p_vout->p_sys->b_cursor_autohidden = 0;
-    p_vout->p_sys->b_display_enabled = 0;
     p_vout->p_sys->i_lastmoved = mdate();
 
-    p_vout->b_fullscreen = main_GetIntVariable( VOUT_FULLSCREEN_VAR,
-                                                VOUT_FULLSCREEN_DEFAULT );
-    p_vout->p_sys->b_overlay = main_GetIntVariable( VOUT_OVERLAY_VAR,
-                                                    VOUT_OVERLAY_DEFAULT );
-    p_vout->p_sys->i_window_width = main_GetIntVariable( VOUT_WIDTH_VAR,
-                                                         VOUT_WIDTH_DEFAULT );
-    p_vout->p_sys->i_window_height = main_GetIntVariable( VOUT_HEIGHT_VAR,
-                                                         VOUT_HEIGHT_DEFAULT );
-    /* We don't know yet the dimensions of the video so the best guess is to
-     * pick the same as the window */
-    p_vout->p_sys->i_image_width = p_vout->p_sys->i_window_width;
-    p_vout->p_sys->i_image_height = p_vout->p_sys->i_window_height;
-
-    /* Create a window for the video */
-    /* Creating a window under Windows also initializes the thread's event
-     * message qeue */
-    if( WinDXCreateWindow( p_vout ) )
+    /* Set main window's size */
+    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 );
+    vlc_cond_init( &p_vout->p_sys->event_thread_wait );
+    p_vout->p_sys->i_event_thread_status = THREAD_CREATE;
+
+    /* Create the DirectXEventThread, this thread is created by us to isolate
+     * the Win32 PeekMessage function calls. We want to do this because
+     * Windows can stay blocked inside this call for a long time, and when
+     * this happens it thus blocks vlc's video_output thread.
+     * DirectXEventThread will take care of the creation of the video
+     * window (because PeekMessage has to be called from the same thread which
+     * created the window). */
+    intf_WarnMsg( 3, "vout: vout_Create creating DirectXEventThread" );
+    if( vlc_thread_create( &p_vout->p_sys->event_thread_id,
+                           "DirectX Events Thread",
+                           (void *) DirectXEventThread, (void *) p_vout) )
     {
-        intf_ErrMsg( "vout error: can't create window" );
+        intf_ErrMsg( "vout error: can't create DirectXEventThread" );
+        intf_ErrMsg("vout error: %s", strerror(ENOMEM));
         free( p_vout->p_sys );
-        return ( 1 );
+        return( 1 );
     }
 
+    /* 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_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 );
+    if( p_vout->p_sys->i_event_thread_status != THREAD_READY )
+    {
+        intf_ErrMsg( "vout error: DirectXEventThread failed" );
+        free( p_vout->p_sys );
+        return( 1 );
+    }
+
+    intf_WarnMsg( 3, "vout: vout_Create DirectXEventThread running" );
+
+
     /* Initialise DirectDraw */
-    if( WinDXInitDDraw( p_vout ) )
+    if( DirectXInitDDraw( p_vout ) )
     {
         intf_ErrMsg( "vout error: can't initialise DirectDraw" );
-        WinDXCloseWindow( p_vout );
-        free( p_vout->p_sys );
+
+        /* 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 );
     }
 
-    /* create the directx display */
-    if( WinDXCreateDisplay( p_vout ) )
+    /* Create the directx display */
+    if( DirectXCreateDisplay( p_vout ) )
     {
         intf_ErrMsg( "vout error: can't initialise DirectDraw" );
-        WinDXCloseDDraw( p_vout );
-        WinDXCloseWindow( p_vout );
-        free( p_vout->p_sys );
+        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 );
     }
 
+    /* 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 );
 }
 
 /*****************************************************************************
  * vout_Init: initialize DirectX video thread output method
  *****************************************************************************
- *
+ * This function create the directx surfaces needed by the output thread.
+ * It is called at the beginning of the thread.
  *****************************************************************************/
 static int vout_Init( vout_thread_t *p_vout )
 {
+
+    /* Initialize the output structure.
+     * Since DirectDraw can do rescaling for us, stick to the default
+     * coordinates and aspect. */
+    p_vout->output.i_width  = p_vout->render.i_width;
+    p_vout->output.i_height = p_vout->render.i_height;
+    p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+#define MAX_DIRECTBUFFERS 1
+
+    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)" );
+
     return( 0 );
 }
 
@@ -254,6 +262,7 @@ static int vout_Init( vout_thread_t *p_vout )
  *****************************************************************************/
 static void vout_End( vout_thread_t *p_vout )
 {
+    FreePictureVec( p_vout, p_vout->p_picture, I_OUTPUTPICTURES );
     return;
 }
 
@@ -265,180 +274,77 @@ static void vout_End( vout_thread_t *p_vout )
 static void vout_Destroy( vout_thread_t *p_vout )
 {
     intf_WarnMsg( 3, "vout: vout_Destroy" );
-    WinDXCloseDisplay( p_vout );
-    WinDXCloseDDraw( p_vout );
-    WinDXCloseWindow( p_vout );
+    DirectXCloseDisplay( p_vout );
+    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 */
+    if( p_vout->p_sys->i_event_thread_status == THREAD_READY &&
+        p_vout->p_sys->hwnd )
+    {
+        PostMessage( p_vout->p_sys->hwnd, WM_CHAR, (WPARAM)'^', 0);
+        vlc_thread_join( p_vout->p_sys->event_thread_id );
+    }
 
     if( p_vout->p_sys != NULL )
     {
         free( p_vout->p_sys );
         p_vout->p_sys = NULL;
     }
-
 }
 
 /*****************************************************************************
  * vout_Manage: handle Sys events
  *****************************************************************************
- * This function should be called regularly by video output thread. It returns
- * a non null value if an error occured.
+ * This function should be called regularly by the video output thread.
+ * It returns a non null value if an error occured.
  *****************************************************************************/
 static int vout_Manage( vout_thread_t *p_vout )
 {
-    MSG             msg;
     WINDOWPLACEMENT window_placement;
-    boolean_t       b_dispatch_msg = TRUE;
-
-    while( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
-    {
-        if( GetMessage(&msg, NULL, 0, 0) >= 0 )
-        {
-            switch( msg.message )
-            {
-
-                case WM_CLOSE:
-                    intf_WarnMsg( 3, "vout: WinDX vout_Manage WM_CLOSE" );
-                    p_vout->b_die = 1;
-                    break;
-
-                case WM_QUIT:
-                    intf_WarnMsg( 3, "vout: WinDX vout_Manage WM_QUIT" );
-                    p_main->p_intf->b_die = 1;
-                    break;
-
-                case WM_MOVE:
-                    intf_WarnMsg( 3, "vout: WinDX vout_Manage WM_MOVE" );
-                    if( !p_vout->b_need_render )
-                    {
-                        p_vout->i_changes |= VOUT_SIZE_CHANGE;
-                    }
-                    /* don't create a never ending loop */
-                    b_dispatch_msg = FALSE;
-                    break;
-
-                case WM_APP:
-                    intf_WarnMsg( 3, "vout: WinDX vout_Manage WM_APP" );
-                    if( !p_vout->b_need_render )
-                    {
-                        p_vout->i_changes |= VOUT_SIZE_CHANGE;
-                    }
-                    /* don't create a never ending loop */
-                    b_dispatch_msg = FALSE;
-                    break;
-
-                case WM_PAINT:
-                    intf_WarnMsg( 3, "vout: WinDX vout_Manage WM_PAINT" );
-                    break;
-
-                case WM_ERASEBKGND:
-                    intf_WarnMsg( 3, "vout: WinDX vout_Manage WM_ERASEBKGND" );
-                    break;
-
-                case WM_MOUSEMOVE:
-                    intf_WarnMsg( 3, "vout: WinDX vout_Manage WM_MOUSEMOVE" );
-                    if( p_vout->p_sys->b_cursor )
-                    {
-                    if( p_vout->p_sys->b_cursor_autohidden )
-                        {
-                            p_vout->p_sys->b_cursor_autohidden = 0;
-                            p_vout->p_sys->i_lastmoved = mdate();
-                            ShowCursor( TRUE );
-                        }
-                        else
-                        {
-                            p_vout->p_sys->i_lastmoved = mdate();
-                        }
-                    }               
-                    break;
-
-                case WM_KEYDOWN:
-                    /* the key events are first processed here. The next
-                     * message processed by this main message loop will be the
-                     * char translation of the key event */
-                    intf_WarnMsg( 3, "vout: WinDX vout_Manage WM_KEYDOWN" );
-                    switch( msg.wParam )
-                    {
-                        case VK_ESCAPE:
-                        case VK_F12:
-                            p_main->p_intf->b_die = 1;
-                            break;
-                    }
-                    TranslateMessage(&msg);
-                    b_dispatch_msg = FALSE;
-                    break;
-
-                case WM_CHAR:
-                    intf_WarnMsg( 3, "vout: WinDX vout_Manage WM_CHAR" );
-                    switch( msg.wParam )
-                    {
-                        case 'q':
-                        case 'Q':
-                            p_main->p_intf->b_die = 1;
-                            break;
-
-                        case 'f':
-                        case 'F':
-                            p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
-                            break;
-
-                        case '0': network_ChannelJoin( 0 ); break;
-                        case '1': network_ChannelJoin( 1 ); break;
-                        case '2': network_ChannelJoin( 2 ); break;
-                        case '3': network_ChannelJoin( 3 ); break;
-                        case '4': network_ChannelJoin( 4 ); break;
-                        case '5': network_ChannelJoin( 5 ); break;
-                        case '6': network_ChannelJoin( 6 ); break;
-                        case '7': network_ChannelJoin( 7 ); break;
-                        case '8': network_ChannelJoin( 8 ); break;
-                        case '9': network_ChannelJoin( 9 ); break;
-
-                        default:
-                            if( intf_ProcessKey( p_main->p_intf,
-                                                 (char )msg.wParam ) )
-                            {
-                               intf_DbgMsg( "unhandled key '%c' (%i)",
-                                            (char)msg.wParam, msg.wParam );
-                            }
-                            break;
-                    }
-
-                default:
-                    intf_WarnMsg( 3, "vout: WinDX vout_Manage WM Default %i",
-                                  msg.message );
-                break;
-            }
 
-            /* don't create a never ending loop */
-            if( b_dispatch_msg )
-            {
-                TranslateMessage(&msg);
-                DispatchMessage(&msg);
-            }
-            b_dispatch_msg = TRUE;
+    /* We used to call the Win32 PeekMessage function here to read the window
+     * messages. But since window can stay blocked into this function for a
+     * long time (for example when you move your window on the screen), I
+     * decided to isolate PeekMessage in another thread. */
 
-        }
+    /*
+     * Scale Change 
+     */
+    if( p_vout->i_changes & VOUT_SCALE_CHANGE
+        || p_vout->p_sys->i_changes & VOUT_SCALE_CHANGE)
+    {
+        intf_WarnMsg( 3, "vout: vout_Manage Scale Change" );
+        if( !p_vout->p_sys->b_using_overlay )
+            InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE );
         else
-        {
-            return( 1 );
-        }
-
+            DirectXUpdateOverlay( p_vout );
+        p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
+        p_vout->p_sys->i_changes &= ~VOUT_SCALE_CHANGE;
     }
 
-
     /*
      * Size Change 
      */
-    if( p_vout->i_changes & VOUT_SIZE_CHANGE )
+    if( p_vout->i_changes & VOUT_SIZE_CHANGE
+        || p_vout->p_sys->i_changes & VOUT_SIZE_CHANGE )
     {
-        intf_WarnMsg( 3, "vout: WinDX vout_Manage Size Change" );
-        WinDXUpdateOverlay( p_vout );
+        intf_WarnMsg( 3, "vout: vout_Manage Size Change" );
+        if( !p_vout->p_sys->b_using_overlay )
+            InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE );
+        else
+            DirectXUpdateOverlay( p_vout );
         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
+        p_vout->p_sys->i_changes &= ~VOUT_SIZE_CHANGE;
     }
 
     /*
      * Fullscreen change
      */
-    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
+    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
+        || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
     {
         p_vout->b_fullscreen = ! p_vout->b_fullscreen;
 
@@ -463,23 +369,25 @@ static int vout_Manage( vout_thread_t *p_vout )
         }
 
         SetWindowPlacement( p_vout->p_sys->hwnd, &window_placement );
-        /*WinDXUpdateOverlay( p_vout );*/
 
         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+        p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
     }
 
     /*
      * Pointer change
      */
     if( ! p_vout->p_sys->b_cursor_autohidden &&
-        ( mdate() - p_vout->p_sys->i_lastmoved > 2000000 ) )
+        ( mdate() - p_vout->p_sys->i_lastmoved > 5000000 ) )
     {
         /* Hide the mouse automatically */
         p_vout->p_sys->b_cursor_autohidden = 1;
         ShowCursor( FALSE );
     }
 
-    if( p_vout->i_changes & VOUT_CURSOR_CHANGE )
+#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;
 
@@ -487,156 +395,117 @@ static int vout_Manage( vout_thread_t *p_vout )
                      ! p_vout->p_sys->b_cursor_autohidden );
 
         p_vout->i_changes &= ~VOUT_CURSOR_CHANGE;
+        p_vout->p_sys->i_changes &= ~VOUT_CURSOR_CHANGE;
     }
+#endif
+
+    /* Check if the event thread is still running */
+    if( p_vout->p_sys->b_event_thread_die )
+        return 1; /* exit */
 
     return( 0 );
 }
 
 /*****************************************************************************
- * vout_SetPalette: sets an 8 bpp palette
- *****************************************************************************
- * This function sets the palette given as an argument. It does not return
- * anything, but could later send information on which colors it was unable
- * to set.
+ * vout_Render: render previously calculated output
  *****************************************************************************/
-static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green,
-                         u16 *blue, u16 *transp)
+static void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
 {
-    /* Nothing yet */
-    return;
+    ;
 }
 
 /*****************************************************************************
  * vout_Display: displays previously rendered output
  *****************************************************************************
- * This function send the currently rendered image to the display, wait until
- * it is displayed and switch the two rendering buffer, preparing next frame.
+ * This function sends the currently rendered image to the display, wait until
+ * it is displayed and switch the two rendering buffers, preparing next frame.
  *****************************************************************************/
-static void vout_Display( vout_thread_t *p_vout )
+static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
 {
-    DDSURFACEDESC ddsd;
-    HRESULT       dxresult;
-    int           i;
-    int           i_image_width  = p_vout->p_rendered_pic->i_width;
-    int           i_image_height = p_vout->p_rendered_pic->i_height;
-
+    HRESULT dxresult;
 
     if( (p_vout->p_sys->p_display == NULL) )
     {
-        intf_WarnMsg( 3, "vout error: WinDX no display!!" );
+        intf_WarnMsg( 3, "vout error: vout_Display no display!!" );
         return;
     }
 
-    /* The first time this function is called it enables the display */
-    p_vout->p_sys->b_display_enabled = 1;
-
-    if( p_vout->b_need_render )
+    if( !p_vout->p_sys->b_using_overlay )
     {
-        /* Nothing yet */
-    }
-    else
-    {
-        /*
-         * p_vout->p_rendered_pic->p_y/u/v contains the YUV buffers to
-         * render
-         */
-        /* TODO: support for streams other than 4:2:0 */
-
-        /* if the size of the decoded pictures has changed then we close the
-         * YUVOverlay (which doesn't have the right size anymore). */
-        if( p_vout->p_sys->i_image_width != i_image_width
-            || p_vout->p_sys->i_image_height != i_image_height )
+        DDBLTFX  ddbltfx;
+
+        /* We ask for the "NOTEARING" option */
+        memset( &ddbltfx, 0, sizeof(DDBLTFX) );
+        ddbltfx.dwSize = sizeof(DDBLTFX);
+        ddbltfx.dwDDFX = DDBLTFX_NOTEARING | DDBLT_ASYNC;
+
+        /* Blit video surface to display */
+        dxresult = IDirectDrawSurface3_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 );
+        if ( dxresult == DDERR_SURFACELOST )
         {
-            intf_WarnMsg( 3, "vout: WinDX overlay size changed" );
-            p_vout->p_sys->i_image_width = i_image_width;
-            p_vout->p_sys->i_image_height = i_image_height;
-            WinDXCloseYUVOverlay( p_vout );
+            /* Our surface can be lost so be sure
+             * to check this and restore it if needed */
+            IDirectDrawSurface3_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,
+                                           &p_vout->p_sys->rect_dest_clipped,
+                                           p_pic->p_sys->p_surface,
+                                           &p_vout->p_sys->rect_src_clipped,
+                                           0, &ddbltfx );
         }
 
-        if( p_vout->p_sys->p_overlay == NULL )
+        if( dxresult != DD_OK )
         {
-            intf_WarnMsg( 3, "vout: WinDX no overlay, open one..." );
-            if( WinDXCreateYUVOverlay( p_vout ) )
-            {
-                intf_WarnMsg( 3, "vout: WinDX cannot open a new overlay !!" );
-                return;
-            }
-            /* Display the Overlay */
-            p_vout->p_sys->b_display_enabled = 1;
-            WinDXUpdateOverlay( p_vout );
+            intf_WarnMsg( 3, "vout: could not Blit the surface" );
+            return;
         }
 
-        /* Lock the overlay surface */
-        memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
-        ddsd.dwSize = sizeof(DDSURFACEDESC);
-        dxresult = IDirectDrawSurface_Lock(p_vout->p_sys->p_overlay, NULL,
-                                           &ddsd, DDLOCK_NOSYSLOCK, NULL);
+    }
+    else /* using overlay */
+    {
+
+#if 0
+        /* Flip the overlay buffers */
+        dxresult = IDirectDrawSurface3_Flip( p_pic->p_sys->p_front_surface,
+                                             NULL, DDFLIP_WAIT );
         if ( dxresult == DDERR_SURFACELOST )
         {
-            /* Your surface can be lost (thanks to windows) so be sure
+            /* Our surface can be lost so be sure
              * to check this and restore it if needed */
-            dxresult = IDirectDrawSurface_Restore( p_vout->p_sys->p_overlay );
-            dxresult = IDirectDrawSurface_Lock( p_vout->p_sys->p_overlay,
-                                                NULL, &ddsd, DDLOCK_NOSYSLOCK
-                                                | DDLOCK_WAIT, NULL);
+            IDirectDrawSurface3_Restore( p_vout->p_sys->p_display );
+            IDirectDrawSurface3_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,
+                                                 NULL, DDFLIP_WAIT );
+            DirectXUpdateOverlay( p_vout );
         }
+
         if( dxresult != DD_OK )
+            intf_WarnMsg( 8, "vout: couldn't flip overlay surface" );
+#endif
+
+        if( !DirectXGetSurfaceDesc( p_pic ) )
         {
-            intf_WarnMsg( 3, "vout: WinDX could not lock the surface" );
+            /* AAARRGG */
+            intf_ErrMsg( "vout error: vout_Display cannot get surface desc" );
             return;
         }
 
-        /* Now we can do the actual image copy.
-         * The copy has to be done line by line because of the special case
-         * when the Pitch does not equal the width of the picture */
-        for( i=0; i < ddsd.dwHeight/2; i++)
+        if( !UpdatePictureStruct( p_vout, p_pic, p_vout->output.i_chroma ) )
         {
-#ifdef NONAMELESSUNION
-            /* copy Y, we copy two lines at once */
-            memcpy(ddsd.lpSurface + i*2*ddsd.u1.lPitch,
-                   p_vout->p_rendered_pic->p_y + i*2*i_image_width,
-                   i_image_width);
-            memcpy(ddsd.lpSurface + (i*2+1)*ddsd.u1.lPitch,
-                   p_vout->p_rendered_pic->p_y + (i*2+1)*i_image_width,
-                   i_image_width);
-            /* then V */
-            memcpy((ddsd.lpSurface + ddsd.dwHeight * ddsd.u1.lPitch)
-                      + i * ddsd.u1.lPitch/2,
-                   p_vout->p_rendered_pic->p_v + i*i_image_width/2,
-                   i_image_width/2);
-            /* and U */
-            memcpy((ddsd.lpSurface + ddsd.dwHeight * ddsd.u1.lPitch)
-                      + (ddsd.dwHeight * ddsd.u1.lPitch/4)
-                      + i * ddsd.u1.lPitch/2,
-                   p_vout->p_rendered_pic->p_u + i*i_image_width/2,
-                   i_image_width/2);
-#else
-            /* copy Y, we copy two lines at once */
-            memcpy(ddsd.lpSurface + i*2*ddsd.lPitch,
-                   p_vout->p_rendered_pic->p_y + i*2*i_image_width,
-                   i_image_width);
-            memcpy(ddsd.lpSurface + (i*2+1)*ddsd.lPitch,
-                   p_vout->p_rendered_pic->p_y + (i*2+1)*i_image_width,
-                   i_image_width);
-            /* then V */
-            memcpy((ddsd.lpSurface + ddsd.dwHeight * ddsd.lPitch)
-                      + i * ddsd.lPitch/2,
-                   p_vout->p_rendered_pic->p_v + i*i_image_width/2,
-                   i_image_width/2);
-            /* and U */
-            memcpy((ddsd.lpSurface + ddsd.dwHeight * ddsd.lPitch)
-                      + (ddsd.dwHeight * ddsd.lPitch/4)
-                      + i * ddsd.lPitch/2,
-                   p_vout->p_rendered_pic->p_u + i*i_image_width/2,
-                   i_image_width/2);
-#endif /* NONAMELESSUNION */
-
+            /* AAARRGG */
+            intf_ErrMsg( "vout error: vout_Display unvalid pic chroma" );
+            return;
         }
 
-        /* Unlock the Surface */
-        dxresult = IDirectDrawSurface_Unlock(p_vout->p_sys->p_overlay,
-                                             ddsd.lpSurface );
-
+        /* set currently displayed pic */
+        p_vout->p_sys->p_current_surface = p_pic->p_sys->p_front_surface;
     }
 
 }
@@ -644,784 +513,822 @@ static void vout_Display( vout_thread_t *p_vout )
 
 /* following functions are local */
 
-
 /*****************************************************************************
- * WinDXEventProc: This is the window event processing function.
+ * DirectXInitDDraw: Takes care of all the DirectDraw initialisations
  *****************************************************************************
- * On Windows, when you create a window you have to attach an event processing
- * function to it. The aim of this function is to manage "Queued Messages" and
- * "Nonqueued Messages".
- * Queued Messages are those picked up and retransmitted by vout_Manage
- * (using the GetMessage function).
- * Nonqueued Messages are those that Windows will send directly to this
- * function (like WM_DESTROY, WM_WINDOWPOSCHANGED...)
+ * This function initialise and allocate resources for DirectDraw.
  *****************************************************************************/
-long FAR PASCAL WinDXEventProc( HWND hwnd, UINT message,
-                                WPARAM wParam, LPARAM lParam )
+static int DirectXInitDDraw( vout_thread_t *p_vout )
 {
-    switch( message )
-    {
-
-    case WM_ACTIVATE:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_ACTIVED" );
-        break;
+    HRESULT    dxresult;
+    HRESULT    (WINAPI *OurDirectDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
+    LPDIRECTDRAW  p_ddobject;
 
-    case WM_CREATE:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_CREATE" );
-        break;
+    intf_WarnMsg( 3, "vout: DirectXInitDDraw" );
 
-    /* the user wants to close the window */
-    case WM_CLOSE:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_CLOSE" );
-        break;
-
-    /* the window has been closed so shut down everything now */
-    case WM_DESTROY:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_DESTROY" );
-        PostQuitMessage( 0 );
-        break;
-
-    case WM_SYSCOMMAND:
-        switch (wParam)
-        {
-            case SC_SCREENSAVE:                     /* catch the screensaver */
-            case SC_MONITORPOWER:              /* catch the monitor turn-off */
-            intf_WarnMsg( 3, "vout: WinDX WinProc WM_SYSCOMMAND" );
-            return 0;                      /* this stops them from happening */
-        }
-        break;
-
-    case WM_MOVE:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_MOVE" );
-        break;
-
-    case WM_SIZE:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_SIZE" );
-        break;
-
-    case WM_MOVING:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_MOVING" );
-        break;
-
-    case WM_SIZING:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_SIZING" );
-        break;
-
-    case WM_WINDOWPOSCHANGED:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_WINDOWPOSCHANGED" );
-        PostMessage( NULL, WM_APP, 0, 0);
-        break;
-
-    case WM_WINDOWPOSCHANGING:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_WINDOWPOSCHANGING" );
-        break;
-
-    case WM_PAINT:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_PAINT" );
-        break;
-
-    case WM_ERASEBKGND:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM_ERASEBKGND" );
-        break;
-
-    default:
-        intf_WarnMsg( 3, "vout: WinDX WinProc WM Default %i", message );
-        break;
-    }
-
-    return DefWindowProc(hwnd, message, wParam, lParam);
-}
-
-/*****************************************************************************
- * WinDXCreateWindow: create a windows window where the video will play.
- *****************************************************************************
- * Before creating a direct draw surface, we need to create a window in which
- * the video will be displayed. This window will also allow us to capture the
- * events.
- *****************************************************************************/
-static int WinDXCreateWindow( vout_thread_t *p_vout )
-{
-    HINSTANCE hInstance;
-    WNDCLASS  wc;                                 /* window class components */
-    RECT      rect_window;
-    COLORREF  colorkey; 
-    HDC       hdc;
-
-    intf_WarnMsg( 3, "vout: WinDX WinDXCreateWindow" );
-
-    /* get this module's instance */
-    hInstance = GetModuleHandle(NULL);
-
-    /* Create a BRUSH that will be used by Windows to paint the window
-     * background.
-     * This window background is important for us as it will be used by the
-     * graphics card to display the overlay.
-     * This is why we carefully choose the color for this background, the goal
-     * being to choose a color which isn't complete black but nearly. We
-     * obviously don't want to use black as a colorkey for the overlay because
-     * black is one of the most used color and thus would give us undesirable
-     * effects */
-    /* the first step is to find the colorkey we want to use. The difficulty
-     * comes from the potential dithering (depends on the display depth)
-     * because we need to know the real RGB value of the chosen colorkey */
-    hdc = GetDC( GetDesktopWindow() );
-    for( colorkey = 1; colorkey < 0xFF /*all shades of red*/; colorkey++ )
+    /* load direct draw DLL */
+    p_vout->p_sys->hddraw_dll = LoadLibrary("DDRAW.DLL");
+    if( p_vout->p_sys->hddraw_dll == NULL )
     {
-        if( colorkey == GetNearestColor( hdc, colorkey ) )
-          break;
-    }
-    intf_WarnMsg( 3, "vout: WinDXCreateWindow background color:%i", colorkey );
-    ReleaseDC( p_vout->p_sys->hwnd, hdc );
-
-    /* create the actual brush */  
-    p_vout->p_sys->hbrush = CreateSolidBrush(colorkey);
-    p_vout->p_sys->i_colorkey = (int)colorkey;
-
-    /* fill in the window class structure */
-    wc.style         = 0;                               /* no special styles */
-    wc.lpfnWndProc   = (WNDPROC)WinDXEventProc;             /* event handler */
-    wc.cbClsExtra    = 0;                             /* no extra class data */
-    wc.cbWndExtra    = 0;                            /* no extra window data */
-    wc.hInstance     = hInstance;                                /* instance */
-    wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO);   /* load a default icon */
-    wc.hCursor       = LoadCursor(NULL, IDC_ARROW); /* load a default cursor */
-    wc.hbrBackground = p_vout->p_sys->hbrush;            /* background color */
-    wc.lpszMenuName  = NULL;                                      /* no menu */
-    wc.lpszClassName = "VLC DirectX";                 /* use a special class */
-
-    /* register the window class */
-    if (!RegisterClass(&wc)) {
-        intf_WarnMsg( 3, "vout: WinDX register window FAILED" );
-        return (1);
+        intf_WarnMsg( 3, "vout: DirectXInitDDraw failed loading ddraw.dll" );
+        return( 1 );
     }
-
-    /* when you create a window you give the dimensions you wish it to have.
-     * Unfortunatly these dimensions will include the borders and title bar.
-     * We use the following function to find out the size of the window
-     * corresponding to the useable surface we want */
-    rect_window.top    = 10;
-    rect_window.left   = 10;
-    rect_window.right  = rect_window.left + p_vout->p_sys->i_window_width;
-    rect_window.bottom = rect_window.top + p_vout->p_sys->i_window_height;
-    AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 );
-
-    /* create the window */
-    p_vout->p_sys->hwnd = CreateWindow("VLC DirectX",/* name of window class */
-                    "VLC DirectX",                  /* window title bar text */
-                    WS_OVERLAPPEDWINDOW
-                    | WS_SIZEBOX | WS_VISIBLE,               /* window style */
-                    10,                              /* default X coordinate */
-                    10,                              /* default Y coordinate */
-                    rect_window.right - rect_window.left,    /* window width */
-                    rect_window.bottom - rect_window.top,   /* window height */
-                    NULL,                                /* no parent window */
-                    NULL,                          /* no menu in this window */
-                    hInstance,            /* handle of this program instance */
-                    NULL);                        /* no additional arguments */
-
-    if (p_vout->p_sys->hwnd == NULL) {
-        intf_WarnMsg( 3, "vout: WinDX create window FAILED" );
-        return (1);
+      
+    OurDirectDrawCreate = 
+      (void *)GetProcAddress(p_vout->p_sys->hddraw_dll, "DirectDrawCreate");
+    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 );    
     }
 
-    /* now display the window */
-    ShowWindow(p_vout->p_sys->hwnd, SW_SHOW);
-
-    return ( 0 );
-}
-
-/*****************************************************************************
- * WinDXInitDDraw: Takes care of all the DirectDraw initialisations
- *****************************************************************************
- * This function initialise and allocate resources for DirectDraw.
- *****************************************************************************/
-static int WinDXInitDDraw( vout_thread_t *p_vout )
-{
-    HRESULT     dxresult;
-    DWORD       flags;
-
-    intf_WarnMsg( 3, "vout: WinDX WinDXInitDDraw" );
-
-    /* Initialize DirectDraw */
-    dxresult = DirectDrawCreate( NULL, &p_vout->p_sys->p_ddobject, NULL );
+    /* Initialize DirectDraw now */
+    dxresult = OurDirectDrawCreate( NULL, &p_ddobject, NULL );
     if( dxresult != DD_OK )
     {
-        intf_ErrMsg( "vout error: can't initialize Direct Draw" );
+        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 */
-    if( p_vout->b_fullscreen )
-    {
-        flags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
-    }
-    else
+     * display */
+    dxresult = IDirectDraw_SetCooperativeLevel( p_ddobject,
+                                           p_vout->p_sys->hwnd, DDSCL_NORMAL );
+    if( dxresult != DD_OK )
     {
-        flags = DDSCL_NORMAL;
+        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 );
     }
 
-    dxresult = IDirectDraw_SetCooperativeLevel( p_vout->p_sys->p_ddobject,
-                                                p_vout->p_sys->hwnd, flags );
+    /* Get the IDirectDraw2 interface */
+    dxresult = IDirectDraw_QueryInterface( p_ddobject, &IID_IDirectDraw2,
+                                        (LPVOID *)&p_vout->p_sys->p_ddobject );
     if( dxresult != DD_OK )
     {
-        intf_ErrMsg( "vout error: can't set direct draw cooperative level." );
-        IDirectDraw_Release(p_vout->p_sys->p_ddobject);
+        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 );
     }
+    else
+    {
+        /* Release the unused interface */
+        IDirectDraw_Release( p_ddobject );
+    }
 
+    /* Probe the capabilities of the hardware */
+    DirectXGetDDrawCaps( p_vout );
+
+    intf_WarnMsg( 3, "vout: End DirectXInitDDraw" );
     return( 0 );
 }
 
 /*****************************************************************************
- * WinDXCreateDisplay: create the DirectDraw display.
+ * DirectXCreateDisplay: create the DirectDraw display.
  *****************************************************************************
  * Create and initialize display according to preferences specified in the vout
  * thread fields.
  *****************************************************************************/
-static int WinDXCreateDisplay( vout_thread_t *p_vout )
+static int DirectXCreateDisplay( vout_thread_t *p_vout )
 {
-    DDCAPS        ddcaps;
-    HRESULT       dxresult;
-    DDSURFACEDESC ddsd;
-    BOOL          bHasOverlay, bHasColorKey, bCanStretch;
+    HRESULT              dxresult;
+    DDSURFACEDESC        ddsd;
+    LPDIRECTDRAWSURFACE  p_display;
+    DDPIXELFORMAT   pixel_format;
+
+    intf_WarnMsg( 3, "vout: DirectXCreateDisplay" );
 
-    /* Now create the primary surface. This surface is the displayed surface */
-    /* The following two steps are important! */
+    /* Now get the primary surface. This surface is what you actually see
+     * on your screen */
     memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
     ddsd.dwSize = sizeof(DDSURFACEDESC);
     ddsd.dwFlags = DDSD_CAPS;
     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
 
-    dxresult = IDirectDraw_CreateSurface( p_vout->p_sys->p_ddobject,
-                                          &ddsd,
-                                          &p_vout->p_sys->p_display, NULL );
+    dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
+                                           &ddsd,
+                                           &p_display, NULL );
     if( dxresult != DD_OK )
     {
-        intf_ErrMsg( "vout error: can't create direct draw primary surface." );
+        intf_ErrMsg( "vout error: can't get direct draw primary surface." );
         p_vout->p_sys->p_display = NULL;
         return( 1 );
     }
 
-#if 0
-    /* Now create a clipper for our window.
-     * This clipper prevents us to modify by mistake anything on the screen
-     * (primary surface) which doesn't belong to our window */
-    dxresult = IDirectDraw_CreateClipper(p_vout->p_sys->p_ddobject, 0,
-                                         &p_vout->p_sys->p_clipper, NULL);
-    if( dxresult != DD_OK )
+    dxresult = IDirectDrawSurface_QueryInterface( p_display,
+                                         &IID_IDirectDrawSurface3,
+                                         (LPVOID *)&p_vout->p_sys->p_display );
+    if ( dxresult != DD_OK )
     {
-        intf_ErrMsg( "vout error: can't create clipper." );
-        IDirectDrawSurface_Release( p_vout->p_sys->p_display );
+        intf_ErrMsg( "vout error: can't get IDirectDrawSurface3 interface." );
+        IDirectDrawSurface_Release( p_display );
         p_vout->p_sys->p_display = NULL;
         return( 1 );
     }
+    else
+    {
+        /* Release the old interface */
+        IDirectDrawSurface_Release( p_display );
+    }
 
-    dxresult = IDirectDrawClipper_SetHWnd(p_vout->p_sys->p_clipper, 0,
-                                              p_vout->p_sys->hwnd);
+
+    /* The clipper will be used only in non-overlay mode */
+    DirectXCreateClipper( p_vout );
+
+
+#if 1
+    /* 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,
+                                                   &pixel_format );
+    if( dxresult != DD_OK )
+        intf_WarnMsg( 3, "vout: DirectXUpdateOverlay GetPixelFormat failed" );
+    p_vout->p_sys->i_colorkey = (DWORD)((( p_vout->p_sys->i_rgb_colorkey
+                                           * pixel_format.dwRBitMask) / 255)
+                                        & pixel_format.dwRBitMask);
+#endif
+
+    return( 0 );
+}
+
+
+/*****************************************************************************
+ * DirectXCreateClipper: Create a clipper that will be used when blitting the
+ *                       RGB surface to the main display.
+ *****************************************************************************
+ * This clipper prevents us to modify by mistake anything on the screen
+ * which doesn't belong to our window. For example when a part of our video
+ * window is hidden by another window.
+ *****************************************************************************/
+static int DirectXCreateClipper( vout_thread_t *p_vout )
+{
+    HRESULT dxresult;
+
+    intf_WarnMsg( 3, "vout: DirectXCreateClipper" );
+
+    /* Create the clipper */
+    dxresult = IDirectDraw2_CreateClipper( p_vout->p_sys->p_ddobject, 0,
+                                           &p_vout->p_sys->p_clipper, NULL );
     if( dxresult != DD_OK )
     {
-        intf_ErrMsg( "vout error: can't attach clipper to window." );
-        IDirectDrawSurface_Release( p_vout->p_sys->p_display );
-        p_vout->p_sys->p_display = NULL;
+        intf_WarnMsg( 3, "vout: DirectXCreateClipper can't create clipper." );
+        p_vout->p_sys->p_clipper = NULL;
         return( 1 );
     }
 
-    dxresult = IDirectDrawSurface_SetClipper(p_vout->p_sys->p_display,
-                                              p_vout->p_sys->p_clipper);
+    /* associate the clipper to the window */
+    dxresult = IDirectDrawClipper_SetHWnd(p_vout->p_sys->p_clipper, 0,
+                                          p_vout->p_sys->hwnd);
     if( dxresult != DD_OK )
     {
-        intf_ErrMsg( "vout error: can't attach clipper to surface." );
-        IDirectDrawSurface_Release( p_vout->p_sys->p_display );
-        p_vout->p_sys->p_display = NULL;
+        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 );
     }
-#endif
 
-    /* Probe the capabilities of the hardware */
-    /* This is just an indication of whever or not we'll support overlay,
-     * but with this test we don't know if we support YUV overlay */
-    memset( &ddcaps, 0, sizeof( DDCAPS ));
-    ddcaps.dwSize = sizeof(DDCAPS);
-    dxresult = IDirectDraw_GetCaps( p_vout->p_sys->p_ddobject,
-                                    &ddcaps, NULL );
-    if(dxresult != DD_OK )
-    {
-        intf_ErrMsg( "vout error: can't get caps." );
-        bHasOverlay  = FALSE;
-        bHasColorKey = FALSE;
-        bCanStretch  = FALSE;
-    }
-    else
+    /* associate the clipper with the surface */
+    dxresult = IDirectDrawSurface_SetClipper(p_vout->p_sys->p_display,
+                                             p_vout->p_sys->p_clipper);
+    if( dxresult != DD_OK )
     {
-        /* Determine if the hardware supports overlay surfaces */
-        bHasOverlay = ((ddcaps.dwCaps & DDCAPS_OVERLAY) ==
-                       DDCAPS_OVERLAY) ? TRUE : FALSE;
-        /* Determine if the hardware supports colorkeying */
-        bHasColorKey = ((ddcaps.dwCaps & DDCAPS_COLORKEY) ==
-                        DDCAPS_COLORKEY) ? TRUE : FALSE;
-        /* Determine if the hardware supports scaling of the overlay surface */
-        bCanStretch = ((ddcaps.dwCaps & DDCAPS_OVERLAYSTRETCH) ==
-                       DDCAPS_OVERLAYSTRETCH) ? TRUE : FALSE;
-        intf_WarnMsg( 3, "vout: WinDX Caps: overlay=%i colorkey=%i stretch=%i",
-                         bHasOverlay, bHasColorKey, bCanStretch );
-    }
+        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 );
+    }    
 
-    p_vout->p_sys->p_overlay = NULL;
-    if( bHasOverlay && bHasColorKey && bCanStretch )
-    {
-        if( !WinDXCreateYUVOverlay( p_vout ) )
-        {
-           /* Overlay created successfully */
-           p_vout->b_need_render = 0;
-        }
-    }
+    return( 0 );
+}
+
+/*****************************************************************************
+ * DirectXCreateSurface: create an YUV overlay or RGB surface for the video.
+ *****************************************************************************
+ * The best method of display is with an YUV overlay because the YUV->RGB
+ * conversion is done in hardware.
+ * You can also create a plain RGB surface.
+ * ( Maybe we could also try an RGB overlay surface, which could have hardware
+ * scaling and which would also be faster in window mode because you don't
+ * 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 )
+{
+    HRESULT dxresult;
+    LPDIRECTDRAWSURFACE p_surface;
+    DDSURFACEDESC ddsd;
 
+    intf_WarnMsg( 3, "vout: DirectXCreateSurface" );
 
-    /* Now do some initialisation for video_output */
-    if( p_vout->b_need_render )
+    /* Create the video surface */
+    if( b_overlay )
     {
-        /* if we want a valid pointer to the surface memory, we must lock
-         * the surface */
+        /* Now try to create the YUV overlay surface.
+         * This overlay will be displayed on top of the primary surface.
+         * A color key is used to determine whether or not the overlay will be
+         * displayed, ie the overlay will be displayed in place of the primary
+         * surface wherever the primary surface will have this color.
+         * The video window has been created with a background of this color so
+         * the overlay will be only displayed on top of this window */
+
         memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
         ddsd.dwSize = sizeof(DDSURFACEDESC);
-        dxresult = IDirectDrawSurface_Lock(p_vout->p_sys->p_display,
-                                           NULL, &ddsd,
-                                           DDLOCK_NOSYSLOCK, NULL);
-        if ( dxresult == DDERR_SURFACELOST )
+        ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+        ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
+        ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
+        ddsd.dwFlags = DDSD_CAPS |
+                       DDSD_HEIGHT |
+                       DDSD_WIDTH |
+                     //DDSD_BACKBUFFERCOUNT |
+                       DDSD_PIXELFORMAT;
+        ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY |
+                            //DDSCAPS_COMPLEX |
+                            //DDSCAPS_FLIP |
+                              DDSCAPS_VIDEOMEMORY;
+        ddsd.dwHeight = p_vout->render.i_height;
+        ddsd.dwWidth = p_vout->render.i_width;
+        ddsd.dwBackBufferCount = 1;                       /* One back buffer */
+
+        dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
+                                               &ddsd,
+                                               &p_surface, NULL );
+        if( dxresult == DD_OK )
         {
-            /* Your surface can be lost so be sure
-             * to check this and restore it if needed */
-            dxresult = IDirectDrawSurface_Restore( p_vout->p_sys->p_display );
-            dxresult = IDirectDrawSurface_Lock( p_vout->p_sys->p_display,
-                                                NULL, &ddsd, DDLOCK_NOSYSLOCK
-                                                | DDLOCK_WAIT, NULL);
+            intf_WarnMsg( 3,"vout: DirectX YUV overlay created successfully" );
         }
-        if( dxresult != DD_OK )
+        else
         {
-            intf_WarnMsg( 3, "vout: WinDX could not lock the surface" );
-            return( 1 );
+            intf_ErrMsg( "vout error: can't create YUV overlay surface." );
+            *pp_surface_final = NULL;
+            return 0;
         }
-
-        /* Set the pointer to the surface memory */
-        p_vout->p_sys->p_windx_buf[ 0 ] = ddsd.lpSurface;
-        /* back buffer, none for now */
-        p_vout->p_sys->p_windx_buf[ 1 ] = ddsd.lpSurface;
-
-
-        /* Set thread information */
-        p_vout->i_width =           ddsd.dwWidth;
-        p_vout->i_height =          ddsd.dwHeight;
-
-#ifdef NONAMELESSUNION
-        p_vout->i_bytes_per_line =  ddsd.u1.lPitch;
-
-        p_vout->i_screen_depth =    ddsd.ddpfPixelFormat.u1.dwRGBBitCount;
-        p_vout->i_bytes_per_pixel = ddsd.ddpfPixelFormat.u1.dwRGBBitCount/8;
-
-        p_vout->i_red_mask =        ddsd.ddpfPixelFormat.u2.dwRBitMask;
-        p_vout->i_green_mask =      ddsd.ddpfPixelFormat.u3.dwGBitMask;
-        p_vout->i_blue_mask =       ddsd.ddpfPixelFormat.u4.dwBBitMask;
-#else
-        p_vout->i_bytes_per_line =  ddsd.lPitch;
-
-        p_vout->i_screen_depth =    ddsd.ddpfPixelFormat.dwRGBBitCount;
-        p_vout->i_bytes_per_pixel = ddsd.ddpfPixelFormat.dwRGBBitCount/8;
-
-        p_vout->i_red_mask =        ddsd.ddpfPixelFormat.dwRBitMask;
-        p_vout->i_green_mask =      ddsd.ddpfPixelFormat.dwGBitMask;
-        p_vout->i_blue_mask =       ddsd.ddpfPixelFormat.dwBBitMask;
-
-#endif /* NONAMELESSUNION */
-
-        /* Unlock the Surface */
-        dxresult = IDirectDrawSurface_Unlock(p_vout->p_sys->p_display,
-                                             ddsd.lpSurface );
-        /* FIXME: palette in 8bpp ?? */
-        /* Set and initialize buffers */
-        p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_windx_buf[ 0 ],
-                                 p_vout->p_sys->p_windx_buf[ 1 ] );
     }
-    else
+
+    if( !b_overlay )
     {
-        /* Lock the surface */
-        memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
+        /* Now try to create a plain RGB surface. */
+        memset( &ddsd, 0, sizeof( DDSURFACEDESC ) );
         ddsd.dwSize = sizeof(DDSURFACEDESC);
-        dxresult = IDirectDrawSurface_Lock(p_vout->p_sys->p_overlay,
-                                          NULL, &ddsd, DDLOCK_NOSYSLOCK, NULL);
-        if ( dxresult == DDERR_SURFACELOST )
+        ddsd.dwFlags = DDSD_HEIGHT |
+                       DDSD_WIDTH |
+                       DDSD_CAPS;
+        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
+                              DDSCAPS_SYSTEMMEMORY;
+        ddsd.dwHeight = p_vout->render.i_height;
+        ddsd.dwWidth = p_vout->render.i_width;
+
+        dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
+                                               &ddsd,
+                                               &p_surface, NULL );
+        if( dxresult == DD_OK )
         {
-            /* Your surface can be lost (thanks to windows) so be sure
-             * to check this every time you want to do something with
-             * it */
-            dxresult = IDirectDrawSurface_Restore(
-                                           p_vout->p_sys->p_overlay );
-            dxresult = IDirectDrawSurface_Lock( p_vout->p_sys->p_overlay
-                        , NULL, &ddsd,DDLOCK_NOSYSLOCK| DDLOCK_WAIT, NULL);
+            intf_WarnMsg( 3,"vout: DirectX RGB surface created successfully" );
         }
-        if( dxresult != DD_OK )
+        else
         {
-            intf_WarnMsg( 3, "vout: WinDX could not lock the surface" );
-            return( 1 );
+            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,
+                                     (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." );
+        *pp_surface_final = NULL;
+        return 0;
+    }
 
-        p_vout->p_sys->p_windx_buf[ 0 ] = ddsd.lpSurface;
-        p_vout->p_sys->p_windx_buf[ 1 ] = ddsd.lpSurface;
+    return 1;
+}
 
-        /* Set thread information */
-        p_vout->i_width =           ddsd.dwWidth;
-        p_vout->i_height =          ddsd.dwHeight;
-#ifdef NONAMELESSUNION
-        p_vout->i_bytes_per_line =  ddsd.u1.lPitch;
-#else
-        p_vout->i_bytes_per_line =  ddsd.lPitch;
-#endif /* NONAMELESSUNION */
 
-        /* Unlock the Surface */
-        dxresult = IDirectDrawSurface_Unlock(p_vout->p_sys->p_overlay,
-                                             ddsd.lpSurface );
+/*****************************************************************************
+ * DirectXUpdateOverlay: Move or resize overlay surface on video display.
+ *****************************************************************************
+ * This function is used to move or resize an overlay surface on the screen.
+ * Ususally the overlay is moved by the user and thus, by a move or resize
+ * event (in vout_Manage).
+ *****************************************************************************/
+void DirectXUpdateOverlay( vout_thread_t *p_vout )
+{
+    DDOVERLAYFX     ddofx;
+    DWORD           dwFlags;
+    HRESULT         dxresult;
 
-        p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_windx_buf[ 0 ],
-                                 p_vout->p_sys->p_windx_buf[ 1 ] );
+    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 */
+
+    /* Position and show the overlay */
+    memset(&ddofx, 0, sizeof(DDOVERLAYFX));
+    ddofx.dwSize = sizeof(DDOVERLAYFX);
+    ddofx.dckDestColorkey.dwColorSpaceLowValue = p_vout->p_sys->i_colorkey;
+    ddofx.dckDestColorkey.dwColorSpaceHighValue = p_vout->p_sys->i_colorkey;
+
+    dwFlags = DDOVER_SHOW;
+    if( !p_vout->p_sys->b_caps_overlay_clipping )
+        dwFlags |= DDOVER_KEYDESTOVERRIDE;
+
+    dxresult = IDirectDrawSurface3_UpdateOverlay(
+                                         p_vout->p_sys->p_current_surface,
+                                         &p_vout->p_sys->rect_src_clipped,
+                                         p_vout->p_sys->p_display,
+                                         &p_vout->p_sys->rect_dest_clipped,
+                                         dwFlags,
+                                         &ddofx );
+    if(dxresult != DD_OK)
+    {
+        intf_WarnMsg( 3,
+          "vout: DirectXUpdateOverlay can't move or resize overlay" );
     }
 
-    return( 0 );
 }
 
 /*****************************************************************************
- * WinDXCreateYUVOveraly: create an YUV overlay surface for the video.
+ * DirectXCloseDDraw: Release the DDraw object allocated by DirectXInitDDraw
  *****************************************************************************
- * The best method of display is with an YUV overlay because the YUV->RGB
- * conversion is done in hardware.
- * This function will try to create an YUV overlay.
+ * This function returns all resources allocated by DirectXInitDDraw.
  *****************************************************************************/
-static int WinDXCreateYUVOverlay( vout_thread_t *p_vout )
+static void DirectXCloseDDraw( vout_thread_t *p_vout )
 {
-    HRESULT dxresult;
-    DDSURFACEDESC ddsd;
+    intf_WarnMsg(3, "vout: DirectXCloseDDraw" );
+    if( p_vout->p_sys->p_ddobject != NULL )
+    {
+        IDirectDraw2_Release(p_vout->p_sys->p_ddobject);
+        p_vout->p_sys->p_ddobject = NULL;
+    }
 
-    /* Now create the overlay surface. This overlay will be displayed on
-     * top of the primary surface.
-     * A color key is used to determine whether or not the overlay will be
-     * displayed, ie the overlay will be displayed in place of the primary
-     * surface wherever the primary surface will have this color.
-     * The video window has been created with a background of this color so
-     * the overlay will be only displayed on top of this window */
+    if( p_vout->p_sys->hddraw_dll != NULL )
+    {
+        FreeLibrary( p_vout->p_sys->hddraw_dll );
+        p_vout->p_sys->hddraw_dll = NULL;
+    }
+}
 
-    memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
-    ddsd.dwSize = sizeof(DDSURFACEDESC);
-    ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-    ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
-    ddsd.ddpfPixelFormat.dwFourCC = mmioFOURCC('Y','V','1','2');
-#ifdef NONAMELESSUNION
-    ddsd.ddpfPixelFormat.u1.dwYUVBitCount = 16;
-#else
-    ddsd.ddpfPixelFormat.dwYUVBitCount = 16;
-#endif
+/*****************************************************************************
+ * DirectXCloseDisplay: close and reset the DirectX display device
+ *****************************************************************************
+ * This function returns all resources allocated by DirectXCreateDisplay.
+ *****************************************************************************/
+static void DirectXCloseDisplay( vout_thread_t *p_vout )
+{
+    intf_WarnMsg( 3, "vout: DirectXCloseDisplay" );
 
-    ddsd.dwSize = sizeof(DDSURFACEDESC);
-    ddsd.dwFlags = DDSD_CAPS |
-                   DDSD_HEIGHT |
-                   DDSD_WIDTH |
-                   DDSD_PIXELFORMAT;
-    ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
-    ddsd.dwHeight =  p_vout->p_sys->i_image_height;
-    ddsd.dwWidth =  p_vout->p_sys->i_image_width;
-
-    dxresult = IDirectDraw_CreateSurface( p_vout->p_sys->p_ddobject,
-                                          &ddsd,
-                                          &p_vout->p_sys->p_overlay, NULL );
-    if( dxresult != DD_OK )
+    if( p_vout->p_sys->p_clipper != NULL )
     {
-        intf_ErrMsg( "vout error: can't create overlay surface." );
-        p_vout->p_sys->p_overlay = NULL;
+        intf_WarnMsg( 3, "vout: DirectXCloseDisplay clipper" );
+        IDirectDraw2_Release( p_vout->p_sys->p_clipper );
+        p_vout->p_sys->p_clipper = NULL;
     }
-    else
+
+    if( p_vout->p_sys->p_display != NULL )
     {
-        intf_WarnMsg( 3, "vout: WinDX YUV overlay created successfully" );
+        intf_WarnMsg( 3, "vout: DirectXCloseDisplay display" );
+        IDirectDraw2_Release( p_vout->p_sys->p_display );
+        p_vout->p_sys->p_display = NULL;
     }
-    /* Hide the overlay for now */
-    IDirectDrawSurface_UpdateOverlay(p_vout->p_sys->p_overlay,
-                                     NULL,
-                                     p_vout->p_sys->p_display,
-                                     NULL,
-                                     DDOVER_HIDE,
-                                     NULL);
-
-    return ( 0 );
 }
 
 /*****************************************************************************
- * WinDXUpdateOverlay: Move or resize overlay surface on video display.
+ * DirectXCloseSurface: close the YUV overlay or RGB surface.
  *****************************************************************************
- * This function is used to move or resize an overlay surface on the screen.
- * Ususally the overlay is moved by the user and thus, by a move or resize
- * event (in vout_Manage).
+ * This function returns all resources allocated for the surface.
  *****************************************************************************/
-static int WinDXUpdateOverlay( vout_thread_t *p_vout )
+static void DirectXCloseSurface( vout_thread_t *p_vout,
+                                 LPDIRECTDRAWSURFACE3 p_surface )
 {
-    DDOVERLAYFX     ddofx;
-    RECT            rect_window, rect_image;
-    POINT           point_window;
-    DWORD           dwFlags;
-    HRESULT         dxresult;
-    DWORD           dw_colorkey;
-    DDPIXELFORMAT   pixel_format;
-
-    if( p_vout->p_sys->p_overlay == NULL || p_vout->b_need_render)
+    intf_WarnMsg( 3, "vout: DirectXCloseSurface" );
+    if( p_surface != NULL )
     {
-        intf_WarnMsg( 3, "vout: WinDX no overlay !!" );
-        return( 0 );
+        IDirectDraw2_Release( p_surface );
     }
+}
 
-    if( !p_vout->p_sys->b_display_enabled )
+/*****************************************************************************
+ * NewPictureVec: allocate a vector of identical pictures
+ *****************************************************************************
+ * Returns 0 on success, -1 otherwise
+ *****************************************************************************/
+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( )
     {
-        return( 0 );
+        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 );
     }
+#endif
 
+    intf_WarnMsg( 3, "vout: NewPictureVec" );
 
-    /* Now get the coordinates of the window. We don't actually want the
-     * window coordinates but these of the usable surface inside the window.
-     * By specification GetClientRect will always set rect_window.left and
-     * rect_window.top to 0 because the Client area is always relative to the
-     * container window */
-    GetClientRect(p_vout->p_sys->hwnd, &rect_window);
-
-    point_window.x = 0;
-    point_window.y = 0;
-    ClientToScreen(p_vout->p_sys->hwnd, &point_window);
-    rect_window.left = point_window.x;
-    rect_window.top = point_window.y;
+    I_OUTPUTPICTURES = 0;
 
-    point_window.x = rect_window.right;
-    point_window.y = rect_window.bottom;
-    ClientToScreen(p_vout->p_sys->hwnd, &point_window);
-    rect_window.right = point_window.x;
-    rect_window.bottom = point_window.y;
+    /* 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
 
-    /* We want to keep the aspect ratio of the video */
-    if( p_vout->b_scale )
+    /* 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. */
+    if( p_vout->p_sys->b_using_overlay )
     {
-        switch( p_vout->p_rendered_pic->i_aspect_ratio )
+        if( DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma,
+                                  p_vout->p_sys->b_using_overlay ) )
         {
-            case AR_16_9_PICTURE:
-            if( ((rect_window.right-rect_window.left)*9)
-                > ((rect_window.bottom-rect_window.top)*16) )
-            {
-                int temp;
-                temp = (rect_window.bottom-rect_window.top)*16/9;
-                temp = (rect_window.right-rect_window.left) - temp;
-                rect_window.left += (temp/2);
-                rect_window.right -= (temp/2);
-            }
-            else
-            {
-                int temp;
-                temp = (rect_window.right-rect_window.left)*9/16;
-                temp = (rect_window.bottom-rect_window.top) - temp;
-                rect_window.top += (temp/2);
-                rect_window.bottom -= (temp/2);
-            }
-            break;
+            DDSCAPS dds_caps;
 
-            case AR_221_1_PICTURE:
-            if( ((rect_window.right-rect_window.left)*100)
-                > ((rect_window.bottom-rect_window.top)*221) )
-            {
-                int temp;
-                temp = (rect_window.bottom-rect_window.top)*221/100;
-                temp = (rect_window.right-rect_window.left) - temp;
-                rect_window.left += (temp/2);
-                rect_window.right -= (temp/2);
-            }
-            else
+            /* Allocate internal structure */
+            p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
+            if( p_pic[0].p_sys == NULL )
             {
-                int temp;
-                temp = (rect_window.right-rect_window.left)*100/221;
-                temp = (rect_window.bottom-rect_window.top) - temp;
-                rect_window.top += (temp/2);
-                rect_window.bottom -= (temp/2);
+                DirectXCloseSurface( p_vout, p_surface );
+                return -1;
             }
-            break;
 
-            case AR_SQUARE_PICTURE:
-            if( (rect_window.right-rect_window.left)
-                > (rect_window.bottom-rect_window.top) )
-            {
-                int temp;
-                temp = (rect_window.bottom-rect_window.top);
-                temp = (rect_window.right-rect_window.left) - temp;
-                rect_window.left += (temp/2);
-                rect_window.right -= (temp/2);
-            }
-            else
-            {
-                int temp;
-                temp = (rect_window.right-rect_window.left);
-                temp = (rect_window.bottom-rect_window.top) - temp;
-                rect_window.top += (temp/2);
-                rect_window.bottom -= (temp/2);
-            }
-            break;
+            /* set front buffer */
+            p_pic[0].p_sys->p_front_surface = p_surface;
 
-            case AR_3_4_PICTURE:
-            default:
-            if( ((rect_window.right-rect_window.left)*3)
-                > ((rect_window.bottom-rect_window.top)*4) )
+            /* Get the back buffer */
+            memset( &dds_caps, 0, sizeof( DDSCAPS ));
+            dds_caps.dwCaps = DDSCAPS_BACKBUFFER;
+            if( DD_OK != IDirectDrawSurface3_GetAttachedSurface(
+                                                p_surface, &dds_caps,
+                                                &p_pic[0].p_sys->p_surface ) )
             {
-                int temp;
-                temp = (rect_window.bottom-rect_window.top)*4/3;
-                temp = (rect_window.right-rect_window.left) - temp;
-                rect_window.left += (temp/2);
-                rect_window.right -= (temp/2);
+                intf_WarnMsg( 3, "vout: NewPictureVec couldn't get "
+                              "back buffer" );
+                /* front buffer is the same as back buffer */
+                p_pic[0].p_sys->p_surface = p_surface;
             }
-            else
-            {
-                int temp;
-                temp = (rect_window.right-rect_window.left)*3/4;
-                temp = (rect_window.bottom-rect_window.top) - temp;
-                rect_window.top += (temp/2);
-                rect_window.bottom -= (temp/2);
-            }
-            break;
+
+
+            p_vout->p_sys->p_current_surface= p_pic[0].p_sys->p_front_surface;
+            DirectXUpdateOverlay( p_vout );
+            I_OUTPUTPICTURES = 1;
         }
+        else p_vout->p_sys->b_using_overlay = 0;
     }
 
+    /* As we can't have overlays, we'll 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 */
+    if( !p_vout->p_sys->b_using_overlay )
+    {
+        /* FixMe */
+        p_vout->output.i_chroma = FOURCC_RV16;
+        p_vout->output.i_rmask  = 0x001f;
+        p_vout->output.i_gmask  = 0x03e0;
+        p_vout->output.i_bmask  = 0x7c00;
 
-    /* It seems we can't feed the UpdateOverlay directdraw function with
-     * negative values so we have to clip the computed rectangles */
-    /* FIXME */
+        for( i = 0; i < i_num_pics; i++ )
+        {
+            if( DirectXCreateSurface( p_vout, &p_surface,
+                                      p_vout->output.i_chroma,
+                                      p_vout->p_sys->b_using_overlay ) )
+            {
+                /* Allocate internal structure */
+                p_pic[i].p_sys = malloc( sizeof( picture_sys_t ) );
+                if( p_pic[i].p_sys == NULL )
+                {
+                    DirectXCloseSurface( p_vout, p_surface );
+                    FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
+                    I_OUTPUTPICTURES = 0;
+                    return -1;
+                }
+                p_pic[i].p_sys->p_surface = p_surface;
+                p_pic[i].p_sys->p_front_surface = NULL;
+                I_OUTPUTPICTURES++;
 
+            }
+            else break;
+        }
+    }
 
-    /* compute the colorkey pixel value from the RGB value we've got */
-    memset( &pixel_format, 0, sizeof( DDPIXELFORMAT ));
-    pixel_format.dwSize = sizeof( DDPIXELFORMAT );
-    dxresult = IDirectDrawSurface_GetPixelFormat( p_vout->p_sys->p_display,
-                                                  &pixel_format );
-    if( dxresult != DD_OK )
-        intf_WarnMsg( 3, "vout: WinDX GetPixelFormat failed !!" );
-    dw_colorkey = (DWORD)p_vout->p_sys->i_colorkey;
-#ifdef NONAMELESSUNION
-    dw_colorkey = (DWORD)((( dw_colorkey * pixel_format.u2.dwRBitMask) / 255)
-                          & pixel_format.u2.dwRBitMask);
-#else
-    dw_colorkey = (DWORD)((( dw_colorkey * pixel_format.dwRBitMask) / 255)
-                          & pixel_format.dwRBitMask);
-#endif
 
-    /* Position and show the overlay */
-    memset(&ddofx, 0, sizeof(DDOVERLAYFX));
-    ddofx.dwSize = sizeof(DDOVERLAYFX);
-    ddofx.dckDestColorkey.dwColorSpaceLowValue = dw_colorkey;
-    ddofx.dckDestColorkey.dwColorSpaceHighValue = dw_colorkey;
+    /* Now that we've got all our direct-buffers, we can finish filling in the
+     * picture_t structures */
+    for( i = 0; i < I_OUTPUTPICTURES; i++ )
+    {
+        p_pic[i].i_status = DESTROYED_PICTURE;
+        p_pic[i].i_type   = DIRECT_PICTURE;
+        PP_OUTPUTPICTURE[i] = &p_pic[i];
 
-    dwFlags = DDOVER_KEYDESTOVERRIDE | DDOVER_SHOW;
+        if( !DirectXGetSurfaceDesc( &p_pic[i] ) )
+        {
+            /* AAARRGG */
+            FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
+            I_OUTPUTPICTURES = 0;
+            return -1;
+        }
 
-    dxresult = IDirectDrawSurface_UpdateOverlay(p_vout->p_sys->p_overlay,
-                                                NULL,    /*&rect_image,*/
-                                                p_vout->p_sys->p_display,
-                                                &rect_window,
-                                                dwFlags,
-                                                &ddofx);
-    if(dxresult != DD_OK)
-    {
-        intf_WarnMsg( 3, "vout: WinDX can't move or resize overlay" );
+        if( !UpdatePictureStruct(p_vout, &p_pic[i], p_vout->output.i_chroma) )
+        {
+
+            /* Unknown chroma, tell the guy to get lost */
+            intf_ErrMsg( "vout error: never heard of chroma 0x%.8x (%4.4s)",
+                         p_vout->output.i_chroma,
+                         (char*)&p_vout->output.i_chroma );
+            FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
+            I_OUTPUTPICTURES = 0;
+            return -1;
+        }
     }
 
-    return ( 0 );
+    intf_WarnMsg( 3, "vout: End NewPictureVec");
+    return 0;
 }
 
 /*****************************************************************************
- * WinDXCloseWindow: close the window created by WinDXCreateWindow
+ * FreePicture: destroy a picture vector allocated with NewPictureVec
  *****************************************************************************
- * This function returns all resources allocated by WinDXCreateWindow.
+ * 
  *****************************************************************************/
-static void WinDXCloseWindow( vout_thread_t *p_vout )
+static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic,
+                            int i_num_pics )
 {
-    HINSTANCE hInstance;
+    int i;
 
-    intf_WarnMsg( 3, "vout: WinDXCloseWindow" );
-    if( p_vout->p_sys->hwnd != INVALID_HANDLE_VALUE )
+    for( i = 0; i < i_num_pics; i++ )
     {
-        DestroyWindow( p_vout->p_sys->hwnd);
-        p_vout->p_sys->hwnd = INVALID_HANDLE_VALUE;
-    }
+#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
 
-    hInstance = GetModuleHandle(NULL);
-    UnregisterClass( "VLC DirectX",                            /* class name */
-                     hInstance );          /* handle to application instance */
+        DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_surface );
 
-    /* free window background brush */
-    if( p_vout->p_sys->hwnd != INVALID_HANDLE_VALUE )
-    {
-        DeleteObject( p_vout->p_sys->hbrush );
-        p_vout->p_sys->hbrush = INVALID_HANDLE_VALUE;
+        for( i = 0; i < i_num_pics; i++ )
+        {
+            free( p_pic[i].p_sys );
+        }
     }
 }
 
 /*****************************************************************************
- * WinDXCloseDDraw: Release the DDraw object allocated by WinDXInitDDraw
+ * UpdatePictureStruct: updates the internal data in the picture_t structure
  *****************************************************************************
- * This function returns all resources allocated by WinDXInitDDraw.
+ * This will setup stuff for use by the video_output thread
  *****************************************************************************/
-static void WinDXCloseDDraw( vout_thread_t *p_vout )
+static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic,
+                                int i_chroma )
 {
-    intf_WarnMsg(3, "vout: WinDXCloseDDraw" );
-    if( p_vout->p_sys->p_ddobject != NULL )
+
+    switch( p_vout->output.i_chroma )
     {
-        IDirectDraw_Release(p_vout->p_sys->p_ddobject);
-        p_vout->p_sys->p_ddobject = NULL;
+
+        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].b_margin = 0;
+
+            p_pic->V_PIXELS =  p_pic->Y_PIXELS
+              + p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_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[Y_PLANE].i_pitch / 2;
+            p_pic->p[V_PLANE].i_pixel_bytes = 1;
+            p_pic->p[V_PLANE].b_margin = 0;
+
+            p_pic->U_PIXELS = p_pic->V_PIXELS
+              + p_pic->p[V_PLANE].i_lines * p_pic->p[V_PLANE].i_pitch;
+            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].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->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->i_planes = 1;
+            break;
+
+        case FOURCC_I420:
+
+            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].b_margin = 0;
+
+            p_pic->U_PIXELS = p_pic->Y_PIXELS
+              + p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch;
+            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].b_margin = 0;
+
+            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[Y_PLANE].i_pitch / 2;
+            p_pic->p[V_PLANE].i_pixel_bytes = 1;
+            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->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->i_planes = 1;
+            break;
+#endif
+
+        default:
+            /* Not supported */
+            return 0;
+
     }
+
+    return 1;
 }
 
 /*****************************************************************************
- * WinDXCloseDisplay: close and reset DirectX device
+ * DirectXGetDDrawCaps: Probe the capabilities of the hardware
  *****************************************************************************
- * This function returns all resources allocated by WinDXCreateDisplay and
- * restore the original state of the device.
+ * It is nice to know which features are supported by the hardware so we can
+ * find ways to optimize our rendering.
  *****************************************************************************/
-static void WinDXCloseDisplay( vout_thread_t *p_vout )
+static void DirectXGetDDrawCaps( vout_thread_t *p_vout )
 {
-    intf_WarnMsg( 3, "vout: WinDXCloseDisplay" );
-    if( p_vout->p_sys->p_display != NULL )
+    DDCAPS ddcaps;
+    HRESULT dxresult;
+
+    /* This is just an indication of whether or not we'll support overlay,
+     * but with this test we don't know if we support YUV overlay */
+    memset( &ddcaps, 0, sizeof( DDCAPS ));
+    ddcaps.dwSize = sizeof(DDCAPS);
+    dxresult = IDirectDraw2_GetCaps( p_vout->p_sys->p_ddobject,
+                                     &ddcaps, NULL );
+    if(dxresult != DD_OK )
     {
-        if( p_vout->p_sys->p_overlay != NULL )
-        {
-            intf_WarnMsg( 3, "vout: WinDXCloseDisplay overlay" );
-            IDirectDraw_Release( p_vout->p_sys->p_overlay );
-            p_vout->p_sys->p_overlay = NULL;
-        }
+        intf_WarnMsg( 3,"vout error: can't get caps." );
+    }
+    else
+    {
+        BOOL bHasOverlay, bHasOverlayFourCC, bCanClipOverlay,
+             bHasColorKey, bCanStretch;
 
-        if( p_vout->p_sys->p_clipper != NULL )
-        {
-            intf_WarnMsg( 3, "vout: WinDXCloseDisplay clipper" );
-            IDirectDraw_Release( p_vout->p_sys->p_clipper );
-            p_vout->p_sys->p_clipper = NULL;
-        }
+        /* Determine if the hardware supports overlay surfaces */
+        bHasOverlay = ((ddcaps.dwCaps & DDCAPS_OVERLAY) ==
+                       DDCAPS_OVERLAY) ? TRUE : FALSE;
+        /* Determine if the hardware supports overlay surfaces */
+        bHasOverlayFourCC = ((ddcaps.dwCaps & DDCAPS_OVERLAYFOURCC) ==
+                       DDCAPS_OVERLAYFOURCC) ? TRUE : FALSE;
+        /* Determine if the hardware supports overlay surfaces */
+        bCanClipOverlay = ((ddcaps.dwCaps & DDCAPS_OVERLAYCANTCLIP) ==
+                       0 ) ? TRUE : FALSE;
+        /* Determine if the hardware supports colorkeying */
+        bHasColorKey = ((ddcaps.dwCaps & DDCAPS_COLORKEY) ==
+                        DDCAPS_COLORKEY) ? TRUE : FALSE;
+        /* Determine if the hardware supports scaling of the overlay surface */
+        bCanStretch = ((ddcaps.dwCaps & DDCAPS_OVERLAYSTRETCH) ==
+                       DDCAPS_OVERLAYSTRETCH) ? TRUE : FALSE;
+        intf_WarnMsg( 3, "vout: DirectDraw Capabilities:" );
+        intf_WarnMsg( 3, "       overlay=%i yuvoverlay=%i can_clip_overlay=%i "
+                         "colorkey=%i stretch=%i",
+                      bHasOverlay, bHasOverlayFourCC, bCanClipOverlay,
+                      bHasColorKey, bCanStretch );
+
+        /* Overlay clipping support is interesting for us as it means we can
+         * get rid of the colorkey alltogether */
+        p_vout->p_sys->b_caps_overlay_clipping = bCanClipOverlay;
 
-        intf_WarnMsg( 3, "vout: WinDXCloseDisplay display" );
-        IDirectDraw_Release( p_vout->p_sys->p_display );
-        p_vout->p_sys->p_display = NULL;
     }
 }
 
 /*****************************************************************************
- * WinDXCloseYUVOverlay: close the overlay surface
+ * DirectXGetSurfaceDesc: Get some more information about the surface
  *****************************************************************************
- * This function returns all resources allocated by the overlay surface.
- * We also call this function when the decoded picture change its dimensions
- * (in that case we close the overlay surface and reopen another with the
- * right dimensions).
+ * This function get and stores the surface descriptor which among things
+ * has the pointer to the picture data.
  *****************************************************************************/
-static void WinDXCloseYUVOverlay( vout_thread_t *p_vout )
+static int DirectXGetSurfaceDesc( picture_t *p_pic )
 {
-    intf_WarnMsg( 3, "vout: WinDXCloseYUVOverlay" );
-    if( p_vout->p_sys->p_overlay != NULL )
+    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,
+                                         NULL, &p_pic->p_sys->ddsd,
+                                         DDLOCK_NOSYSLOCK,
+                                         NULL );
+    if ( dxresult == DDERR_SURFACELOST )
+    {
+        /* 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,
+                                             &p_pic->p_sys->ddsd,
+                                             DDLOCK_NOSYSLOCK | DDLOCK_WAIT,
+                                             NULL);
+    }
+    if( dxresult != DD_OK )
     {
-        IDirectDraw_Release( p_vout->p_sys->p_overlay );
-        p_vout->p_sys->p_overlay = NULL;
+        intf_ErrMsg( "vout: DirectXGetSurfaceDesc can't lock surface" );
+        return 0;
     }
-    p_vout->p_sys->b_display_enabled = 0;
+
+    /* Unlock the Surface */
+    dxresult = IDirectDrawSurface3_Unlock( p_pic->p_sys->p_surface, NULL );
+
+    return 1;
 }