]> git.sesse.net Git - vlc/commitdiff
* major rewrite of the directx video plugin to adapt it to the new vout4
authorGildas Bazin <gbazin@videolan.org>
Thu, 17 Jan 2002 23:02:45 +0000 (23:02 +0000)
committerGildas Bazin <gbazin@videolan.org>
Thu, 17 Jan 2002 23:02:45 +0000 (23:02 +0000)
    architecture. This plugin has also been through a major clean-up
    and it is now much more robust and optimized.

* Fixed a few problems with the win32 build.

* Replaced the "overlay" command line option with "nooverlay". The
    former was confusing and useless because overlays were used by
    default anyway.

include/config.h
plugins/directx/aout_directx.c
plugins/directx/directx.c
plugins/directx/vout_directx.c
plugins/directx/vout_directx.h
plugins/directx/vout_events.c
plugins/gtk/gtk_playlist.c
plugins/qnx/vout_qnx.c
src/interface/main.c
src/video_output/vout_pictures.c

index 6190004f1ddfed4dbe3f0f2fc3787ffcfb2edcad..7425d09461e2ff0211d64431d04f56c8ddcc3265 100644 (file)
 #define VOUT_FULLSCREEN_DEFAULT         0
 
 /* Environment variable for overlay mode, and default value */
-#define VOUT_OVERLAY_VAR                "vlc_overlay"
-#define VOUT_OVERLAY_DEFAULT            0
+#define VOUT_NOOVERLAY_VAR              "vlc_nooverlay"
+#define VOUT_NOOVERLAY_DEFAULT          0
 
 /* Default gamma */
 #define VOUT_GAMMA_VAR                  "vlc_gamma"
index 37d28f661c7db4b73dea5fcfb9e7aa973a728f7f..e5a26139cb4cb6c6a9f8d52c82a404b4e58a34ad 100644 (file)
@@ -2,7 +2,7 @@
  * aout_directx.c: Windows DirectX audio output method
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: aout_directx.c,v 1.14 2001/12/30 07:09:54 sam Exp $
+ * $Id: aout_directx.c,v 1.15 2002/01/17 23:02:45 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
 
 #include "audio_output.h"                                   /* aout_thread_t */
 
+/*****************************************************************************
+ * DirectSound GUIDs.
+ * Defining them here allows us to get rid of the dxguid library during
+ * the linking stage.
+ *****************************************************************************/
+#include <initguid.h>
+DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
+
 /*****************************************************************************
  * aout_sys_t: directx audio output method descriptor
  *****************************************************************************
@@ -120,10 +128,6 @@ void _M( aout_getfunctions )( function_list_t * p_function_list )
 static int aout_Probe( probedata_t *p_data )
 {
     /* For now just assume the computer has a sound device */
-    if( TestMethod( AOUT_METHOD_VAR, "directx" ) )
-    {
-        return( 999 );
-    }
     return( 1 );
 }
 
index 8678229489abe1c535597723eea81477e4e5759e..c2cce42edfde1d3dde25da168038702b2a2f1a04 100644 (file)
@@ -2,7 +2,7 @@
  * directx.c : Windows DirectX plugin for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: directx.c,v 1.4 2001/12/30 07:09:54 sam Exp $
+ * $Id: directx.c,v 1.5 2002/01/17 23:02:45 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *      
@@ -44,15 +44,15 @@ void _M( vout_getfunctions )( function_list_t * p_function_list );
  * Building configuration tree
  *****************************************************************************/
 MODULE_CONFIG_START
-ADD_WINDOW( "Configuration for Windows DirectX module" )
+    ADD_WINDOW( "Configuration for Windows DirectX module" )
     ADD_COMMENT( "For now, the Windows DirectX module cannot be configured" )
 MODULE_CONFIG_STOP
 
 MODULE_INIT_START
-    p_module->i_capabilities = MODULE_CAPABILITY_NULL
-                               | MODULE_CAPABILITY_VOUT
-                               | MODULE_CAPABILITY_AOUT;
-    p_module->psz_longname = "DirectX module";
+    SET_DESCRIPTION( "DirectX extension module" )
+    ADD_CAPABILITY( AOUT, 150 )
+    ADD_CAPABILITY( VOUT, 150 )
+    ADD_SHORTCUT( "directx" )
 MODULE_INIT_STOP
 
 MODULE_ACTIVATE_START
@@ -62,4 +62,3 @@ MODULE_ACTIVATE_STOP
 
 MODULE_DEACTIVATE_START
 MODULE_DEACTIVATE_STOP
-
index 5766f204cc931a1c5af16c4545b6f89540050fdb..fbda1e8bee83e1bb24e0a5b8f4e6d7bce67c2034 100644 (file)
@@ -2,7 +2,7 @@
  * vout_directx.c: Windows DirectX video output display method
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: vout_directx.c,v 1.18 2002/01/04 14:01:34 sam Exp $
+ * $Id: vout_directx.c,v 1.19 2002/01/17 23:02:45 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
-/* ToDo:
- *
- * Double buffering
- *
- * Port this plugin to Video Output IV
- */
-
 /*****************************************************************************
  * Preamble:
  *
  * 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 the plugin will use an RGB offscreen video
- * surface that will be blitted onto the primary surface (display) to
- * effectively display the picture. this fallback method enables us to display
+ * 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 yet) would be to use the
- * primary surface as the video buffer. This would allow for better
- * performance but this is restricted to fullscreen video. In short,
- * implementing this is not considered high priority.
+ * 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 <errno.h>                                                 /* ENOMEM */
 #include <windows.h>
 #include <windowsx.h>
 
-#if defined( _MSC_VER )
-#   include <ddraw.h>
-#else
-#   include <directx.h>
-#endif
+#include <ddraw.h>
 
 #include "netutils.h"
 
 
 #include "vout_directx.h"
 
+/*****************************************************************************
+ * DirectDraw GUIDs.
+ * Defining them here allows us to get rid of the dxguid library during
+ * the linking stage.
+ *****************************************************************************/
+#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  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 int  DirectXCreateDisplay  ( vout_thread_t *p_vout );
-static int  DirectXCreateSurface  ( vout_thread_t *p_vout );
-static int  DirectXCreateClipper  ( vout_thread_t *p_vout );
-static int  DirectXUpdateOverlay  ( 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 void DirectXCloseSurface   ( vout_thread_t *p_vout );
-static void DirectXKeepAspectRatio( vout_thread_t *p_vout, RECT *coordinates );
+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
@@ -104,8 +108,8 @@ void _M( vout_getfunctions )( function_list_t * p_function_list )
     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;
 }
 
 /*****************************************************************************
@@ -117,11 +121,6 @@ void _M( vout_getfunctions )( function_list_t * p_function_list )
 static int vout_Probe( probedata_t *p_data )
 {
 
-    if( TestMethod( VOUT_METHOD_VAR, "directx" ) )
-    {
-        return( 999 );
-    }
-
     /* Check that at least DirectX5 is installed on the computer */
     /* Fixme */
 
@@ -146,37 +145,44 @@ 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_surface = NULL;
+    p_vout->p_sys->p_current_surface = NULL;
     p_vout->p_sys->p_clipper = NULL;
     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_display_enabled = 0;
+    p_vout->p_sys->b_caps_overlay_clipping = 0;
+    SetRectEmpty( &p_vout->p_sys->rect_display );
+    p_vout->p_sys->b_using_overlay =
+        !main_GetIntVariable( VOUT_NOOVERLAY_VAR, VOUT_NOOVERLAY_DEFAULT );
 
-    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->i_lastmoved = mdate();
 
-    p_vout->b_fullscreen = main_GetIntVariable( VOUT_FULLSCREEN_VAR,
-                                                VOUT_FULLSCREEN_DEFAULT );
+    /* Set main window's size */
+    if( p_vout->render.i_height * p_vout->render.i_aspect
+        >= p_vout->render.i_width * VOUT_ASPECT_FACTOR )
+    {
+        p_vout->p_sys->i_window_width = p_vout->render.i_height
+          * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
+        p_vout->p_sys->i_window_height = p_vout->render.i_height;
+    }
+    else
+    {
+        p_vout->p_sys->i_window_width = p_vout->render.i_width;
+        p_vout->p_sys->i_window_height = p_vout->render.i_width
+          * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
+    }
+
 #if 0
-    p_vout->b_need_render = !main_GetIntVariable( VOUT_OVERLAY_VAR,
-                                                  VOUT_OVERLAY_DEFAULT );
-#else
-    p_vout->b_need_render = 0;                          /* default = overlay */
-#endif
     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;
+#endif
 
     /* 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 );
@@ -215,8 +221,8 @@ static int vout_Create( vout_thread_t *p_vout )
         return( 1 );
     }
 
+    intf_WarnMsg( 3, "vout: vout_Create DirectXEventThread running" );
 
-    intf_WarnMsg( 3, "vout : vout_Create DirectXEventThread running" );
 
     /* Initialise DirectDraw */
     if( DirectXInitDDraw( p_vout ) )
@@ -249,16 +255,36 @@ static int vout_Create( vout_thread_t *p_vout )
         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 );
+
     return( 0 );
 }
 
@@ -270,6 +296,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;
 }
 
@@ -304,13 +331,12 @@ static void vout_Destroy( vout_thread_t *p_vout )
 /*****************************************************************************
  * 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 )
 {
     WINDOWPLACEMENT window_placement;
-    extern int b_directx_update_overlay;
 
     /* 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
@@ -324,11 +350,10 @@ static int vout_Manage( vout_thread_t *p_vout )
         || p_vout->p_sys->i_changes & VOUT_SCALE_CHANGE)
     {
         intf_WarnMsg( 3, "vout: vout_Manage Scale Change" );
-        if( p_vout->b_need_render )
+        if( !p_vout->p_sys->b_using_overlay )
             InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE );
-        if( DirectXUpdateOverlay( p_vout ) )
-            /* failed so try again next time */
-            PostMessage( p_vout->p_sys->hwnd, WM_CHAR, (WPARAM)'S', 0);
+        else
+          DirectXUpdateOverlay( p_vout );
         p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
         p_vout->p_sys->i_changes &= ~VOUT_SCALE_CHANGE;
     }
@@ -337,45 +362,15 @@ static int vout_Manage( vout_thread_t *p_vout )
      * Size Change 
      */
     if( p_vout->i_changes & VOUT_SIZE_CHANGE
-        || p_vout->p_sys->i_changes & VOUT_SIZE_CHANGE
-        || b_directx_update_overlay )
+        || p_vout->p_sys->i_changes & VOUT_SIZE_CHANGE )
     {
         intf_WarnMsg( 3, "vout: vout_Manage Size Change" );
-        if( DirectXUpdateOverlay( p_vout ) )
-            /* failed so try again next time */
-            PostMessage( p_vout->p_sys->hwnd, WM_APP, 0, 0);
+        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;
-        b_directx_update_overlay = 0;
-    }
-
-    /*
-     * YUV Change 
-     */
-    if( p_vout->i_changes & VOUT_YUV_CHANGE
-        || p_vout->p_sys->i_changes & VOUT_YUV_CHANGE )
-    {
-        p_vout->b_need_render = ! p_vout->b_need_render;
-        
-        /* Need to reopen display */
-        DirectXCloseSurface( p_vout );
-        if( DirectXCreateSurface( p_vout ) )
-        {
-          intf_ErrMsg( "error: can't reopen display after YUV change" );
-          return( 1 );
-        }
-
-        /* Repaint the window background (needed by the overlay surface) */
-        if( !p_vout->b_need_render )
-        {
-            InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE );
-            p_vout->p_sys->b_display_enabled = 1;
-            if( DirectXUpdateOverlay( p_vout ) )
-                /* failed so try again next time */
-                PostMessage( p_vout->p_sys->hwnd, WM_APP, 0, 0);
-        }
-        p_vout->i_changes &= ~VOUT_YUV_CHANGE;
-        p_vout->p_sys->i_changes &= ~VOUT_YUV_CHANGE;
     }
 
     /*
@@ -423,6 +418,7 @@ static int vout_Manage( vout_thread_t *p_vout )
         ShowCursor( FALSE );
     }
 
+#if 0
     if( p_vout->i_changes & VOUT_CURSOR_CHANGE
         || p_vout->p_sys->i_changes & VOUT_CURSOR_CHANGE )
     {
@@ -434,38 +430,34 @@ static int vout_Manage( vout_thread_t *p_vout )
         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;
+    HRESULT dxresult;
 
-    int           i;
-    int           i_image_width;
-    int           i_image_height;
+    intf_WarnMsg( 8, "vout: vout_Display" );
 
     if( (p_vout->p_sys->p_display == NULL) )
     {
@@ -473,77 +465,19 @@ static void vout_Display( vout_thread_t *p_vout )
         return;
     }
 
-    /* if the size of the decoded pictures has changed then we close the
-     * video surface (which doesn't have the right size anymore). */
-    i_image_width = ( p_vout->p_rendered_pic ) ?
-      p_vout->p_rendered_pic->i_width : p_vout->p_sys->i_image_width;
-    i_image_height = ( p_vout->p_rendered_pic ) ?
-      p_vout->p_rendered_pic->i_height : p_vout->p_sys->i_image_height;
-
-    if( p_vout->p_sys->i_image_width != i_image_width
-        || p_vout->p_sys->i_image_height != i_image_height )
-    {
-        intf_WarnMsg( 3, "vout: video surface size changed" );
-        p_vout->p_sys->i_image_width = i_image_width;
-        p_vout->p_sys->i_image_height = i_image_height;
-        DirectXCloseSurface( p_vout );
-    }
-
-    if( p_vout->b_need_render )
+    if( !p_vout->p_sys->b_using_overlay )
     {
-        RECT     rect_window;
-        POINT    point_window;
         DDBLTFX  ddbltfx;
-  
-        /* Nothing yet */
-        if( p_vout->p_sys->p_surface == NULL )
-        {
-            intf_WarnMsg( 3, "vout: no video surface, open one..." );
-            if( DirectXCreateSurface( p_vout ) )
-            {
-                intf_WarnMsg( 3, "vout: cannot open a new video surface !!" );
-                return;
-            }
-            /* Display the surface */
-            p_vout->p_sys->b_display_enabled = 1;
-        }
-
-        /* 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;
-        
-        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;
-
-        /* We want to keep the aspect ratio of the video */
-#if 0
-        if( p_vout->b_scale )
-        {
-            DirectXKeepAspectRatio( p_vout, &rect_window );
-        }
-#endif
 
         /* We ask for the "NOTEARING" option */
         memset( &ddbltfx, 0, sizeof(DDBLTFX) );
         ddbltfx.dwSize = sizeof(DDBLTFX);
-        ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
+        ddbltfx.dwDDFX = DDBLTFX_NOTEARING | DDBLT_ASYNC;
 
         /* Blit video surface to display */
         dxresult = IDirectDrawSurface3_Blt(p_vout->p_sys->p_display,
-                                           &rect_window,
-                                           p_vout->p_sys->p_surface,
+                                           &p_vout->p_sys->rect_dest,
+                                           p_pic->p_sys->p_surface,
                                            NULL,
                                            0, &ddbltfx );
         if( dxresult != DD_OK )
@@ -553,107 +487,31 @@ static void vout_Display( vout_thread_t *p_vout )
         }
 
     }
-    else
+    else /* using overlay */
     {
-        /*
-         * 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( p_vout->p_sys->p_surface == NULL )
-        {
-            intf_WarnMsg( 3, "vout: no video surface, open one..." );
-            if( DirectXCreateSurface( p_vout ) )
-            {
-                intf_WarnMsg( 3, "vout: cannot open a new video surface !!" );
-                return;
-            }
-        }
+        /* Flip the overlay buffers */
+        //dxresult = IDirectDrawSurface3_Flip(p_pic->p_sys->p_surface, NULL, 0 );
 
-        /* Lock the overlay surface */
-        memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
-        ddsd.dwSize = sizeof(DDSURFACEDESC);
-        dxresult = IDirectDrawSurface3_Lock(p_vout->p_sys->p_surface, NULL,
-                                            &ddsd, DDLOCK_NOSYSLOCK, NULL);
-        if ( dxresult == DDERR_SURFACELOST )
+        if( !DirectXGetSurfaceDesc( p_pic ) )
         {
-            /* Your surface can be lost (thanks to windows) so be sure
-             * to check this and restore it if needed */
-            dxresult = IDirectDrawSurface3_Restore( p_vout->p_sys->p_surface );
-            dxresult = IDirectDrawSurface3_Lock( p_vout->p_sys->p_surface,
-                                                 NULL, &ddsd, DDLOCK_NOSYSLOCK
-                                                 | DDLOCK_WAIT, NULL);
-        }
-        if( dxresult != DD_OK )
-        {
-            intf_WarnMsg( 3, "vout: 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++)
-        {
-#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((u8*)ddsd.lpSurface + i*2*ddsd.lPitch,
-                   p_vout->p_rendered_pic->p_y + i*2*i_image_width,
-                   i_image_width);
-            memcpy((u8*)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(((u8*)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(((u8*)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 */
-
-        }
-
-        /* Unlock the Surface */
-        dxresult = IDirectDrawSurface3_Unlock(p_vout->p_sys->p_surface,
-                                              ddsd.lpSurface );
-
-        /* If display not enabled yet then enable */
-        if( !p_vout->p_sys->b_display_enabled )
+        if( !UpdatePictureStruct( p_vout, p_pic, p_vout->output.i_chroma ) )
         {
-            p_vout->p_sys->b_display_enabled = 1;
-            DirectXUpdateOverlay( p_vout );
+            /* AAARRGG */
+            intf_ErrMsg( "vout error: vout_Display unvalid pic chroma" );
+            return;
         }
 
+        /* set currently displayed pic !!! faux*/
+        p_vout->p_sys->p_current_surface = p_pic->p_sys->p_surface;
     }
 
-    /* The first time this function is called it enables the display */
-    p_vout->p_sys->b_display_enabled = 1;
-
+    intf_WarnMsg( 8, "vout: vout_Display End" );
 }
 
 
@@ -733,6 +591,9 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
         IDirectDraw_Release( p_ddobject );
     }
 
+    /* Probe the capabilities of the hardware */
+    DirectXGetDDrawCaps( p_vout );
+
     intf_WarnMsg( 3, "vout: End DirectXInitDDraw" );
     return( 0 );
 }
@@ -748,11 +609,11 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
     HRESULT              dxresult;
     DDSURFACEDESC        ddsd;
     LPDIRECTDRAWSURFACE  p_display;
-    DDPIXELFORMAT        ddpfPixelFormat;
+    DDPIXELFORMAT   pixel_format;
 
     intf_WarnMsg( 3, "vout: DirectXCreateDisplay" );
 
-    /* Now create the primary surface. This surface is what you actually see
+    /* Now get the primary surface. This surface is what you actually see
      * on your screen */
     memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
     ddsd.dwSize = sizeof(DDSURFACEDESC);
@@ -764,7 +625,7 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
                                            &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 );
     }
@@ -786,39 +647,75 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
     }
 
 
-    /* We need to fill in some information for the video output thread.
-     * We do this here because it must be done before the video_output
-     * thread enters its main loop - and DirectXCreateSurface can be called
-     * after that ! */
-    ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-    IDirectDrawSurface3_GetPixelFormat( p_vout->p_sys->p_display,
-                                        &ddpfPixelFormat );
-#ifdef NONAMELESSUNION
-    p_vout->i_screen_depth =    ddpfPixelFormat.u1.dwRGBBitCount;
-    p_vout->i_bytes_per_pixel = ddpfPixelFormat.u1.dwRGBBitCount/8;
-    
-    p_vout->i_red_mask =        ddpfPixelFormat.u2.dwRBitMask;
-    p_vout->i_green_mask =      ddpfPixelFormat.u3.dwGBitMask;
-    p_vout->i_blue_mask =       ddpfPixelFormat.u4.dwBBitMask;
-#else
-    p_vout->i_screen_depth =    ddpfPixelFormat.dwRGBBitCount;
-    p_vout->i_bytes_per_pixel = ddpfPixelFormat.dwRGBBitCount/8;
-
-    p_vout->i_red_mask =        ddpfPixelFormat.dwRBitMask;
-    p_vout->i_green_mask =      ddpfPixelFormat.dwGBitMask;
-    p_vout->i_blue_mask =       ddpfPixelFormat.dwBBitMask;
-#endif /* NONAMELESSUNION */
-
-    /* Create a video surface. This function will try to create an
-     * YUV overlay first and if it can't it will create a simple RGB surface */
-    if( DirectXCreateSurface( p_vout ) )
+    /* 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 create a video surface." );
-        IDirectDrawSurface3_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 );
     }
-      
+
+    /* 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_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 );
+    }
+
+    /* 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 )
+    {
+        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 );
+    }    
+
     return( 0 );
 }
 
@@ -826,61 +723,24 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
  * 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, so we'll try to create this surface first.
- * If we fail, we'll try to create a plain RGB surface.
+ * 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 )
+static int DirectXCreateSurface( vout_thread_t *p_vout,
+                                 LPDIRECTDRAWSURFACE3 *pp_surface_final,
+                                 int i_chroma, int b_overlay )
 {
     HRESULT dxresult;
-    DDSURFACEDESC ddsd;
     LPDIRECTDRAWSURFACE p_surface;
-    DDCAPS ddcaps;
+    DDSURFACEDESC ddsd;
 
     intf_WarnMsg( 3, "vout: DirectXCreateSurface" );
 
-    /* Disable display */
-    p_vout->p_sys->b_display_enabled = 0;
-
-#if 1
-    /* Probe the capabilities of the hardware */
-    /* 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 )
-    {
-        intf_WarnMsg( 3,"vout error: can't get caps." );
-    }
-    else
-    {
-        BOOL bHasOverlay, bHasColorKey, bCanStretch;
-
-        /* 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: Dx Caps: overlay=%i colorkey=%i stretch=%i",
-                         bHasOverlay, bHasColorKey, bCanStretch );
-
-#if 0
-        if( !bHasOverlay ) p_vout->b_need_render = 1;
-#endif
-    }
-#endif
-
-
     /* Create the video surface */
-    if( !p_vout->b_need_render )
+    if( b_overlay )
     {
         /* Now try to create the YUV overlay surface.
          * This overlay will be displayed on top of the primary surface.
@@ -894,23 +754,23 @@ static int DirectXCreateSurface( vout_thread_t *p_vout )
         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
+        ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
         ddsd.dwFlags = DDSD_CAPS |
                        DDSD_HEIGHT |
                        DDSD_WIDTH |
+          //DDSD_BACKBUFFERCOUNT |
                        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;
-        ddsd.dwBackBufferCount = 1;                       /* One back buffer */
+        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 = 0;                       /* One back buffer */
 
         dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
-                                               &ddsd, &p_surface, NULL );
+                                               &ddsd,
+                                               &p_surface, NULL );
         if( dxresult == DD_OK )
         {
             intf_WarnMsg( 3,"vout: DirectX YUV overlay created successfully" );
@@ -918,24 +778,27 @@ static int DirectXCreateSurface( vout_thread_t *p_vout )
         else
         {
             intf_ErrMsg( "vout error: can't create YUV overlay surface." );
-            p_vout->b_need_render = 1;
+            *pp_surface_final = NULL;
+            return 0;
         }
     }
 
-    if( p_vout->b_need_render )
+    if( !b_overlay )
     {
         /* Now try to create a plain RGB surface. */
-        memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
+        memset( &ddsd, 0, sizeof( DDSURFACEDESC ) );
         ddsd.dwSize = sizeof(DDSURFACEDESC);
         ddsd.dwFlags = DDSD_HEIGHT |
                        DDSD_WIDTH |
                        DDSD_CAPS;
-        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
-        ddsd.dwHeight =  p_vout->p_sys->i_image_height;
-        ddsd.dwWidth =  p_vout->p_sys->i_image_width;
+        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 );
+                                               &ddsd,
+                                               &p_surface, NULL );
         if( dxresult == DD_OK )
         {
             intf_WarnMsg( 3,"vout: DirectX RGB surface created successfully" );
@@ -943,167 +806,24 @@ static int DirectXCreateSurface( vout_thread_t *p_vout )
         else
         {
             intf_ErrMsg( "vout error: can't create RGB surface." );
-            p_vout->p_sys->p_surface = NULL;
-            return( 1 );
+            *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 *)&p_vout->p_sys->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." );
-        IDirectDrawSurface_Release( p_surface );
-        p_vout->p_sys->p_surface = NULL;
-        return( 1 );
-    }
-    else
-    {
-        /* Release the old interface */
-        IDirectDrawSurface_Release( p_surface );
-    }
-
-    if( !p_vout->b_need_render )
-    {
-        /* Hide the overlay for now */
-        IDirectDrawSurface3_UpdateOverlay(p_vout->p_sys->p_surface,
-                                          NULL,
-                                          p_vout->p_sys->p_display,
-                                          NULL,
-                                          DDOVER_HIDE,
-                                          NULL);
+        *pp_surface_final = NULL;
+        return 0;
     }
-    else
-    {
-         DirectXCreateClipper( p_vout );
-    }
-
-
-    /* From now on, do some initialisation for video_output */
-
-    /* if we want a valid pointer to the surface memory, we must lock
-     * the surface */
-
-    memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
-    ddsd.dwSize = sizeof(DDSURFACEDESC);
-    dxresult = IDirectDrawSurface3_Lock( p_vout->p_sys->p_surface, NULL, &ddsd,
-                                         DDLOCK_NOSYSLOCK | DDLOCK_WAIT, 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_vout->p_sys->p_surface );
-        dxresult = IDirectDrawSurface3_Lock( p_vout->p_sys->p_surface,
-                                             NULL, &ddsd, DDLOCK_NOSYSLOCK
-                                             | DDLOCK_WAIT, NULL);
-    }
-    if( dxresult != DD_OK )
-    {
-        intf_ErrMsg( "vout: DirectXCreateDisplay could not lock the surface" );
-        return( 1 );
-    }
-
-    /* Set the pointer to the surface memory */
-    p_vout->p_sys->p_directx_buf[ 0 ] = ddsd.lpSurface;
-    /* back buffer, none for now */
-    p_vout->p_sys->p_directx_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;
-#else
-    p_vout->i_bytes_per_line =  ddsd.lPitch;
-#endif /* NONAMELESSUNION */
-
-
-    if( p_vout->b_need_render )
-    {
-        /* For an RGB surface we need to fill in some more info */
-#ifdef NONAMELESSUNION
-        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_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 = IDirectDrawSurface3_Unlock(p_vout->p_sys->p_surface,
-                                          ddsd.lpSurface );
-
-    /* Set and initialize buffers */
-    p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_directx_buf[ 0 ],
-                           p_vout->p_sys->p_directx_buf[ 1 ] );
 
-
-    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_WarnMsg( 3, "vout: DirectXCreateClipper can't create clipper." );
-        IDirectDrawSurface_Release( p_vout->p_sys->p_clipper );
-        p_vout->p_sys->p_clipper = NULL;
-        return( 1 );
-    }
-    
-    /* 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_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 );
-    }
-    
-    /* 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 )
-    {
-        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 );
-    }    
-     
-    return( 0 );
+    return 1;
 }
 
 
@@ -1114,155 +834,45 @@ static int DirectXCreateClipper( vout_thread_t *p_vout )
  * Ususally the overlay is moved by the user and thus, by a move or resize
  * event (in vout_Manage).
  *****************************************************************************/
-static int DirectXUpdateOverlay( vout_thread_t *p_vout )
+void DirectXUpdateOverlay( vout_thread_t *p_vout )
 {
     DDOVERLAYFX     ddofx;
-    RECT            rect_window, rect_window_backup, rect_image;
-    POINT           point_window;
     DWORD           dwFlags;
     HRESULT         dxresult;
-    DWORD           dw_colorkey;
-    DDPIXELFORMAT   pixel_format;
-    DDSURFACEDESC   ddsd;
-
-    if( p_vout->p_sys->p_surface == NULL || p_vout->b_need_render )
-    {
-        intf_WarnMsg( 3, "vout: DirectXUpdateOverlay no overlay !!" );
-        return( 0 );
-    }
 
-    if( !p_vout->p_rendered_pic )
+    if( p_vout->p_sys->p_current_surface == NULL ||
+        !p_vout->p_sys->b_using_overlay )
     {
-        intf_WarnMsg( 3, "vout: DirectXUpdateOverlay p_rendered_pic=NULL !" );
-        return( 1 );
-    }
-
-    if( !p_vout->p_sys->b_display_enabled )
-    {
-        return( 0 );
-    }
-
-    /* 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;
-
-    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;
-
-
-    /* We want to keep the aspect ratio of the video */
-    if( p_vout->b_scale )
-    {
-        DirectXKeepAspectRatio( p_vout, &rect_window );
+        intf_WarnMsg( 5, "vout: DirectXUpdateOverlay no overlay !!" );
+        return;
     }
 
-    /* It seems we can't feed the UpdateOverlay directdraw function with
-     * negative values so we have to clip the computed rectangles */
-    memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
-    ddsd.dwSize = sizeof(DDSURFACEDESC);
-    ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
-    IDirectDraw2_GetDisplayMode( p_vout->p_sys->p_ddobject, &ddsd );
-
-    rect_window_backup = rect_window;
-
-    /* Clip the destination window */
-    rect_window.left = (rect_window.left < 0) ? 0 : rect_window.left;
-    rect_window.right = (rect_window.right < 0) ? 0 : rect_window.right;
-    rect_window.top = (rect_window.top < 0) ? 0 : rect_window.top;
-    rect_window.bottom = (rect_window.bottom < 0) ? 0 : rect_window.bottom;
-
-    rect_window.left = (rect_window.left > ddsd.dwWidth) ? ddsd.dwWidth
-      : rect_window.left;
-    rect_window.right = (rect_window.right > ddsd.dwWidth) ? ddsd.dwWidth
-      : rect_window.right;
-    rect_window.top = (rect_window.top > ddsd.dwHeight) ? ddsd.dwHeight
-      : rect_window.top;
-    rect_window.bottom = (rect_window.bottom > ddsd.dwHeight) ? ddsd.dwHeight
-      : rect_window.bottom;
-
-    intf_WarnMsg( 3, "vout: DirectXUpdateOverlay window coords: %i,%i,%i,%i",
-                  rect_window.left, rect_window.top,
-                  rect_window.right, rect_window.bottom);
-
-    /* the 2 following lines are to fix a bug when click on Windows desktop */
-    if( (rect_window.right-rect_window.left)==0 ||
-        (rect_window.bottom-rect_window.top)==0 ) return 0;
-
-    /* Clip the source image */
-    rect_image.left = ( rect_window.left == rect_window_backup.left ) ? 0
-      : labs(rect_window_backup.left - rect_window.left) *
-      p_vout->p_rendered_pic->i_width /
-      (rect_window_backup.right - rect_window_backup.left);
-    rect_image.right = ( rect_window.right == rect_window_backup.right ) ?
-      p_vout->p_rendered_pic->i_width
-      : p_vout->p_rendered_pic->i_width -
-      labs(rect_window_backup.right - rect_window.right) *
-      p_vout->p_rendered_pic->i_width /
-      (rect_window_backup.right - rect_window_backup.left);
-    rect_image.top = ( rect_window.top == rect_window_backup.top ) ? 0
-      : labs(rect_window_backup.top - rect_window.top) *
-      p_vout->p_rendered_pic->i_height /
-      (rect_window_backup.bottom - rect_window_backup.top);
-    rect_image.bottom = ( rect_window.bottom == rect_window_backup.bottom ) ?
-      p_vout->p_rendered_pic->i_height
-      : p_vout->p_rendered_pic->i_height -
-      labs(rect_window_backup.bottom - rect_window.bottom) *
-      p_vout->p_rendered_pic->i_height /
-      (rect_window_backup.bottom - rect_window_backup.top);
-
-    intf_WarnMsg( 3, "vout: DirectXUpdateOverlay image coords: %i,%i,%i,%i",
-                  rect_image.left, rect_image.top,
-                  rect_image.right, rect_image.bottom);
-
-    /* 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" );
-    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
+    /* 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 = dw_colorkey;
-    ddofx.dckDestColorkey.dwColorSpaceHighValue = dw_colorkey;
-
-    dwFlags = DDOVER_KEYDESTOVERRIDE | DDOVER_SHOW;
-
-    dxresult = IDirectDrawSurface3_UpdateOverlay(p_vout->p_sys->p_surface,
-                                                 &rect_image,
-                                                 p_vout->p_sys->p_display,
-                                                 &rect_window,
-                                                 dwFlags,
-                                                 &ddofx);
+    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 );
 }
 
 /*****************************************************************************
@@ -1294,10 +904,16 @@ static void DirectXCloseDDraw( vout_thread_t *p_vout )
 static void DirectXCloseDisplay( vout_thread_t *p_vout )
 {
     intf_WarnMsg( 3, "vout: DirectXCloseDisplay" );
-    if( p_vout->p_sys->p_display != NULL )
+
+    if( p_vout->p_sys->p_clipper != NULL )
     {
-        DirectXCloseSurface( p_vout );
+        intf_WarnMsg( 3, "vout: DirectXCloseDisplay clipper" );
+        IDirectDraw2_Release( p_vout->p_sys->p_clipper );
+        p_vout->p_sys->p_clipper = NULL;
+    }
 
+    if( p_vout->p_sys->p_display != NULL )
+    {
         intf_WarnMsg( 3, "vout: DirectXCloseDisplay display" );
         IDirectDraw2_Release( p_vout->p_sys->p_display );
         p_vout->p_sys->p_display = NULL;
@@ -1307,126 +923,392 @@ static void DirectXCloseDisplay( vout_thread_t *p_vout )
 /*****************************************************************************
  * DirectXCloseSurface: close the YUV overlay or RGB surface.
  *****************************************************************************
- * This function returns all resources allocated by the 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 returns all resources allocated for the surface.
  *****************************************************************************/
-static void DirectXCloseSurface( vout_thread_t *p_vout )
+static void DirectXCloseSurface( vout_thread_t *p_vout,
+                                 LPDIRECTDRAWSURFACE3 p_surface )
 {
     intf_WarnMsg( 3, "vout: DirectXCloseSurface" );
-    if( p_vout->p_sys->p_surface != NULL )
+    if( p_surface != NULL )
     {
-        intf_WarnMsg( 3, "vout: DirectXCloseSurface surface" );
-        IDirectDraw2_Release( p_vout->p_sys->p_surface );
-        p_vout->p_sys->p_surface = NULL;
+        IDirectDraw2_Release( p_surface );
     }
+}
 
-    if( p_vout->p_sys->p_clipper != NULL )
+/*****************************************************************************
+ * 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( )
     {
-        intf_WarnMsg( 3, "vout: DirectXCloseSurface clipper" );
-        IDirectDraw2_Release( p_vout->p_sys->p_clipper );
-        p_vout->p_sys->p_clipper = NULL;
+        case 8: /* FIXME: set the palette */
+            p_vout->output.i_chroma = FOURCC_BI_RGB; break;
+        case 15:
+            p_vout->output.i_chroma = FOURCC_RV15; break;
+        case 16:
+            p_vout->output.i_chroma = FOURCC_RV16; break;
+        case 24:
+            p_vout->output.i_chroma = FOURCC_BI_BITFIELDS; break;
+        case 32:
+            p_vout->output.i_chroma = FOURCC_BI_BITFIELDS; break;
+        default:
+            intf_ErrMsg( "vout error: unknown screen depth" );
+            return( 0 );
+    }
+#endif
+
+    intf_WarnMsg( 3, "vout: NewPictureVec" );
+
+    I_OUTPUTPICTURES = 0;
+
+    /* chroma asked for */
+    p_vout->output.i_chroma = p_vout->render.i_chroma;
+
+    /* hack */
+    if( p_vout->render.i_chroma == FOURCC_I420 )
+        p_vout->output.i_chroma = FOURCC_YV12;
+
+    /* 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 )
+    {
+        if( DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma,
+                                  p_vout->p_sys->b_using_overlay ) )
+        {
+            /* Allocate internal structure */
+            p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
+            if( p_pic[0].p_sys == NULL )
+            {
+                DirectXCloseSurface( p_vout, p_surface );
+                return -1;
+            }
+            p_pic[0].p_sys->p_surface = p_surface;
+            p_vout->p_sys->p_current_surface = p_surface;
+            DirectXUpdateOverlay( p_vout );
+            I_OUTPUTPICTURES = 1;
+        }
+        else p_vout->p_sys->b_using_overlay = 0;
+    }
+
+    /* As we can't have overlays, will try to create plain RBG surfaces in
+     * system memory. These surfaces will then be blitted onto the primary
+     * surface (display) so they can be displayed */
+    if( !p_vout->p_sys->b_using_overlay )
+    {
+        /* FixMe */
+        p_vout->output.i_chroma = FOURCC_RV16;
+
+        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;
+                I_OUTPUTPICTURES++;
+
+            }
+            else break;
+        }
+    }
+
+
+    /* 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];
+
+        if( !DirectXGetSurfaceDesc( &p_pic[i] ) )
+        {
+            /* AAARRGG */
+            FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
+            I_OUTPUTPICTURES = 0;
+            return -1;
+        }
+
+        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;
+        }
     }
 
-    /* Disable any display */
-    p_vout->p_sys->b_display_enabled = 0;
+    intf_WarnMsg( 3, "vout: End NewPictureVec");
+    return 0;
 }
 
 /*****************************************************************************
- * DirectXKeepAspectRatio: 
+ * FreePicture: destroy a picture vector allocated with NewPictureVec
  *****************************************************************************
- * This function adjusts the coordinates of the video rectangle to keep the
- * aspect/ratio of the video.
+ * 
  *****************************************************************************/
-static void DirectXKeepAspectRatio( vout_thread_t *p_vout, RECT *rect_window )
+static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic,
+                            int i_num_pics )
 {
+    int i;
+
+    for( i = 0; i < i_num_pics; i++ )
+    {
+        DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_surface );
 
-  if( !p_vout->p_rendered_pic ) return;
-
-  switch( p_vout->p_rendered_pic->i_aspect )
-  {
-      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
+        for( i = 0; i < i_num_pics; i++ )
         {
-          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);
+            free( p_pic[i].p_sys );
         }
-      break;
-      
-  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
-      {
-        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);
-      }
-    break;
-    
-  case AR_3_4_PICTURE:
-    if( ((rect_window->right-rect_window->left)*3)
-        > ((rect_window->bottom-rect_window->top)*4) )
-      {
-        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);
-      }
-    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;
-
-  case AR_SQUARE_PICTURE:
-  default:
-    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);
-      }
+    }
+}
+
+/*****************************************************************************
+ * UpdatePictureStruct: updates the internal data in the picture_t structure
+ *****************************************************************************
+ * This will setup stuff for use by the video_output thread
+ *****************************************************************************/
+static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic,
+                                int i_chroma )
+{
+
+    switch( p_vout->output.i_chroma )
+    {
+
+        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->p->i_red_mask   = 0x001f;
+            p_pic->p->i_green_mask = 0x03e0;
+            p_pic->p->i_blue_mask  = 0x7c00;
+
+            p_pic->i_planes = 1;
+            break;
+
+        case FOURCC_RV15:
+
+            p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
+            p_pic->p->i_lines = p_vout->output.i_height;
+            p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
+            p_pic->p->i_pixel_bytes = 2;
+            p_pic->p->b_margin = 0;
+
+            p_pic->p->i_red_mask   = 0x001f;
+            p_pic->p->i_green_mask = 0x07e0;
+            p_pic->p->i_blue_mask  = 0xf800;
+
+            p_pic->i_planes = 1;
+            break;
+#if 0
+        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[U_PLANE].i_pitch;
+            p_pic->p[V_PLANE].i_pixel_bytes = 1;
+            p_pic->p[V_PLANE].b_margin = 0;
+
+            p_pic->i_planes = 3;
+            break;
+
+        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;
+}
+
+/*****************************************************************************
+ * DirectXGetDDrawCaps: Probe the capabilities of the hardware
+ *****************************************************************************
+ * It is nice to know which features are supported by the hardware so we can
+ * find ways to optimize our rendering.
+ *****************************************************************************/
+static void DirectXGetDDrawCaps( vout_thread_t *p_vout )
+{
+    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 )
+    {
+        intf_WarnMsg( 3,"vout error: can't get caps." );
+    }
     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;
-    
-  }
+    {
+        BOOL bHasOverlay, bHasOverlayFourCC, bCanClipOverlay,
+             bHasColorKey, bCanStretch;
+
+        /* 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;
+
+    }
+}
+
+/*****************************************************************************
+ * DirectXGetSurfaceDesc: Get some more information about the surface
+ *****************************************************************************
+ * This function get and stores the surface descriptor which among things
+ * has the pointer to the picture data.
+ *****************************************************************************/
+static int DirectXGetSurfaceDesc( picture_t *p_pic )
+{
+    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 | DDLOCK_WAIT,
+                                         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 )
+    {
+        intf_ErrMsg( "vout: DirectXGetSurfaceDesc can't lock surface" );
+        return 0;
+    }
+
+    /* Unlock the Surface */
+    dxresult = IDirectDrawSurface3_Unlock( p_pic->p_sys->p_surface, NULL );
 
+    return 1;
 }
index e7a2031c9c103b00a4f30b7211c0e44ca0193888..4082b1916c32e176a30e2c68818a700d9b7c51aa 100644 (file)
@@ -2,7 +2,7 @@
  * vout_directx.h: Windows DirectX video output header file
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: vout_directx.h,v 1.1 2001/07/11 14:26:19 gbazin Exp $
+ * $Id: vout_directx.h,v 1.2 2002/01/17 23:02:45 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
@@ -32,28 +32,42 @@ typedef struct vout_sys_s
 
     LPDIRECTDRAW2        p_ddobject;                    /* DirectDraw object */
     LPDIRECTDRAWSURFACE3 p_display;                        /* Display device */
-    LPDIRECTDRAWSURFACE3 p_surface;    /* surface where we display the video */
+    LPDIRECTDRAWSURFACE3 p_current_surface;   /* surface currently displayed */
     LPDIRECTDRAWCLIPPER  p_clipper;             /* clipper used for blitting */
     HINSTANCE            hddraw_dll;       /* handle of the opened ddraw dll */
     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;
+    boolean_t    b_using_overlay;         /* Are we using an overlay surface */
 
-    int         i_colorkey;          /* colorkey used to display the overlay */
-    boolean_t   b_display_enabled;
-    boolean_t   b_cursor;
+    /* size of the display */
+    RECT         rect_display;
+    int          i_display_depth;
+
+    /* Window position and size */
+    int          i_window_x;
+    int          i_window_y;
+    int          i_window_width;
+    int          i_window_height;
+
+    /* Coordinates of src and dest images (used when blitting to display) */
+    RECT         rect_src;
+    RECT         rect_src_clipped;
+    RECT         rect_dest;
+    RECT         rect_dest_clipped;
 
-    u16         i_changes;              /* changes made to the video display */
+    /* DDraw capabilities */
+    int          b_caps_overlay_clipping;
 
-    boolean_t   b_cursor_autohidden;
-    mtime_t     i_lastmoved;
+    int          i_rgb_colorkey;      /* colorkey in RGB used by the overlay */
+    int          i_colorkey;                 /* colorkey used by the overlay */
+    boolean_t    b_cursor;
+
+    u16          i_changes;             /* changes made to the video display */
 
-    char       *p_directx_buf[2];                      /* Buffer information */
+    boolean_t    b_cursor_autohidden;
+    mtime_t      i_lastmoved;
 
     vlc_thread_t event_thread_id;                            /* event thread */
     vlc_mutex_t  event_thread_lock;             /* lock for the event thread */
@@ -64,6 +78,19 @@ typedef struct vout_sys_s
 
 } vout_sys_t;
 
+/*****************************************************************************
+ * picture_sys_t: direct buffer method descriptor
+ *****************************************************************************
+ * This structure is part of the picture descriptor, it describes the
+ * DirectX specific properties of a direct buffer.
+ *****************************************************************************/
+typedef struct picture_sys_s
+{
+    LPDIRECTDRAWSURFACE3 p_surface;
+    DDSURFACEDESC        ddsd;
+
+} picture_sys_t;
+
 /*****************************************************************************
  * Prototypes from vout_directx.c
  *****************************************************************************/
@@ -72,3 +99,4 @@ typedef struct vout_sys_s
  * Prototypes from vout_events.c
  *****************************************************************************/
 void DirectXEventThread ( vout_thread_t *p_vout );
+void DirectXUpdateOverlay( vout_thread_t *p_vout );
index b9fa3c20ffe585d52e627e3e25e94da7bde62f91..362ca2aaa553164f52ace6c20a7ea4dfa2fdf3ce 100644 (file)
@@ -2,7 +2,7 @@
  * vout_events.c: Windows DirectX video output events handler
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: vout_events.c,v 1.7 2001/12/30 07:09:54 sam Exp $
+ * $Id: vout_events.c,v 1.8 2002/01/17 23:02:45 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
 
 #include <windows.h>
 #include <windowsx.h>
+#include <shellapi.h>
 
-#if defined( _MSC_VER )
-#   include <ddraw.h>
-#else
-#   include <directx.h>
-#endif
+#include <ddraw.h>
 
 #include "interface.h"
 
  *****************************************************************************/
 static int  DirectXCreateWindow( vout_thread_t *p_vout );
 static void DirectXCloseWindow ( vout_thread_t *p_vout );
+static void DirectXUpdateRects( vout_thread_t *p_vout );
 static long FAR PASCAL DirectXEventProc ( HWND hwnd, UINT message,
                                           WPARAM wParam, LPARAM lParam );
 
-/*****************************************************************************
- * Global variables.
- * I really hate them, but here I don't have any choice. And anyway, this
- * shouldn't really affect reentrancy.
- * This variable is used to know if we have to update the overlay position
- * and size. This is to fix the bug we've got when the Windows option, to show
- * the content of a window when you drag it, is enabled.
- *****************************************************************************/
-int b_directx_update_overlay = 0;
-
 /*****************************************************************************
  * DirectXEventThread: Create video window & handle its messages
  *****************************************************************************
@@ -79,7 +67,6 @@ int b_directx_update_overlay = 0;
 void DirectXEventThread( vout_thread_t *p_vout )
 {
     MSG             msg;
-    boolean_t       b_dispatch_msg = TRUE;
 
     /* Initialisation */
 
@@ -104,191 +91,147 @@ void DirectXEventThread( vout_thread_t *p_vout )
     vlc_mutex_unlock( &p_vout->p_sys->event_thread_lock );
 
     /* Main loop */
-    while( !p_vout->b_die && !p_vout->p_sys->b_event_thread_die )
+    /* GetMessage will sleep if there's no message in the queue */
+    while( GetMessage( &msg, p_vout->p_sys->hwnd, 0, 0 ) )
     {
 
-        /* GetMessage will sleep if there's no message in the queue */
-        if( GetMessage( &msg, NULL, 0, 0 ) >= 0 )
+        /* Check if we are asked to exit */
+        if( p_vout->b_die || p_vout->p_sys->b_event_thread_die )
+            break;
+
+        switch( msg.message )
         {
-            switch( msg.message )
+
+#if 0
+        case WM_PAINT:
+            intf_WarnMsg( 4, "vout: vout_Manage WM_PAINT" );
+            break;
+
+        case WM_ERASEBKGND:
+            intf_WarnMsg( 4, "vout: vout_Manage WM_ERASEBKGND" );
+            break;
+#endif
+
+        case WM_MOUSEMOVE:
+            if( p_vout->p_sys->b_cursor )
             {
-                
-            case WM_CLOSE:
-                intf_WarnMsg( 3, "vout: vout_Manage WM_CLOSE" );
-                break;
-                
-            case WM_QUIT:
-                intf_WarnMsg( 3, "vout: vout_Manage WM_QUIT" );
-                p_vout->p_sys->b_event_thread_die = 1;
-                p_main->p_intf->b_die = 1;
-                break;
-                
-            case WM_MOVE:
-                intf_WarnMsg( 3, "vout: vout_Manage WM_MOVE" );
-                if( !p_vout->b_need_render )
+                if( p_vout->p_sys->b_cursor_autohidden )
                 {
-                    p_vout->p_sys->i_changes |= VOUT_SIZE_CHANGE;
+                    p_vout->p_sys->b_cursor_autohidden = 0;
+                    p_vout->p_sys->i_lastmoved = mdate();
+                    ShowCursor( TRUE );
                 }
-                /* don't create a never ending loop */
-                b_dispatch_msg = FALSE;
-                break;
-          
-            case WM_APP:
-                intf_WarnMsg( 3, "vout: vout_Manage WM_APP" );
-                if( !p_vout->b_need_render )
+                else
                 {
-                    p_vout->p_sys->i_changes |= VOUT_SIZE_CHANGE;
+                    p_vout->p_sys->i_lastmoved = mdate();
                 }
-                /* size change has been handled (to fix a bug)*/
-                b_directx_update_overlay = 0;
-                /* don't create a never ending loop */
-                b_dispatch_msg = FALSE;
+            }
+            break;
+
+        case WM_RBUTTONUP:
+            intf_WarnMsg( 4, "vout: vout_Manage WM_RBUTTONUP" );
+            p_main->p_intf->b_menu_change = 1;
+            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: vout_Manage WM_KEYDOWN" );
+            switch( msg.wParam )
+            {
+            case VK_ESCAPE:
+            case VK_F12:
+                PostQuitMessage( 0 );
                 break;
-              
-#if 0
-            case WM_PAINT:
-                intf_WarnMsg( 4, "vout: vout_Manage WM_PAINT" );
+            }
+            TranslateMessage(&msg);
+            break;
+
+        case WM_CHAR:
+            intf_WarnMsg( 3, "vout: vout_Manage WM_CHAR" );
+            switch( msg.wParam )
+            {
+            case 'q':
+            case 'Q':
+                PostQuitMessage( 0 );
                 break;
-              
-            case WM_ERASEBKGND:
-                intf_WarnMsg( 4, "vout: vout_Manage WM_ERASEBKGND" );
+
+            case 'f':                            /* switch to fullscreen */
+            case 'F':
+                p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
                 break;
-#endif
-              
-            case WM_MOUSEMOVE:
-                intf_WarnMsg( 4, "vout: 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();
-                    }
-                }               
+
+            case 'c':                                /* toggle grayscale */
+            case 'C':
+                p_vout->b_grayscale = ! p_vout->b_grayscale;
+                p_vout->p_sys->i_changes |= VOUT_GRAYSCALE_CHANGE;
                 break;
-                
-            case WM_RBUTTONUP:
-                intf_WarnMsg( 4, "vout: vout_Manage WM_RBUTTONUP" );
-                p_main->p_intf->b_menu_change = 1;
+
+            case 'i':                                     /* toggle info */
+            case 'I':
+                p_vout->b_info = ! p_vout->b_info;
+                p_vout->p_sys->i_changes |= VOUT_INFO_CHANGE;
                 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: vout_Manage WM_KEYDOWN" );
-                switch( msg.wParam )
-                {
-                case VK_ESCAPE:
-                case VK_F12:
-                    PostQuitMessage( 0 );
-                    break;
-                }
-                TranslateMessage(&msg);
-                b_dispatch_msg = FALSE;
+            case 's':                                  /* toggle scaling */
+            case 'S':
+                p_vout->b_scale = ! p_vout->b_scale;
+                p_vout->p_sys->i_changes |= VOUT_SCALE_CHANGE;
                 break;
-              
-            case WM_CHAR:
-                intf_WarnMsg( 3, "vout: vout_Manage WM_CHAR" );
-                switch( msg.wParam )
-                {
-                case 'q':
-                case 'Q':
-                    PostQuitMessage( 0 );
-                    break;
-                  
-                case 'f':                            /* switch to fullscreen */
-                case 'F':
-                    p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
-                    break;
-                  
-                case 'y':                              /* switch to hard YUV */
-                case 'Y':
-                    p_vout->p_sys->i_changes |= VOUT_YUV_CHANGE;
-                    break;
-                  
-                case 'c':                                /* toggle grayscale */
-                case 'C':
-                    p_vout->b_grayscale = ! p_vout->b_grayscale;
-                    p_vout->p_sys->i_changes |= VOUT_GRAYSCALE_CHANGE;
-                    break;
-                  
-                case 'i':                                     /* toggle info */
-                case 'I':
-                    p_vout->b_info = ! p_vout->b_info;
-                    p_vout->p_sys->i_changes |= VOUT_INFO_CHANGE;
-                    break;
-                  
-                case 's':                                  /* toggle scaling */
-                case 'S':
-                    p_vout->b_scale = ! p_vout->b_scale;
-                    p_vout->p_sys->i_changes |= VOUT_SCALE_CHANGE;
-                    break;
-                  
-                case ' ':                                /* toggle interface */
-                    p_vout->b_interface = ! p_vout->b_interface;
-                    p_vout->p_sys->i_changes |= VOUT_INTF_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;
-                }
-              
-#if 0          
-            default:
-                intf_WarnMsg( 4, "vout: vout_Manage WM Default %i",
-                              msg.message );
+
+            case ' ':                                /* toggle interface */
+                p_vout->b_interface = ! p_vout->b_interface;
+                p_vout->p_sys->i_changes |= VOUT_INTF_CHANGE;
                 break;
-#endif
 
-            } /* End Switch */
+            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;
 
-            /* don't create a never ending loop */
-            if( b_dispatch_msg )
-            {
-                TranslateMessage(&msg);
-                DispatchMessage(&msg);
+            default:
+                intf_DbgMsg( "unhandled key '%c' (%i)",
+                             (char)msg.wParam, msg.wParam );
+                break;
             }
-            b_dispatch_msg = TRUE;
 
-        } /* if( GetMessage() ) */
-        else
-        {
-            intf_ErrMsg("vout error: GetMessage failed in DirectXEventThread");
-            p_vout->p_sys->b_event_thread_die = 1;
-        } /* End if( GetMessage() ) */
+        default:
+            /* Messages we don't handle directly are dispatched to the
+             * window procedure */
+#if 0
+            intf_WarnMsg( 5, "vout: vout_Manage unhandled message",
+                          msg.message );
+#endif
+            TranslateMessage(&msg);
+            DispatchMessage(&msg);
+            break;
 
+        } /* End Switch */
 
     } /* End Main loop */
 
-    /* Destroy the window */
-    DirectXCloseWindow( p_vout );
+    if( msg.message == WM_QUIT )
+    {
+        intf_WarnMsg( 3, "vout: DirectXEventThread WM_QUIT" );
+        p_vout->p_sys->hwnd = NULL; /* Window already destroyed */
+
+        /* exit application */
+        p_main->p_intf->b_die = 1;
+    }
+
+    intf_WarnMsg( 3, "vout: DirectXEventThread Terminating" );
 
-    /* Set thread Status */
-    p_vout->p_sys->i_event_thread_status = THREAD_OVER;
+    /* clear the changes formerly signaled */
+    p_vout->p_sys->i_changes = 0;
 
+    DirectXCloseWindow( p_vout );
 }
 
 
@@ -308,6 +251,8 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
     RECT       rect_window;
     COLORREF   colorkey; 
     HDC        hdc;
+    HICON      vlc_icon = NULL;
+    char       vlc_path[_MAX_PATH+1];
 
     intf_WarnMsg( 3, "vout: DirectXCreateWindow" );
 
@@ -326,18 +271,37 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
     /* 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() );
+    hdc = GetDC( NULL );
     for( colorkey = 5; colorkey < 0xFF /*all shades of red*/; colorkey++ )
     {
         if( colorkey == GetNearestColor( hdc, colorkey ) )
           break;
     }
     intf_WarnMsg(3,"vout: DirectXCreateWindow 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;
+    p_vout->p_sys->i_rgb_colorkey = (int)colorkey;
+
+    /* Get the current size of the display and its colour depth */
+    p_vout->p_sys->rect_display.right = GetDeviceCaps( hdc, HORZRES );
+    p_vout->p_sys->rect_display.bottom = GetDeviceCaps( hdc, VERTRES );
+    p_vout->p_sys->i_display_depth = GetDeviceCaps( hdc, BITSPIXEL );
+    intf_WarnMsg( 3, "vout: Screen dimensions %ix%i colour depth %i",
+                  p_vout->p_sys->rect_display.right,
+                  p_vout->p_sys->rect_display.bottom,
+                  p_vout->p_sys->i_display_depth );
+
+    ReleaseDC( p_vout->p_sys->hwnd, hdc );
+
+    /* Get the Icon from the main app */
+    if( GetModuleFileName( NULL, vlc_path, _MAX_PATH ) )
+    {
+        vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
+    }
+    if( !vlc_icon )
+        vlc_icon = LoadIcon( NULL, IDI_APPLICATION );
+
 
     /* fill in the window class structure */
     wc.cbSize        = sizeof(WNDCLASSEX);
@@ -346,12 +310,12 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
     wc.cbClsExtra    = 0;                             /* no extra class data */
     wc.cbWndExtra    = 0;                            /* no extra window data */
     wc.hInstance     = hInstance;                                /* instance */
-    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION); /* load the vlc icon */
+    wc.hIcon         = CopyIcon( vlc_icon );            /* load the vlc 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 */
-    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION); /* load the vlc icon */
+    wc.hIconSm       = CopyIcon( vlc_icon );            /* load the vlc icon */
 
     /* register the window class */
     if (!RegisterClassEx(&wc))
@@ -374,7 +338,7 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
     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 */
+                    | WS_SIZEBOX,               /* window style */
                     10,                              /* default X coordinate */
                     10,                              /* default Y coordinate */
                     rect_window.right - rect_window.left,    /* window width */
@@ -389,6 +353,11 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
         return (1);
     }
 
+    /* store a p_vout pointer into the window local storage (for later use
+     * in DirectXEventProc).
+     * We need to use SetWindowLongPtr when it is available in mingw */
+    SetWindowLong( p_vout->p_sys->hwnd, GWL_USERDATA, (LONG)p_vout );
+
     /* now display the window */
     ShowWindow(p_vout->p_sys->hwnd, SW_SHOW);
 
@@ -423,6 +392,83 @@ static void DirectXCloseWindow( vout_thread_t *p_vout )
     }
 }
 
+/*****************************************************************************
+ * DirectXUpdateRects: 
+ *****************************************************************************
+ * This function is called when the window position and size is changed, and
+ * its job is to update the source and destination RECTs used to display the
+ * picture.
+ *****************************************************************************/
+static void DirectXUpdateRects( vout_thread_t *p_vout )
+{
+    int i_width, i_height, i_x, i_y;
+
+#define rect_src p_vout->p_sys->rect_src
+#define rect_src_clipped p_vout->p_sys->rect_src_clipped
+#define rect_dest p_vout->p_sys->rect_dest
+#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
+#define rect_display p_vout->p_sys->rect_display
+
+    vout_PlacePicture( p_vout, p_vout->p_sys->i_window_width,
+                       p_vout->p_sys->i_window_height,
+                       &i_x, &i_y, &i_width, &i_height );
+
+    /* Destination image position and dimensions */
+    rect_dest.left = i_x + p_vout->p_sys->i_window_x;
+    rect_dest.top = i_y + p_vout->p_sys->i_window_y;
+    rect_dest.right = rect_dest.left + i_width;
+    rect_dest.bottom = rect_dest.top + i_height;
+
+
+    /* UpdateOverlay directdraw function doesn't automatically clip to the
+     * display size so we need to do it otherwise it will fails */
+
+    /* Clip the destination window */
+    IntersectRect( &rect_dest_clipped, &rect_dest, &rect_display );
+
+    intf_WarnMsg( 3, "vout: DirectXUpdateRects image_dst_clipped coords:"
+                  " %i,%i,%i,%i",
+                  rect_dest_clipped.left, rect_dest_clipped.top,
+                  rect_dest_clipped.right, rect_dest_clipped.bottom);
+
+    /* the 2 following lines are to fix a bug when clicking on the desktop */
+    if( (rect_dest_clipped.right - rect_dest_clipped.left)==0 ||
+        (rect_dest_clipped.bottom - rect_dest_clipped.top)==0 )
+    {
+        SetRectEmpty( &rect_src_clipped );
+        return;
+    }
+
+    /* src image dimensions */
+    rect_src.left = 0;
+    rect_src.top = 0;
+    rect_src.right = p_vout->render.i_width;
+    rect_src.bottom = p_vout->render.i_height;
+
+    /* Clip the source image */
+    rect_src_clipped.left = (rect_dest_clipped.left - rect_dest.left) *
+      p_vout->render.i_width / (rect_dest.right - rect_dest.left);
+    rect_src_clipped.right = p_vout->render.i_width - 
+      (rect_dest.right - rect_dest_clipped.right) * p_vout->render.i_width /
+      (rect_dest.right - rect_dest.left);
+    rect_src_clipped.top = (rect_dest_clipped.top - rect_dest.top) *
+      p_vout->render.i_height / (rect_dest.bottom - rect_dest.top);
+    rect_src_clipped.bottom = p_vout->render.i_height -
+      (rect_dest.bottom - rect_dest_clipped.bottom) * p_vout->render.i_height /
+      (rect_dest.bottom - rect_dest.top);
+
+    intf_WarnMsg( 3, "vout: DirectXUpdateRects image_src_clipped"
+                  " coords: %i,%i,%i,%i",
+                  rect_src_clipped.left, rect_src_clipped.top,
+                  rect_src_clipped.right, rect_src_clipped.bottom);
+
+#undef rect_src
+#undef rect_src_clipped
+#undef rect_dest
+#undef rect_dest_clipped
+#undef rect_display
+}
+
 /*****************************************************************************
  * DirectXEventProc: This is the window event processing function.
  *****************************************************************************
@@ -430,23 +476,54 @@ static void DirectXCloseWindow( vout_thread_t *p_vout )
  * 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).
+ * (using the GetMessage and DispatchMessage functions).
  * Nonqueued Messages are those that Windows will send directly to this
- * function (like WM_DESTROY, WM_WINDOWPOSCHANGED...)
+ * procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...)
  *****************************************************************************/
 static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
                                          WPARAM wParam, LPARAM lParam )
 {
+    vout_thread_t *p_vout;
+
     switch( message )
     {
 
-#if 0
-    case WM_APP:
-        intf_WarnMsg( 3, "vout: WinProc WM_APP" );
+    case WM_WINDOWPOSCHANGED:
+        {
+        RECT     rect_window;
+        POINT    point_window;
+
+        p_vout = (vout_thread_t *)GetWindowLong( hwnd, GWL_USERDATA );
+
+        /* update the window position */
+        point_window.x = 0;
+        point_window.y = 0;
+        ClientToScreen( hwnd, &point_window );
+        p_vout->p_sys->i_window_x = point_window.x;
+        p_vout->p_sys->i_window_y = point_window.y;
+
+        /* update the window size */
+        GetClientRect( hwnd, &rect_window );
+        p_vout->p_sys->i_window_width = rect_window.right;
+        p_vout->p_sys->i_window_height = rect_window.bottom;
+        intf_WarnMsg( 3, "vout: WinProc WM_WINDOWPOSCHANGED %i,%i,%i,%i",
+                      p_vout->p_sys->i_window_x, p_vout->p_sys->i_window_y,
+                      p_vout->p_sys->i_window_width,
+                      p_vout->p_sys->i_window_height );
+
+        DirectXUpdateRects( p_vout );
+        if( p_vout->p_sys->b_using_overlay )
+            DirectXUpdateOverlay( p_vout );
+
+        /* signal the size change */
+        p_vout->p_sys->i_changes |= VOUT_SIZE_CHANGE;
+
+        return 0;
+        }
         break;
 
     case WM_ACTIVATE:
-        intf_WarnMsg( 4, "vout: WinProc WM_ACTIVED" );
+        intf_WarnMsg( 4, "vout: WinProc WM_ACTIVE" );
         break;
 
     case WM_CREATE:
@@ -457,7 +534,6 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
     case WM_CLOSE:
         intf_WarnMsg( 4, "vout: WinProc WM_CLOSE" );
         break;
-#endif
 
     /* the window has been closed so shut down everything now */
     case WM_DESTROY:
@@ -476,46 +552,6 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
         break;
 
 #if 0
-    case WM_MOVE:
-        intf_WarnMsg( 4, "vout: WinProc WM_MOVE" );
-        break;
-
-    case WM_SIZE:
-        intf_WarnMsg( 4, "vout: WinProc WM_SIZE" );
-        break;
-
-    case WM_MOVING:
-        intf_WarnMsg( 4, "vout: WinProc WM_MOVING" );
-        break;
-
-    case WM_ENTERSIZEMOVE:
-        intf_WarnMsg( 4, "vout: WinProc WM_ENTERSIZEMOVE" );
-        break;
-
-    case WM_SIZING:
-        intf_WarnMsg( 4, "vout: WinProc WM_SIZING" );
-        break;
-#endif
-
-    case WM_WINDOWPOSCHANGED:
-        intf_WarnMsg( 3, "vout: WinProc WM_WINDOWPOSCHANGED" );
-        b_directx_update_overlay = 1;
-        PostMessage( hwnd, WM_APP, 0, 0);
-        break;
-
-#if 0
-    case WM_WINDOWPOSCHANGING:
-        intf_WarnMsg( 3, "vout: WinProc WM_WINDOWPOSCHANGING" );
-        break;
-
-    case WM_PAINT:
-        intf_WarnMsg( 4, "vout: WinProc WM_PAINT" );
-        break;
-
-    case WM_ERASEBKGND:
-        intf_WarnMsg( 4, "vout: WinProc WM_ERASEBKGND" );
-        break;
-
     default:
         intf_WarnMsg( 4, "vout: WinProc WM Default %i", message );
         break;
index 127a09baf21b6ce6d55d4c2411f2d80ecd9927a2..2edefd3b720aa4890ce08a62cb8467b7b3b7c53a 100644 (file)
@@ -2,7 +2,7 @@
  * gtk_playlist.c : Interface for the playlist dialog
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: gtk_playlist.c,v 1.26 2002/01/07 02:12:29 sam Exp $
+ * $Id: gtk_playlist.c,v 1.27 2002/01/17 23:02:45 gbazin Exp $
  *
  * Authors: Pierre Baillet <oct@zoy.org>
  *          Stéphane Borel <stef@via.ecp.fr>
@@ -32,7 +32,7 @@
 
 #include <sys/types.h>          /* for readdir  and stat stuff */
 
-#ifndef WIN32
+#if !defined( _MSC_VER )
 #   include <dirent.h>
 #endif
 
index dbf1c2dd71868f139c939d4097517ac0d2acf85b..966906af6c5a2d72a6e8cae684d1ff767d89f219 100644 (file)
@@ -162,8 +162,8 @@ static int vout_Create( vout_thread_t *p_vout )
     p_vout->b_fullscreen = 
         main_GetIntVariable( VOUT_FULLSCREEN_VAR, VOUT_FULLSCREEN_DEFAULT );
     p_vout->p_sys->i_mode = 
-        main_GetIntVariable( VOUT_OVERLAY_VAR, VOUT_OVERLAY_DEFAULT ) ?
-        MODE_VIDEO_OVERLAY : MODE_NORMAL_MEM;
+        main_GetIntVariable( VOUT_NOOVERLAY_VAR, VOUT_NOOVERLAY_DEFAULT ) ?
+        MODE_NORMAL_MEM : MODE_VIDEO_OVERLAY;
     p_vout->p_sys->dim.w =
         main_GetIntVariable( VOUT_WIDTH_VAR, VOUT_WIDTH_DEFAULT );
     p_vout->p_sys->dim.h =
index 93b871dd8ce105540c8725b2cab74ee733f74890..6a8faf8c38b362504c3c34b2e3751ccfc7aa807e 100644 (file)
@@ -4,7 +4,7 @@
  * and spawn threads.
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: main.c,v 1.144 2002/01/09 10:22:37 sam Exp $
+ * $Id: main.c,v 1.145 2002/01/17 23:02:45 gbazin Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
 #define OPT_HEIGHT              163
 #define OPT_COLOR               164
 #define OPT_FULLSCREEN          165
-#define OPT_OVERLAY             166
+#define OPT_NOOVERLAY           166
 #define OPT_XVADAPTOR           167
 #define OPT_SMP                 168
 #define OPT_FILTER              169
@@ -182,7 +182,7 @@ static const struct option longopts[] =
     {   "idct",             1,          0,      OPT_IDCT },
     {   "yuv",              1,          0,      OPT_YUV },
     {   "fullscreen",       0,          0,      OPT_FULLSCREEN },
-    {   "overlay",          0,          0,      OPT_OVERLAY },
+    {   "nooverlay",        0,          0,      OPT_NOOVERLAY },
     {   "xvadaptor",        1,          0,      OPT_XVADAPTOR },
     {   "smp",              1,          0,      OPT_SMP },
     {   "filter",           1,          0,      OPT_FILTER },
@@ -777,8 +777,8 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
         case OPT_FULLSCREEN:                                 /* --fullscreen */
             main_PutIntVariable( VOUT_FULLSCREEN_VAR, 1 );
             break;
-        case OPT_OVERLAY:                                       /* --overlay */
-            main_PutIntVariable( VOUT_OVERLAY_VAR, 1 );
+        case OPT_NOOVERLAY:                                   /* --nooverlay */
+            main_PutIntVariable( VOUT_NOOVERLAY_VAR, 1 );
             break;
         case OPT_XVADAPTOR:                                   /* --xvadaptor */
             main_PutIntVariable( VOUT_XVADAPTOR_VAR, atoi(optarg) );
@@ -966,7 +966,7 @@ static void Usage( int i_fashion )
           "\n      --width <w>, --height <h>  \tdisplay dimensions"
           "\n  -g, --grayscale                \tgrayscale output"
           "\n      --fullscreen               \tfullscreen output"
-          "\n      --overlay                  \taccelerated display"
+          "\n      --nooverlay                \tdisable accelerated display"
           "\n      --xvadaptor <adaptor>      \tXVideo adaptor"
           "\n      --color                    \tcolor output"
           "\n      --motion <module>          \tmotion compensation method"
@@ -1041,7 +1041,7 @@ static void Usage( int i_fashion )
         "\n  " VOUT_FB_DEV_VAR "=<filename>           \tframebuffer device path"
         "\n  " VOUT_GRAYSCALE_VAR "={1|0}             \tgrayscale or color output"
         "\n  " VOUT_FULLSCREEN_VAR "={1|0}            \tfullscreen"
-        "\n  " VOUT_OVERLAY_VAR "={1|0}               \toverlay"
+        "\n  " VOUT_NOOVERLAY_VAR "={1|0}             \tnooverlay"
         "\n  " VOUT_XVADAPTOR_VAR "=<adaptor>         \tXVideo adaptor"
         "\n  " MOTION_METHOD_VAR "=<method name>      \tmotion compensation method"
         "\n  " IDCT_METHOD_VAR "=<method name>        \tIDCT method"
@@ -1445,4 +1445,3 @@ static void ShowConsole( void )
 #endif
     return;
 }
-
index 8909a034a1d7faec225aeb2cef18e0be05ec7f5f..f0fa3836636fe276ac4e076bb41f7e2301acba2a 100644 (file)
@@ -2,7 +2,7 @@
  * vout_pictures.c : picture management functions
  *****************************************************************************
  * Copyright (C) 2000 VideoLAN
- * $Id: vout_pictures.c,v 1.10 2002/01/12 01:25:57 sam Exp $
+ * $Id: vout_pictures.c,v 1.11 2002/01/17 23:02:45 gbazin Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
@@ -394,6 +394,9 @@ picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
 void vout_PlacePicture( vout_thread_t *p_vout, int i_width, int i_height,
                         int *pi_x, int *pi_y, int *pi_width, int *pi_height )
 {
+    if( (i_width <= 0) || (i_height <=0) )
+        return;
+
     if( p_vout->b_scale )
     {
         *pi_width = i_width;