vout: merged all Microsoft Windows specific vouts under msw directory in order to...
authorDamien Fouilleul <damienf@videolan.org>
Mon, 14 May 2007 12:23:55 +0000 (12:23 +0000)
committerDamien Fouilleul <damienf@videolan.org>
Mon, 14 May 2007 12:23:55 +0000 (12:23 +0000)
16 files changed:
configure.ac
modules/video_output/Modules.am
modules/video_output/directx/Modules.am [deleted file]
modules/video_output/directx/direct3d.c [deleted file]
modules/video_output/directx/directx.c [deleted file]
modules/video_output/directx/events.c [deleted file]
modules/video_output/directx/glwin32.c [deleted file]
modules/video_output/directx/vout.h [deleted file]
modules/video_output/msw/Modules.am [new file with mode: 0644]
modules/video_output/msw/direct3d.c [new file with mode: 0644]
modules/video_output/msw/directx.c [new file with mode: 0644]
modules/video_output/msw/events.c [new file with mode: 0644]
modules/video_output/msw/glwin32.c [new file with mode: 0644]
modules/video_output/msw/vout.h [new file with mode: 0644]
modules/video_output/msw/wingdi.c [new file with mode: 0755]
modules/video_output/wingdi.c [deleted file]

index 9082d62..222cd7f 100644 (file)
@@ -5916,7 +5916,7 @@ AC_CONFIG_FILES([
   modules/video_chroma/Makefile
   modules/video_filter/Makefile
   modules/video_output/Makefile
-  modules/video_output/directx/Makefile
+  modules/video_output/msw/Makefile
   modules/video_output/qte/Makefile
   modules/video_output/x11/Makefile
   modules/visualization/Makefile
index 21dcb63..de69658 100644 (file)
@@ -5,8 +5,6 @@ SOURCES_ggi = ggi.c
 SOURCES_glide = glide.c
 SOURCES_vout_sdl = sdl.c
 SOURCES_svgalib = svgalib.c
-SOURCES_wingdi = wingdi.c
-SOURCES_wingapi = wingdi.c
 SOURCES_mga = mga.c
 SOURCES_hd1000v = hd1000v.cpp
 SOURCES_snapshot = snapshot.c
diff --git a/modules/video_output/directx/Modules.am b/modules/video_output/directx/Modules.am
deleted file mode 100644 (file)
index 2db1b1e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-SOURCES_vout_directx = \
-       directx.c \
-       vout.h \
-       events.c \
-       $(NULL)
-
-SOURCES_direct3d = \
-       direct3d.c \
-       vout.h \
-       events.c \
-       $(NULL)
-
-SOURCES_glwin32 = \
-       glwin32.c \
-       vout.h \
-       events.c \
-       $(NULL)
diff --git a/modules/video_output/directx/direct3d.c b/modules/video_output/directx/direct3d.c
deleted file mode 100644 (file)
index ae3f350..0000000
+++ /dev/null
@@ -1,1524 +0,0 @@
-/*****************************************************************************
- * direct3d.c: Windows Direct3D video output module
- *****************************************************************************
- * Copyright (C) 2006 the VideoLAN team
- *$Id$
- *
- * Authors: Damien Fouilleul <damienf@videolan.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble:
- *
- * This plugin will use YUV surface if supported, using YUV will result in
- * the best video quality (hardware filering when rescaling the picture)
- * and the fastest display as it requires less processing.
- *
- * If YUV overlay is not supported this plugin will use RGB offscreen video
- * surfaces that will be blitted onto the primary surface (display) to
- * effectively display the pictures.
- *
- *****************************************************************************/
-#include <errno.h>                                                 /* ENOMEM */
-#include <stdlib.h>                                                /* free() */
-#include <string.h>                                            /* strerror() */
-
-#include <vlc/vlc.h>
-#include <vlc_interface.h>
-#include <vlc_playlist.h>
-#include <vlc_vout.h>
-
-#include <windows.h>
-#include <d3d9.h>
-
-#include "vout.h"
-
-/*****************************************************************************
- * Local prototypes.
- *****************************************************************************/
-static int  OpenVideo  ( vlc_object_t * );
-static void CloseVideo ( vlc_object_t * );
-
-static int  Init      ( vout_thread_t * );
-static void End       ( vout_thread_t * );
-static int  Manage    ( vout_thread_t * );
-static void Display   ( vout_thread_t *, picture_t * );
-static void FirstDisplay( vout_thread_t *, picture_t * );
-
-static int Direct3DVoutCreate     ( vout_thread_t * );
-static void Direct3DVoutRelease   ( vout_thread_t * );
-
-static int  Direct3DVoutOpen      ( vout_thread_t * );
-static void Direct3DVoutClose     ( vout_thread_t * );
-
-static int Direct3DVoutResetDevice( vout_thread_t * );
-
-static int Direct3DVoutCreatePictures   ( vout_thread_t *, size_t );
-static void Direct3DVoutReleasePictures ( vout_thread_t * );
-
-static int Direct3DVoutLockSurface  ( vout_thread_t *, picture_t * );
-static int Direct3DVoutUnlockSurface( vout_thread_t *, picture_t * );
-
-static int Direct3DVoutCreateScene      ( vout_thread_t * );
-static void Direct3DVoutReleaseScene    ( vout_thread_t * );
-static void Direct3DVoutRenderScene     ( vout_thread_t *, picture_t * );
-
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-
-static vlc_bool_t _got_vista_or_above;
-
-static int get_capability_for_osversion(void)
-{
-    OSVERSIONINFO winVer;
-    winVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-
-    if( GetVersionEx(&winVer) )
-    {
-        if( winVer.dwMajorVersion > 5 )
-        {
-            /* Windows Vista or above, make this module the default */
-           _got_vista_or_above = VLC_TRUE;
-            return 150;
-        }
-    }
-    /* Windows XP or lower, make sure this module isn't the default */
-    _got_vista_or_above = VLC_FALSE;
-    return 50;
-}
-
-vlc_module_begin();
-    set_shortname( "Direct3D" );
-    set_category( CAT_VIDEO );
-    set_subcategory( SUBCAT_VIDEO_VOUT );
-    set_description( _("DirectX 3D video output") );
-    set_capability( "video output", get_capability_for_osversion() );
-    add_shortcut( "direct3d" );
-    set_callbacks( OpenVideo, CloseVideo );
-
-    /* FIXME: Hack to avoid unregistering our window class */
-    linked_with_a_crap_library_which_uses_atexit( );
-vlc_module_end();
-
-#if 0 /* FIXME */
-    /* check if we registered a window class because we need to
-     * unregister it */
-    WNDCLASS wndclass;
-    if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )
-        UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );
-#endif
-
-/*****************************************************************************
- * CUSTOMVERTEX: 
- *****************************************************************************
- *****************************************************************************/
-typedef struct 
-{
-    FLOAT       x,y,z;      // vertex untransformed position 
-    FLOAT       rhw;        // eye distance
-    D3DCOLOR    diffuse;    // diffuse color
-    FLOAT       tu, tv;     // texture relative coordinates
-} CUSTOMVERTEX;
-
-#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
-
-/*****************************************************************************
- * OpenVideo: allocate DirectX video thread output method
- *****************************************************************************
- * This function allocates and initialize the Direct3D vout method.
- *****************************************************************************/
-static int OpenVideo( vlc_object_t *p_this )
-{
-    vout_thread_t * p_vout = (vout_thread_t *)p_this;
-    vlc_value_t val;
-
-    /* Allocate structure */
-    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
-    if( p_vout->p_sys == NULL )
-    {
-        msg_Err( p_vout, "out of memory" );
-        return VLC_ENOMEM;
-    }
-    memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
-
-    if( VLC_SUCCESS != Direct3DVoutCreate( p_vout ) )
-    {
-        msg_Err( p_vout, "Direct3D could not be initialized !");
-        goto error;
-    }
-
-    /* Initialisations */
-    p_vout->pf_init = Init;
-    p_vout->pf_end = End;
-    p_vout->pf_manage = Manage;
-    p_vout->pf_render = Direct3DVoutRenderScene;
-    p_vout->pf_display = FirstDisplay;
-
-    p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
-    p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
-    p_vout->p_sys->i_changes = 0;
-    p_vout->p_sys->b_wallpaper = 0;
-    vlc_mutex_init( p_vout, &p_vout->p_sys->lock );
-    SetRectEmpty( &p_vout->p_sys->rect_display );
-    SetRectEmpty( &p_vout->p_sys->rect_parent );
-
-    var_Create( p_vout, "directx-hw-yuv", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "directx-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
-
-    p_vout->p_sys->b_cursor_hidden = 0;
-    p_vout->p_sys->i_lastmoved = mdate();
-
-    var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
-
-    /* Set main window's size */
-    p_vout->p_sys->i_window_width = p_vout->i_window_width;
-    p_vout->p_sys->i_window_height = p_vout->i_window_height;
-
-    /* Create the DirectXEventThread, this thread is created by us to isolate
-     * the Win32 PeekMessage function calls. We want to do this because
-     * Windows can stay blocked inside this call for a long time, and when
-     * this happens it thus blocks vlc's video_output thread.
-     * DirectXEventThread will take care of the creation of the video
-     * window (because PeekMessage has to be called from the same thread which
-     * created the window). */
-    msg_Dbg( p_vout, "creating DirectXEventThread" );
-    p_vout->p_sys->p_event =
-        vlc_object_create( p_vout, sizeof(event_thread_t) );
-    p_vout->p_sys->p_event->p_vout = p_vout;
-    if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread",
-                           E_(DirectXEventThread), 0, 1 ) )
-    {
-        msg_Err( p_vout, "cannot create DirectXEventThread" );
-        vlc_object_destroy( p_vout->p_sys->p_event );
-        p_vout->p_sys->p_event = NULL;
-        goto error;
-    }
-
-    if( p_vout->p_sys->p_event->b_error )
-    {
-        msg_Err( p_vout, "DirectXEventThread failed" );
-        goto error;
-    }
-
-    vlc_object_attach( p_vout->p_sys->p_event, p_vout );
-
-    msg_Dbg( p_vout, "DirectXEventThread running" );
-
-    /* Variable to indicate if the window should be on top of others */
-    /* Trigger a callback right now */
-    var_Get( p_vout, "video-on-top", &val );
-    var_Set( p_vout, "video-on-top", val );
-
-    /* disable screensaver by temporarily changing system settings */
-    p_vout->p_sys->i_spi_lowpowertimeout = 0;
-    p_vout->p_sys->i_spi_powerofftimeout = 0;
-    p_vout->p_sys->i_spi_screensavetimeout = 0;
-    var_Get( p_vout, "disable-screensaver", &val);
-    if( val.b_bool ) {
-        msg_Dbg(p_vout, "disabling screen saver");
-        SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT,
-            0, &(p_vout->p_sys->i_spi_lowpowertimeout), 0);
-        if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {
-            SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0);
-        }
-        SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0,
-            &(p_vout->p_sys->i_spi_powerofftimeout), 0);
-        if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
-            SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, 0, NULL, 0);
-        }
-        SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0,
-            &(p_vout->p_sys->i_spi_screensavetimeout), 0);
-        if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {
-            SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 0, NULL, 0);
-        }
-    }
-    return VLC_SUCCESS;
-
- error:
-    CloseVideo( VLC_OBJECT(p_vout) );
-    return VLC_EGENERIC;
-}
-
-/*****************************************************************************
- * CloseVideo: destroy Sys video thread output method
- *****************************************************************************
- * Terminate an output method created by Create
- *****************************************************************************/
-static void CloseVideo( vlc_object_t *p_this )
-{
-    vout_thread_t * p_vout = (vout_thread_t *)p_this;
-
-    Direct3DVoutRelease( p_vout );
-
-    if( p_vout->p_sys->p_event )
-    {
-        vlc_object_detach( p_vout->p_sys->p_event );
-
-        /* Kill DirectXEventThread */
-        p_vout->p_sys->p_event->b_die = VLC_TRUE;
-
-        /* we need to be sure DirectXEventThread won't stay stuck in
-         * GetMessage, so we send a fake message */
-        if( p_vout->p_sys->hwnd )
-        {
-            PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);
-        }
-
-        vlc_thread_join( p_vout->p_sys->p_event );
-        vlc_object_destroy( p_vout->p_sys->p_event );
-    }
-
-    vlc_mutex_destroy( &p_vout->p_sys->lock );
-
-    /* restore screensaver system settings */
-    if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {
-        SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT,
-            p_vout->p_sys->i_spi_lowpowertimeout, NULL, 0);
-    }
-    if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
-        SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT,
-            p_vout->p_sys->i_spi_powerofftimeout, NULL, 0);
-    }
-    if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {
-        SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT,
-            p_vout->p_sys->i_spi_screensavetimeout, NULL, 0);
-    }
-
-    if( p_vout->p_sys )
-    {
-        free( p_vout->p_sys );
-        p_vout->p_sys = NULL;
-    }
-}
-
-/*****************************************************************************
- * Init: initialize Direct3D video thread output method
- *****************************************************************************/
-static int Init( vout_thread_t *p_vout )
-{
-    int i_ret;
-    vlc_value_t val;
-
-    var_Get( p_vout, "directx-hw-yuv", &val );
-    p_vout->p_sys->b_hw_yuv = val.b_bool;
-
-    /* Initialise Direct3D */
-    if( VLC_SUCCESS != Direct3DVoutOpen( p_vout ) )
-    {
-        msg_Err( p_vout, "cannot initialize Direct3D" );
-        return VLC_EGENERIC;
-    }
-
-    /* Initialize the output structure.
-     * Since Direct3D 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;
-    p_vout->fmt_out = p_vout->fmt_in;
-    E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
-
-    /*  create picture pool */
-    i_ret = Direct3DVoutCreatePictures(p_vout, 1);
-    if( VLC_SUCCESS != i_ret )
-    {
-        msg_Err(p_vout, "Direct3D picture pool initialization failed !");
-        return i_ret;
-    }
-
-    /* create scene */
-    i_ret = Direct3DVoutCreateScene(p_vout);
-    if( VLC_SUCCESS != i_ret )
-    {
-        msg_Err(p_vout, "Direct3D scene initialization failed !");
-        Direct3DVoutReleasePictures(p_vout);
-        return i_ret;
-    }
-
-    /* Change the window title bar text */
-    PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
-
-    p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * End: terminate Sys video thread output method
- *****************************************************************************
- * Terminate an output method created by Create.
- * It is called at the end of the thread.
- *****************************************************************************/
-static void End( vout_thread_t *p_vout )
-{
-    Direct3DVoutReleaseScene(p_vout);
-    Direct3DVoutReleasePictures(p_vout);
-    Direct3DVoutClose( p_vout );
-}
-
-/*****************************************************************************
- * Manage: handle Sys events
- *****************************************************************************
- * This function should be called regularly by the video output thread.
- * It returns a non null value if an error occurred.
- *****************************************************************************/
-static int Manage( vout_thread_t *p_vout )
-{
-    /* If we do not control our window, we check for geometry changes
-     * ourselves because the parent might not send us its events. */
-    vlc_mutex_lock( &p_vout->p_sys->lock );
-    if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
-    {
-        RECT rect_parent;
-        POINT point;
-
-        vlc_mutex_unlock( &p_vout->p_sys->lock );
-
-        GetClientRect( p_vout->p_sys->hparent, &rect_parent );
-        point.x = point.y = 0;
-        ClientToScreen( p_vout->p_sys->hparent, &point );
-        OffsetRect( &rect_parent, point.x, point.y );
-
-        if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
-        {
-            p_vout->p_sys->rect_parent = rect_parent;
-
-            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
-                          rect_parent.right - rect_parent.left,
-                          rect_parent.bottom - rect_parent.top,
-                          SWP_NOZORDER );
-        }
-    }
-    else
-    {
-        vlc_mutex_unlock( &p_vout->p_sys->lock );
-    }
-
-    /*
-     * Position Change
-     */
-    if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE )
-    {
-#if 0 /* need that when bicubic filter is available */
-        RECT rect;
-        UINT width, height;
-
-        GetClientRect(p_vout->p_sys->hvideownd, &rect);
-        width  = rect.right-rect.left;
-        height = rect.bottom-rect.top;
-
-        if( (width != p_vout->p_sys->d3dpp.BackBufferWidth)
-         || (height != p_vout->p_sys->d3dpp.BackBufferHeight) )
-        {
-            msg_Dbg(p_vout, "resizing device back buffers to (%lux%lu)", width, height);
-            // need to reset D3D device to resize back buffer
-            if( VLC_SUCCESS != Direct3DVoutResetDevice(p_vout, width, height) )
-                return VLC_EGENERIC;
-        }
-#endif
-        p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
-    }
-
-    /* Check for cropping / aspect changes */
-    if( p_vout->i_changes & VOUT_CROP_CHANGE ||
-        p_vout->i_changes & VOUT_ASPECT_CHANGE )
-    {
-        p_vout->i_changes &= ~VOUT_CROP_CHANGE;
-        p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
-
-        p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset;
-        p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset;
-        p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width;
-        p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height;
-        p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect;
-        p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;
-        p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;
-        p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
-        E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
-    }
-
-    /* We used to call the Win32 PeekMessage function here to read the window
-     * messages. But since window can stay blocked into this function for a
-     * long time (for example when you move your window on the screen), I
-     * decided to isolate PeekMessage in another thread. */
-
-    /*
-     * Fullscreen change
-     */
-    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
-        || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
-    {
-        Win32ToggleFullscreen( p_vout );
-
-        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
-        p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
-    }
-
-    /*
-     * Pointer change
-     */
-    if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&
-        (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 )
-    {
-        POINT point;
-        HWND hwnd;
-
-        /* Hide the cursor only if it is inside our window */
-        GetCursorPos( &point );
-        hwnd = WindowFromPoint(point);
-        if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )
-        {
-            PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
-        }
-        else
-        {
-            p_vout->p_sys->i_lastmoved = mdate();
-        }
-    }
-
-    /*
-     * "Always on top" status change
-     */
-    if( p_vout->p_sys->b_on_top_change )
-    {
-        vlc_value_t val;
-        HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
-
-        var_Get( p_vout, "video-on-top", &val );
-
-        /* Set the window on top if necessary */
-        if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
-                           & WS_EX_TOPMOST ) )
-        {
-            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
-                           MF_BYCOMMAND | MFS_CHECKED );
-            SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,
-                          SWP_NOSIZE | SWP_NOMOVE );
-        }
-        else
-        /* The window shouldn't be on top */
-        if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
-                           & WS_EX_TOPMOST ) )
-        {
-            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
-                           MF_BYCOMMAND | MFS_UNCHECKED );
-            SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
-                          SWP_NOSIZE | SWP_NOMOVE );
-        }
-
-        p_vout->p_sys->b_on_top_change = VLC_FALSE;
-    }
-
-    /* Check if the event thread is still running */
-    if( p_vout->p_sys->p_event->b_die )
-    {
-        return VLC_EGENERIC; /* exit */
-    }
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Display: displays previously rendered output
- *****************************************************************************
- * 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 Display( vout_thread_t *p_vout, picture_t *p_pic )
-{
-    LPDIRECT3DDEVICE9       p_d3ddev = p_vout->p_sys->p_d3ddev;
-    // Present the back buffer contents to the display
-    // stretching and filtering happens here
-    HRESULT hr = IDirect3DDevice9_Present(p_d3ddev,
-                    &(p_vout->p_sys->rect_src_clipped),
-                    NULL, NULL, NULL);
-    if( FAILED(hr) )
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-}
-
-/*
-** this function is only used once when the first picture is received
-** this function will show the video window once a picture is ready
-*/
-
-static void FirstDisplay( vout_thread_t *p_vout, picture_t *p_pic )
-{
-    /* get initial picture presented through D3D */
-    Display(p_vout, p_pic);
-
-    /*
-    ** Video window is initially hidden, show it now since we got a 
-    ** picture to show.
-    */
-    SetWindowPos( p_vout->p_sys->hvideownd, 0, 0, 0, 0, 0, 
-        SWP_ASYNCWINDOWPOS|
-        SWP_FRAMECHANGED|
-        SWP_SHOWWINDOW|
-        SWP_NOMOVE|
-        SWP_NOSIZE|
-        SWP_NOZORDER );
-
-    /* use and restores proper display function for further pictures */
-    p_vout->pf_display = Display;
-}
-
-/*****************************************************************************
- * DirectD3DVoutCreate: Initialize and instance of Direct3D9 
- *****************************************************************************
- * This function initialize Direct3D and analyze available resources from
- * default adapter.
- *****************************************************************************/
-static int Direct3DVoutCreate( vout_thread_t *p_vout )
-{
-    HRESULT hr;
-    LPDIRECT3D9 p_d3dobj;
-    D3DCAPS9 d3dCaps;
-
-    LPDIRECT3D9 (WINAPI *OurDirect3DCreate9)(UINT SDKVersion);
-
-    p_vout->p_sys->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
-    if( NULL == p_vout->p_sys->hd3d9_dll )
-    {
-        msg_Warn( p_vout, "cannot load d3d9.dll, aborting" );
-        return VLC_EGENERIC;
-    }
-
-    OurDirect3DCreate9 =
-      (void *)GetProcAddress( p_vout->p_sys->hd3d9_dll,
-                              TEXT("Direct3DCreate9") );
-    if( OurDirect3DCreate9 == NULL )
-    {
-        msg_Err( p_vout, "Cannot locate reference to Direct3DCreate9 ABI in DLL" );
-        return VLC_EGENERIC;
-    }
-
-    /* Create the D3D object. */
-    p_d3dobj = OurDirect3DCreate9( D3D_SDK_VERSION );
-    if( NULL == p_d3dobj )
-    {
-       msg_Err( p_vout, "Could not create Direct3D9 instance.");
-       return VLC_EGENERIC;
-    }
-    p_vout->p_sys->p_d3dobj = p_d3dobj;
-
-    /*
-    ** Get device capabilities
-    */
-    ZeroMemory(&d3dCaps, sizeof(d3dCaps));
-    hr = IDirect3D9_GetDeviceCaps(p_d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps);
-    if( FAILED(hr) )
-    {
-       msg_Err( p_vout, "Could not read adapter capabilities. (hr=0x%lX)", hr);
-       return VLC_EGENERIC;
-    }
-    /* TODO: need to test device capabilities and select the right render function */
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * DirectD3DVoutRelease: release an instance of Direct3D9
- *****************************************************************************/
-
-static void Direct3DVoutRelease( vout_thread_t *p_vout )
-{
-    if( p_vout->p_sys->p_d3dobj )
-    {
-       IDirect3D9_Release(p_vout->p_sys->p_d3dobj);
-       p_vout->p_sys->p_d3dobj = NULL;
-    }
-    if( NULL != p_vout->p_sys->hd3d9_dll )
-    {
-        FreeLibrary(p_vout->p_sys->hd3d9_dll);
-        p_vout->p_sys->hd3d9_dll = NULL;
-    }
-}
-
-static int Direct3DFillPresentationParameters(vout_thread_t *p_vout, D3DPRESENT_PARAMETERS *d3dpp)
-{
-    LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj;
-    D3DDISPLAYMODE d3ddm;
-    HRESULT hr;
-
-    /*
-    ** Get the current desktop display mode, so we can set up a back
-    ** buffer of the same format
-    */
-    hr = IDirect3D9_GetAdapterDisplayMode(p_d3dobj, D3DADAPTER_DEFAULT, &d3ddm );
-    if( FAILED(hr))
-    {
-       msg_Err( p_vout, "Could not read adapter display mode. (hr=0x%lX)", hr);
-       return VLC_EGENERIC;
-    }
-
-    /* keep a copy of current desktop format */
-    p_vout->p_sys->bbFormat = d3ddm.Format;
-
-    /* Set up the structure used to create the D3DDevice. */
-    ZeroMemory( d3dpp, sizeof(D3DPRESENT_PARAMETERS) );
-    d3dpp->Flags                  = D3DPRESENTFLAG_VIDEO;
-    d3dpp->Windowed               = TRUE;
-    d3dpp->hDeviceWindow          = p_vout->p_sys->hvideownd;
-    d3dpp->BackBufferWidth        = p_vout->output.i_width;
-    d3dpp->BackBufferHeight       = p_vout->output.i_height;
-    d3dpp->SwapEffect             = D3DSWAPEFFECT_COPY;
-    d3dpp->MultiSampleType        = D3DMULTISAMPLE_NONE;
-    d3dpp->PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT;
-    d3dpp->BackBufferFormat       = d3ddm.Format;
-    d3dpp->BackBufferCount        = 1;
-    d3dpp->EnableAutoDepthStencil = FALSE;
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * DirectD3DVoutOpen: Takes care of all the Direct3D9 initialisations
- *****************************************************************************
- * This function creates Direct3D device
- * this must be called from the vout thread for performance reason, as
- * all Direct3D Device APIs are used in a non multithread safe environment
- *****************************************************************************/
-static int Direct3DVoutOpen( vout_thread_t *p_vout )
-{
-    LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj;
-    LPDIRECT3DDEVICE9 p_d3ddev;
-    D3DPRESENT_PARAMETERS d3dpp;
-    HRESULT hr;
-
-    if( VLC_SUCCESS != Direct3DFillPresentationParameters(p_vout, &d3dpp) )
-        return VLC_EGENERIC;
-
-    // Create the D3DDevice
-    hr = IDirect3D9_CreateDevice(p_d3dobj, D3DADAPTER_DEFAULT,
-                                 D3DDEVTYPE_HAL, p_vout->p_sys->hvideownd,
-                                 D3DCREATE_SOFTWARE_VERTEXPROCESSING,
-                                 &d3dpp, &p_d3ddev );
-    if( FAILED(hr) )                                      
-    {
-       msg_Err(p_vout, "Could not create the D3D device! (hr=0x%lX)", hr);
-       return VLC_EGENERIC;
-    }
-    p_vout->p_sys->p_d3ddev = p_d3ddev;
-
-    msg_Dbg( p_vout, "Direct3D device adapter successfully initialized" );
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * DirectD3DClose: release the Direct3D9 device 
- *****************************************************************************/
-static void Direct3DVoutClose( vout_thread_t *p_vout )
-{
-    if( p_vout->p_sys->p_d3ddev )
-    {
-       IDirect3DDevice9_Release(p_vout->p_sys->p_d3ddev);
-       p_vout->p_sys->p_d3ddev = NULL;
-    }
-       
-    p_vout->p_sys->hmonitor = NULL;
-}
-
-/*****************************************************************************
- * DirectD3DClose: reset the Direct3D9 device 
- *****************************************************************************
- * All resources must be deallocated before the reset occur, they will be
- * realllocated once the reset has been performed successfully
- *****************************************************************************/
-static int Direct3DVoutResetDevice( vout_thread_t *p_vout )
-{
-    LPDIRECT3DDEVICE9       p_d3ddev = p_vout->p_sys->p_d3ddev;
-    D3DPRESENT_PARAMETERS   d3dpp;
-    HRESULT hr;
-
-    if( VLC_SUCCESS != Direct3DFillPresentationParameters(p_vout, &d3dpp) )
-        return VLC_EGENERIC;
-
-    // release all D3D objects
-    Direct3DVoutReleaseScene( p_vout );
-    Direct3DVoutReleasePictures( p_vout );
-
-    hr = IDirect3DDevice9_Reset(p_d3ddev, &d3dpp);
-    if( SUCCEEDED(hr) )
-    {
-        // re-create them
-        if( (VLC_SUCCESS != Direct3DVoutCreatePictures(p_vout, 1))
-         || (VLC_SUCCESS != Direct3DVoutCreateScene(p_vout)) )
-        {
-            msg_Dbg(p_vout, "%s failed !", __FUNCTION__);
-            return VLC_EGENERIC;
-        }
-    }
-    else {
-        msg_Err(p_vout, "%s failed ! (hr=%08lX)", __FUNCTION__, hr);
-        return VLC_EGENERIC;
-    }
-    return VLC_SUCCESS;
-}
-
-static D3DFORMAT Direct3DVoutSelectFormat( vout_thread_t *p_vout, D3DFORMAT target,
-    const D3DFORMAT *formats, size_t count)
-{
-    LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj;
-    size_t c;
-
-    for( c=0; c<count; ++c )
-    {
-        HRESULT hr;
-        D3DFORMAT format = formats[c];
-        /* test whether device can create a surface of that format */
-        hr = IDirect3D9_CheckDeviceFormat(p_d3dobj, D3DADAPTER_DEFAULT,
-                D3DDEVTYPE_HAL, target, 0, D3DRTYPE_SURFACE, format);
-        if( SUCCEEDED(hr) )
-        {
-            /* test whether device can perform color-conversion
-            ** from that format to target format
-            */
-            hr = IDirect3D9_CheckDeviceFormatConversion(p_d3dobj,
-                    D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
-                    format, target);
-        }
-        if( SUCCEEDED(hr) )
-        {
-            // found a compatible format
-            switch( format )
-            {
-                case D3DFMT_UYVY:
-                    msg_Dbg( p_vout, "selected surface pixel format is UYVY");
-                    break;
-                case D3DFMT_YUY2:
-                    msg_Dbg( p_vout, "selected surface pixel format is YUY2");
-                    break;
-                case D3DFMT_X8R8G8B8:
-                    msg_Dbg( p_vout, "selected surface pixel format is X8R8G8B8");
-                    break;
-                case D3DFMT_A8R8G8B8:
-                    msg_Dbg( p_vout, "selected surface pixel format is A8R8G8B8");
-                    break;
-                case D3DFMT_R8G8B8:
-                    msg_Dbg( p_vout, "selected surface pixel format is R8G8B8");
-                    break;
-                case D3DFMT_R5G6B5:
-                    msg_Dbg( p_vout, "selected surface pixel format is R5G6B5");
-                    break;
-                case D3DFMT_X1R5G5B5:
-                    msg_Dbg( p_vout, "selected surface pixel format is X1R5G5B5");
-                    break;
-                default:
-                    msg_Dbg( p_vout, "selected surface pixel format is 0x%0X", format);
-                    break;
-            }
-            return format;
-        }
-        else if( D3DERR_NOTAVAILABLE != hr )
-        {
-            msg_Err( p_vout, "Could not query adapter supported formats. (hr=0x%lX)", hr);
-            break;
-        }
-    }
-    return D3DFMT_UNKNOWN;
-}
-
-static D3DFORMAT Direct3DVoutFindFormat(vout_thread_t *p_vout, int i_chroma, D3DFORMAT target)
-{
-    if( p_vout->p_sys->b_hw_yuv && ! _got_vista_or_above )
-    {
-       /* it sounds like vista does not support YUV surfaces at all */
-        switch( i_chroma )
-        {
-            case VLC_FOURCC('U','Y','V','Y'):
-            case VLC_FOURCC('U','Y','N','V'):
-            case VLC_FOURCC('Y','4','2','2'):
-            {
-                static const D3DFORMAT formats[] =
-                    { D3DFMT_UYVY, D3DFMT_YUY2, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };
-                return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
-            }
-            case VLC_FOURCC('I','4','2','0'):
-            case VLC_FOURCC('I','4','2','2'):
-            case VLC_FOURCC('Y','V','1','2'):
-            {
-                /* typically 3D textures don't support planar format
-                ** fallback to packed version and use CPU for the conversion
-                */
-                static const D3DFORMAT formats[] = 
-                    { D3DFMT_YUY2, D3DFMT_UYVY, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };
-                return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
-            }
-            case VLC_FOURCC('Y','U','Y','2'):
-            case VLC_FOURCC('Y','U','N','V'):
-            {
-                static const D3DFORMAT formats[] = 
-                    { D3DFMT_YUY2, D3DFMT_UYVY, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };
-                return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
-            }
-        }
-    }
-
-    switch( i_chroma )
-    {
-        case VLC_FOURCC('R', 'V', '1', '5'):
-        {
-            static const D3DFORMAT formats[] = 
-                { D3DFMT_X1R5G5B5 };
-            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
-        }
-        case VLC_FOURCC('R', 'V', '1', '6'):
-        {
-            static const D3DFORMAT formats[] = 
-                { D3DFMT_R5G6B5 };
-            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
-        }
-        case VLC_FOURCC('R', 'V', '2', '4'):
-        {
-            static const D3DFORMAT formats[] = 
-                { D3DFMT_R8G8B8, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8 };
-            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
-        }
-        case VLC_FOURCC('R', 'V', '3', '2'):
-        {
-            static const D3DFORMAT formats[] = 
-                { D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 };
-            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
-        }
-        default:
-        {
-            /* use display default format */
-            LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj;
-            D3DDISPLAYMODE d3ddm;
-
-            HRESULT hr = IDirect3D9_GetAdapterDisplayMode(p_d3dobj, D3DADAPTER_DEFAULT, &d3ddm );
-            if( SUCCEEDED(hr))
-            {
-                /*
-                ** some professional cards could use some advanced pixel format as default, 
-                ** make sure we stick with chromas that we can handle internally
-                */
-                switch( d3ddm.Format )
-                {
-                    case D3DFMT_R8G8B8:
-                    case D3DFMT_X8R8G8B8:
-                    case D3DFMT_A8R8G8B8:
-                        msg_Dbg( p_vout, "defaulting to adpater pixel format");
-                        return Direct3DVoutSelectFormat(p_vout, target, &d3ddm.Format, 1);
-                    default:
-                    {
-                        /* if we fall here, that probably means that we need to render some YUV format */
-                        static const D3DFORMAT formats[] = 
-                            { D3DFMT_R8G8B8, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8 };
-                        msg_Dbg( p_vout, "defaulting to built-in pixel format");
-                        return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
-                    }
-                }
-            }
-        }
-    }
-    return D3DFMT_UNKNOWN;
-}
-
-static int Direct3DVoutSetOutputFormat(vout_thread_t *p_vout, D3DFORMAT format)
-{
-    switch( format )
-    {
-        case D3DFMT_YUY2:
-            p_vout->output.i_chroma = VLC_FOURCC('Y', 'U', 'Y', '2');
-            break;
-        case D3DFMT_UYVY:
-            p_vout->output.i_chroma = VLC_FOURCC('U', 'Y', 'V', 'Y');
-            break;
-        case D3DFMT_R8G8B8:
-            p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '2', '4');
-            break;
-        case D3DFMT_X8R8G8B8:
-        case D3DFMT_A8R8G8B8:
-            p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '3', '2');
-            p_vout->output.i_rmask = 0x00ff0000;
-            p_vout->output.i_gmask = 0x0000ff00;
-            p_vout->output.i_bmask = 0x000000ff;
-#       if defined( WORDS_BIGENDIAN )
-            p_vout->output.i_rrshift = 0;
-            p_vout->output.i_lrshift = 24;
-            p_vout->output.i_rgshift = 0;
-            p_vout->output.i_lgshift = 16;
-            p_vout->output.i_rbshift = 0;
-            p_vout->output.i_lbshift = 8;
-#       else
-            p_vout->output.i_rrshift = 0;
-            p_vout->output.i_lrshift = 8;
-            p_vout->output.i_rgshift = 0;
-            p_vout->output.i_lgshift = 16;
-            p_vout->output.i_rbshift = 0;
-            p_vout->output.i_lbshift = 24;
-#       endif
-            break;
-        case D3DFMT_R5G6B5:
-            p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '1', '6');
-            p_vout->output.i_rmask = (0x1fL)<<11;
-            p_vout->output.i_gmask = (0x3fL)<<5;
-            p_vout->output.i_bmask = (0x1fL)<<0;
-#       if defined( WORDS_BIGENDIAN )
-            p_vout->output.i_rrshift = 0;
-            p_vout->output.i_lrshift = 11;
-            p_vout->output.i_rgshift = 0;
-            p_vout->output.i_lgshift = 5;
-            p_vout->output.i_rbshift = 0;
-            p_vout->output.i_lbshift = 0;
-#       else
-            /* FIXME: since components are not byte aligned,
-                      there is no chance that this will work */
-            p_vout->output.i_rrshift = 0;
-            p_vout->output.i_lrshift = 0;
-            p_vout->output.i_rgshift = 0;
-            p_vout->output.i_lgshift = 5;
-            p_vout->output.i_rbshift = 0;
-            p_vout->output.i_lbshift = 11;
-#       endif
-            break;
-        case D3DFMT_X1R5G5B5:
-            p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '1', '5');
-            p_vout->output.i_rmask = (0x1fL)<<10;
-            p_vout->output.i_gmask = (0x1fL)<<5;
-            p_vout->output.i_bmask = (0x1fL)<<0;
-#       if defined( WORDS_BIGENDIAN )
-            p_vout->output.i_rrshift = 0;
-            p_vout->output.i_lrshift = 10;
-            p_vout->output.i_rgshift = 0;
-            p_vout->output.i_lgshift = 5;
-            p_vout->output.i_rbshift = 0;
-            p_vout->output.i_lbshift = 0;
-#       else
-            /* FIXME: since components are not byte aligned,
-                      there is no chance that this will work */
-            p_vout->output.i_rrshift = 0;
-            p_vout->output.i_lrshift = 1;
-            p_vout->output.i_rgshift = 0;
-            p_vout->output.i_lgshift = 5;
-            p_vout->output.i_rbshift = 0;
-            p_vout->output.i_lbshift = 11;
-#       endif
-            break;
-        default:
-            return VLC_EGENERIC;
-    }
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Direct3DVoutCreatePictures: allocate a vector of identical pictures
- *****************************************************************************
- * Each picture has an associated offscreen surface in video memory
- * depending on hardware capabilities the picture chroma will be as close
- * as possible to the orginal render chroma to reduce CPU conversion overhead
- * and delegate this work to video card GPU
- *****************************************************************************/
-static int Direct3DVoutCreatePictures( vout_thread_t *p_vout, size_t i_num_pics )
-{
-    LPDIRECT3DDEVICE9       p_d3ddev  = p_vout->p_sys->p_d3ddev;
-    D3DFORMAT               format;
-    HRESULT hr;
-    size_t c;
-
-    I_OUTPUTPICTURES = 0;
-
-    /*
-    ** find the appropriate D3DFORMAT for the render chroma, the format will be the closest to
-    ** the requested chroma which is usable by the hardware in an offscreen surface, as they
-    ** typically support more formats than textures
-    */ 
-    format = Direct3DVoutFindFormat(p_vout, p_vout->render.i_chroma, p_vout->p_sys->bbFormat);
-    if( VLC_SUCCESS != Direct3DVoutSetOutputFormat(p_vout, format) )
-    {
-        msg_Err(p_vout, "surface pixel format is not supported.");
-        return VLC_EGENERIC;
-    }
-
-    for( c=0; c<i_num_pics; )
-    {
-
-        LPDIRECT3DSURFACE9 p_d3dsurf;
-        picture_t *p_pic = p_vout->p_picture+c; 
-
-        hr = IDirect3DDevice9_CreateOffscreenPlainSurface(p_d3ddev, 
-                p_vout->render.i_width,
-                p_vout->render.i_height,
-                format,
-                D3DPOOL_DEFAULT,
-                &p_d3dsurf,
-                NULL);
-        if( FAILED(hr) )
-        {
-            msg_Err(p_vout, "Failed to create picture surface. (hr=0x%lx)", hr);
-            Direct3DVoutReleasePictures(p_vout);
-            return VLC_EGENERIC;
-        }
-
-        /* fill surface with black color */
-        IDirect3DDevice9_ColorFill(p_d3ddev, p_d3dsurf, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0) );
-        
-        /* assign surface to internal structure */
-        p_pic->p_sys = (void *)p_d3dsurf;
-
-        /* Now that we've got our direct-buffer, we can finish filling in the
-         * picture_t structures */
-        switch( p_vout->output.i_chroma )
-        {
-            case VLC_FOURCC('R','G','B','2'):
-                p_pic->p->i_lines = p_vout->output.i_height;
-                p_pic->p->i_visible_lines = p_vout->output.i_height;
-                p_pic->p->i_pixel_pitch = 1;
-                p_pic->p->i_visible_pitch = p_vout->output.i_width *
-                    p_pic->p->i_pixel_pitch;
-                p_pic->i_planes = 1;
-            break;
-            case VLC_FOURCC('R','V','1','5'):
-            case VLC_FOURCC('R','V','1','6'):
-                p_pic->p->i_lines = p_vout->output.i_height;
-                p_pic->p->i_visible_lines = p_vout->output.i_height;
-                p_pic->p->i_pixel_pitch = 2;
-                p_pic->p->i_visible_pitch = p_vout->output.i_width *
-                    p_pic->p->i_pixel_pitch;
-                p_pic->i_planes = 1;
-            break;
-            case VLC_FOURCC('R','V','2','4'):
-                p_pic->p->i_lines = p_vout->output.i_height;
-                p_pic->p->i_visible_lines = p_vout->output.i_height;
-                p_pic->p->i_pixel_pitch = 3;
-                p_pic->p->i_visible_pitch = p_vout->output.i_width *
-                    p_pic->p->i_pixel_pitch;
-                p_pic->i_planes = 1;
-            break;
-            case VLC_FOURCC('R','V','3','2'):
-                p_pic->p->i_lines = p_vout->output.i_height;
-                p_pic->p->i_visible_lines = p_vout->output.i_height;
-                p_pic->p->i_pixel_pitch = 4;
-                p_pic->p->i_visible_pitch = p_vout->output.i_width *
-                    p_pic->p->i_pixel_pitch;
-                p_pic->i_planes = 1;
-                break;
-            case VLC_FOURCC('U','Y','V','Y'):
-            case VLC_FOURCC('Y','U','Y','2'):
-                p_pic->p->i_lines = p_vout->output.i_height;
-                p_pic->p->i_visible_lines = p_vout->output.i_height;
-                p_pic->p->i_pixel_pitch = 2;
-                p_pic->p->i_visible_pitch = p_vout->output.i_width *
-                    p_pic->p->i_pixel_pitch;
-                p_pic->i_planes = 1;
-                break;
-            default:
-                Direct3DVoutReleasePictures(p_vout);
-                return VLC_EGENERIC;
-        }
-        p_pic->i_status = DESTROYED_PICTURE;
-        p_pic->i_type   = DIRECT_PICTURE;
-        p_pic->b_slow   = VLC_TRUE;
-        p_pic->pf_lock  = Direct3DVoutLockSurface;
-        p_pic->pf_unlock = Direct3DVoutUnlockSurface;
-        PP_OUTPUTPICTURE[c] = p_pic;
-
-        I_OUTPUTPICTURES = ++c;
-    }
-
-    msg_Dbg( p_vout, "%u Direct3D pictures created successfully", c );
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Direct3DVoutReleasePictures: destroy a picture vector 
- *****************************************************************************
- * release all video resources used for pictures
- *****************************************************************************/
-static void Direct3DVoutReleasePictures( vout_thread_t *p_vout)
-{
-    size_t i_num_pics = I_OUTPUTPICTURES;
-    size_t c;
-    for( c=0; c<i_num_pics; ++c )
-    {
-        picture_t *p_pic = p_vout->p_picture+c; 
-        if( p_pic->p_sys )
-        {
-            LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;
-
-            p_pic->p_sys = NULL;
-
-            if( p_d3dsurf )
-            {
-                IDirect3DSurface9_Release(p_d3dsurf);
-            }
-        }
-    }
-    msg_Dbg( p_vout, "%u Direct3D pictures released.", c);
-
-    I_OUTPUTPICTURES = 0;
-}
-
-/*****************************************************************************
- * Direct3DVoutLockSurface: Lock surface and get picture data pointer
- *****************************************************************************
- * This function locks a surface and get the surface descriptor which amongst
- * other things has the pointer to the picture data.
- *****************************************************************************/
-static int Direct3DVoutLockSurface( vout_thread_t *p_vout, picture_t *p_pic )
-{
-    HRESULT hr;
-    D3DLOCKED_RECT d3drect;
-    LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;
-
-    if( NULL == p_d3dsurf )
-        return VLC_EGENERIC;
-
-    /* Lock the surface to get a valid pointer to the picture buffer */
-    hr = IDirect3DSurface9_LockRect(p_d3dsurf, &d3drect, NULL, 0);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        return VLC_EGENERIC;
-    }
-
-    /* fill in buffer info in first plane */
-    p_pic->p->p_pixels = d3drect.pBits;
-    p_pic->p->i_pitch  = d3drect.Pitch;
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Direct3DVoutUnlockSurface: Unlock a surface locked by Direct3DLockSurface().
- *****************************************************************************/
-static int Direct3DVoutUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )
-{
-    HRESULT hr;
-    LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;
-
-    if( NULL == p_d3dsurf )
-        return VLC_EGENERIC;
-
-    /* Unlock the Surface */
-    hr = IDirect3DSurface9_UnlockRect(p_d3dsurf);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        return VLC_EGENERIC;
-    }
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Direct3DVoutCreateScene: allocate and initialize a 3D scene
- *****************************************************************************
- * for advanced blending/filtering a texture needs be used in a 3D scene.
- *****************************************************************************/
-
-static int Direct3DVoutCreateScene( vout_thread_t *p_vout )
-{
-    LPDIRECT3DDEVICE9       p_d3ddev  = p_vout->p_sys->p_d3ddev;
-    LPDIRECT3DTEXTURE9      p_d3dtex;
-    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc;
-
-    HRESULT hr;
-
-    /*
-    ** Create a texture for use when rendering a scene
-    ** for performance reason, texture format is identical to backbuffer
-    ** which would usually be a RGB format
-    */
-    hr = IDirect3DDevice9_CreateTexture(p_d3ddev, 
-            p_vout->render.i_width,
-            p_vout->render.i_height,
-            1,
-            D3DUSAGE_RENDERTARGET, 
-            p_vout->p_sys->bbFormat,
-            D3DPOOL_DEFAULT,
-            &p_d3dtex, 
-            NULL);
-    if( FAILED(hr))
-    {
-        msg_Err(p_vout, "Failed to create texture. (hr=0x%lx)", hr);
-        return VLC_EGENERIC;
-    }
-
-    /*
-    ** Create a vertex buffer for use when rendering scene
-    */
-    hr = IDirect3DDevice9_CreateVertexBuffer(p_d3ddev,
-            sizeof(CUSTOMVERTEX)*4,
-            D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
-            D3DFVF_CUSTOMVERTEX,
-            D3DPOOL_DEFAULT,
-            &p_d3dvtc,
-            NULL);
-    if( FAILED(hr) )
-    {
-        msg_Err(p_vout, "Failed to create vertex buffer. (hr=0x%lx)", hr);
-            IDirect3DTexture9_Release(p_d3dtex);
-        return VLC_EGENERIC;
-    }
-
-    p_vout->p_sys->p_d3dtex = p_d3dtex;
-    p_vout->p_sys->p_d3dvtc = p_d3dvtc;
-
-    // Texture coordinates outside the range [0.0, 1.0] are set 
-    // to the texture color at 0.0 or 1.0, respectively.
-    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
-    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
-
-    // Set linear filtering quality
-    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
-    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
-
-    // set maximum ambient light
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255));
-
-    // Turn off culling
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_CULLMODE, D3DCULL_NONE);
-
-    // Turn off the zbuffer
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ZENABLE, D3DZB_FALSE);
-
-    // Turn off lights
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_LIGHTING, FALSE);
-
-    // Enable dithering
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_DITHERENABLE, TRUE);
-
-    // disable stencil
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_STENCILENABLE, FALSE);
-
-    // manage blending
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHABLENDENABLE, TRUE);
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHATESTENABLE,TRUE);
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHAREF, 0x10);
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHAFUNC,D3DCMP_GREATER);
-
-    // Set texture states
-    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_COLOROP,D3DTOP_MODULATE);
-    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_COLORARG1,D3DTA_TEXTURE);
-    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_COLORARG2,D3DTA_DIFFUSE);
-
-    // turn off alpha operation
-    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
-
-    msg_Dbg( p_vout, "Direct3D scene created successfully");
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Direct3DVoutReleaseScene
- *****************************************************************************/
-static void Direct3DVoutReleaseScene( vout_thread_t *p_vout )
-{
-    LPDIRECT3DTEXTURE9      p_d3dtex = p_vout->p_sys->p_d3dtex;
-    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc = p_vout->p_sys->p_d3dvtc;
-
-    if( p_d3dvtc )
-    {
-        IDirect3DVertexBuffer9_Release(p_d3dvtc);
-        p_vout->p_sys->p_d3dvtc = NULL;
-    }
-
-    if( p_d3dtex )
-    {
-        IDirect3DTexture9_Release(p_d3dtex);
-        p_vout->p_sys->p_d3dtex = NULL;
-    }
-    msg_Dbg( p_vout, "Direct3D scene released successfully");
-}
-
-/*****************************************************************************
- * Render: copy picture surface into a texture and render into a scene
- *****************************************************************************
- * This function is intented for higher end 3D cards, with pixel shader support
- * and at least 64 MB of video RAM.
- *****************************************************************************/
-static void Direct3DVoutRenderScene( vout_thread_t *p_vout, picture_t *p_pic )
-{
-    LPDIRECT3DDEVICE9       p_d3ddev  = p_vout->p_sys->p_d3ddev;
-    LPDIRECT3DTEXTURE9      p_d3dtex;
-    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc;
-    LPDIRECT3DSURFACE9      p_d3dsrc, p_d3ddest;
-    CUSTOMVERTEX            *p_vertices;
-    HRESULT hr;
-    float f_width, f_height;
-
-    // check if device is still available    
-    hr = IDirect3DDevice9_TestCooperativeLevel(p_d3ddev);
-    if( FAILED(hr) )
-    {
-        if( (D3DERR_DEVICENOTRESET != hr)
-         || (VLC_SUCCESS != Direct3DVoutResetDevice(p_vout)) )
-        {
-            // device is not usable at present (lost device, out of video mem ?)
-            return;
-        }
-    }
-    p_d3dtex  = p_vout->p_sys->p_d3dtex;
-    p_d3dvtc  = p_vout->p_sys->p_d3dvtc;
-
-    /* Clear the backbuffer and the zbuffer */
-    hr = IDirect3DDevice9_Clear( p_d3ddev, 0, NULL, D3DCLEAR_TARGET,
-                              D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0 );
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        return;
-    }
-
-    /*  retrieve picture surface */
-    p_d3dsrc = (LPDIRECT3DSURFACE9)p_pic->p_sys;
-    if( NULL == p_d3dsrc )
-    {
-        msg_Dbg( p_vout, "no surface to render ?");
-        return;
-    }
-
-    /* retrieve texture top-level surface */
-    hr = IDirect3DTexture9_GetSurfaceLevel(p_d3dtex, 0, &p_d3ddest);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        return;
-    }
-
-    /* Copy picture surface into texture surface, color space conversion happens here */
-    hr = IDirect3DDevice9_StretchRect(p_d3ddev, p_d3dsrc, NULL, p_d3ddest, NULL, D3DTEXF_NONE);
-    IDirect3DSurface9_Release(p_d3ddest);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        return;
-    }
-
-    /* Update the vertex buffer */
-    hr = IDirect3DVertexBuffer9_Lock(p_d3dvtc, 0, 0, (VOID **)(&p_vertices), D3DLOCK_DISCARD);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        return;
-    }
-
-    /* Setup vertices */
-    f_width  = (float)(p_vout->output.i_width);
-    f_height = (float)(p_vout->output.i_height);
-
-    p_vertices[0].x       = 0.0f;       // left
-    p_vertices[0].y       = 0.0f;       // top
-    p_vertices[0].z       = 0.0f;
-    p_vertices[0].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
-    p_vertices[0].rhw     = 1.0f;
-    p_vertices[0].tu      = 0.0f;
-    p_vertices[0].tv      = 0.0f;
-    p_vertices[1].x       = f_width;    // right
-    p_vertices[1].y       = 0.0f;       // top
-    p_vertices[1].z       = 0.0f;
-    p_vertices[1].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
-    p_vertices[1].rhw     = 1.0f;
-    p_vertices[1].tu      = 1.0f;
-    p_vertices[1].tv      = 0.0f;
-    p_vertices[2].x       = f_width;    // right
-    p_vertices[2].y       = f_height;   // bottom
-    p_vertices[2].z       = 0.0f;
-    p_vertices[2].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
-    p_vertices[2].rhw     = 1.0f;
-    p_vertices[2].tu      = 1.0f;
-    p_vertices[2].tv      = 1.0f;
-    p_vertices[3].x       = 0.0f;       // left
-    p_vertices[3].y       = f_height;   // bottom
-    p_vertices[3].z       = 0.0f;
-    p_vertices[3].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
-    p_vertices[3].rhw     = 1.0f;
-    p_vertices[3].tu      = 0.0f;
-    p_vertices[3].tv      = 1.0f;
-    hr= IDirect3DVertexBuffer9_Unlock(p_d3dvtc);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        return;
-    }
-
-    // Begin the scene
-    hr = IDirect3DDevice9_BeginScene(p_d3ddev);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        return;
-    }
-
-    // Setup our texture. Using textures introduces the texture stage states,
-    // which govern how textures get blended together (in the case of multiple
-    // textures) and lighting information. In this case, we are modulating
-    // (blending) our texture with the diffuse color of the vertices.
-    hr = IDirect3DDevice9_SetTexture(p_d3ddev, 0, (LPDIRECT3DBASETEXTURE9)p_d3dtex);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(p_d3ddev);
-        return;
-    }
-
-    // Render the vertex buffer contents
-    hr = IDirect3DDevice9_SetStreamSource(p_d3ddev, 0, p_d3dvtc, 0, sizeof(CUSTOMVERTEX));
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(p_d3ddev);
-        return;
-    }
-    // we use FVF instead of vertex shader
-    hr = IDirect3DDevice9_SetVertexShader(p_d3ddev, NULL);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(p_d3ddev);
-        return;
-    }
-
-    hr = IDirect3DDevice9_SetFVF(p_d3ddev, D3DFVF_CUSTOMVERTEX);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(p_d3ddev);
-        return;
-    }
-
-    // draw rectangle
-    hr = IDirect3DDevice9_DrawPrimitive(p_d3ddev, D3DPT_TRIANGLEFAN, 0, 2);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(p_d3ddev);
-        return;
-    }
-
-    // End the scene
-    hr = IDirect3DDevice9_EndScene(p_d3ddev);
-    if( FAILED(hr) )
-    {
-        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        return;
-    }
-}
-
diff --git a/modules/video_output/directx/directx.c b/modules/video_output/directx/directx.c
deleted file mode 100644 (file)
index 9c86356..0000000
+++ /dev/null
@@ -1,2157 +0,0 @@
-/*****************************************************************************
- * vout.c: Windows DirectX video output display method
- *****************************************************************************
- * Copyright (C) 2001-2004 the VideoLAN team
- * $Id$
- *
- * Authors: Gildas Bazin <gbazin@videolan.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble:
- *
- * This plugin will use YUV overlay if supported, using overlay will result in
- * the best video quality (hardware interpolation when rescaling the picture)
- * and the fastest display as it requires less processing.
- *
- * If YUV overlay is not supported this plugin will use RGB offscreen video
- * surfaces that will be blitted onto the primary surface (display) to
- * effectively display the pictures. This fallback method also enables us to
- * display video in window mode.
- *
- *****************************************************************************/
-#include <errno.h>                                                 /* ENOMEM */
-#include <stdlib.h>                                                /* free() */
-#include <string.h>                                            /* strerror() */
-
-#include <vlc/vlc.h>
-#include <vlc_interface.h>
-#include <vlc_playlist.h>
-#include <vlc_vout.h>
-
-#include <windows.h>
-#include <ddraw.h>
-#include <commctrl.h>
-
-#ifndef UNDER_CE
-#   include <multimon.h>
-#endif
-#undef GetSystemMetrics
-
-#ifndef MONITOR_DEFAULTTONEAREST
-#   define MONITOR_DEFAULTTONEAREST 2
-#endif
-
-#include "vout.h"
-
-/*****************************************************************************
- * 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.
- *****************************************************************************/
-struct picture_sys_t
-{
-    LPDIRECTDRAWSURFACE2 p_surface;
-    LPDIRECTDRAWSURFACE2 p_front_surface;
-    DDSURFACEDESC        ddsd;
-};
-
-/*****************************************************************************
- * DirectDraw GUIDs.
- * Defining them here allows us to get rid of the dxguid library during
- * the linking stage.
- *****************************************************************************/
-#include <initguid.h>
-#undef GUID_EXT
-#define GUID_EXT
-DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
-DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );
-
-/*****************************************************************************
- * Local prototypes.
- *****************************************************************************/
-static int  OpenVideo  ( vlc_object_t * );
-static void CloseVideo ( vlc_object_t * );
-
-static int  Init      ( vout_thread_t * );
-static void End       ( vout_thread_t * );
-static int  Manage    ( vout_thread_t * );
-static void Display   ( vout_thread_t *, picture_t * );
-static void FirstDisplay( vout_thread_t *, picture_t * );
-static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
-
-static int  NewPictureVec  ( vout_thread_t *, picture_t *, int );
-static void FreePictureVec ( vout_thread_t *, picture_t *, int );
-static int  UpdatePictureStruct( vout_thread_t *, picture_t *, int );
-
-static int  DirectXInitDDraw      ( vout_thread_t *p_vout );
-static void DirectXCloseDDraw     ( vout_thread_t *p_vout );
-static int  DirectXCreateDisplay  ( vout_thread_t *p_vout );
-static void DirectXCloseDisplay   ( vout_thread_t *p_vout );
-static int  DirectXCreateSurface  ( vout_thread_t *p_vout,
-                                    LPDIRECTDRAWSURFACE2 *, int, int, int );
-static void DirectXCloseSurface   ( vout_thread_t *p_vout,
-                                    LPDIRECTDRAWSURFACE2 );
-static int  DirectXCreateClipper  ( vout_thread_t *p_vout );
-static void DirectXGetDDrawCaps   ( vout_thread_t *p_vout );
-static int  DirectXLockSurface    ( vout_thread_t *p_vout, picture_t *p_pic );
-static int  DirectXUnlockSurface  ( vout_thread_t *p_vout, picture_t *p_pic );
-
-static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *i_color );
-
-void SwitchWallpaperMode( vout_thread_t *, vlc_bool_t );
-
-/* Object variables callbacks */
-static int FindDevicesCallback( vlc_object_t *, char const *,
-                                vlc_value_t, vlc_value_t, void * );
-static int WallpaperCallback( vlc_object_t *, char const *,
-                              vlc_value_t, vlc_value_t, void * );
-
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-#define HW_YUV_TEXT N_("Use hardware YUV->RGB conversions")
-#define HW_YUV_LONGTEXT N_( \
-    "Try to use hardware acceleration for YUV->RGB conversions. " \
-    "This option doesn't have any effect when using overlays." )
-
-#define SYSMEM_TEXT N_("Use video buffers in system memory")
-#define SYSMEM_LONGTEXT N_( \
-    "Create video buffers in system memory instead of video memory. This " \
-    "isn't recommended as usually using video memory allows to benefit from " \
-    "more hardware acceleration (like rescaling or YUV->RGB conversions). " \
-    "This option doesn't have any effect when using overlays." )
-
-#define TRIPLEBUF_TEXT N_("Use triple buffering for overlays")
-#define TRIPLEBUF_LONGTEXT N_( \
-    "Try to use triple buffering when using YUV overlays. That results in " \
-    "much better video quality (no flickering)." )
-
-#define DEVICE_TEXT N_("Name of desired display device")
-#define DEVICE_LONGTEXT N_("In a multiple monitor configuration, you can " \
-    "specify the Windows device name of the display that you want the video " \
-    "window to open on. For example, \"\\\\.\\DISPLAY1\" or " \
-    "\"\\\\.\\DISPLAY2\"." )
-
-#define WALLPAPER_TEXT N_("Enable wallpaper mode ")
-#define WALLPAPER_LONGTEXT N_( \
-    "The wallpaper mode allows you to display the video as the desktop " \
-    "background. Note that this feature only works in overlay mode and " \
-    "the desktop must not already have a wallpaper." )
-
-static char *ppsz_dev[] = { "" };
-static char *ppsz_dev_text[] = { N_("Default") };
-
-vlc_module_begin();
-    set_shortname( "DirectX" );
-    set_category( CAT_VIDEO );
-    set_subcategory( SUBCAT_VIDEO_VOUT );
-    add_bool( "directx-hw-yuv", 1, NULL, HW_YUV_TEXT, HW_YUV_LONGTEXT,
-              VLC_TRUE );
-    add_bool( "directx-use-sysmem", 0, NULL, SYSMEM_TEXT, SYSMEM_LONGTEXT,
-              VLC_TRUE );
-    add_bool( "directx-3buffering", 1, NULL, TRIPLEBUF_TEXT,
-              TRIPLEBUF_LONGTEXT, VLC_TRUE );
-
-    add_string( "directx-device", "", NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
-                VLC_TRUE );
-        change_string_list( ppsz_dev, ppsz_dev_text, FindDevicesCallback );
-        change_action_add( FindDevicesCallback, N_("Refresh list") );
-
-    add_bool( "directx-wallpaper", 0, NULL, WALLPAPER_TEXT, WALLPAPER_LONGTEXT,
-              VLC_TRUE );
-
-    set_description( _("DirectX video output") );
-    set_capability( "video output", 100 );
-    add_shortcut( "directx" );
-    set_callbacks( OpenVideo, CloseVideo );
-
-    /* FIXME: Hack to avoid unregistering our window class */
-    linked_with_a_crap_library_which_uses_atexit( );
-vlc_module_end();
-
-#if 0 /* FIXME */
-    /* check if we registered a window class because we need to
-     * unregister it */
-    WNDCLASS wndclass;
-    if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )
-        UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );
-#endif
-
-/*****************************************************************************
- * OpenVideo: allocate DirectX video thread output method
- *****************************************************************************
- * This function allocates and initialize the DirectX vout method.
- *****************************************************************************/
-static int OpenVideo( vlc_object_t *p_this )
-{
-    vout_thread_t * p_vout = (vout_thread_t *)p_this;
-    vlc_value_t val;
-    HMODULE huser32;
-
-    /* Allocate structure */
-    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
-    if( p_vout->p_sys == NULL )
-    {
-        msg_Err( p_vout, "out of memory" );
-        return VLC_ENOMEM;
-    }
-    memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
-
-    /* Initialisations */
-    p_vout->pf_init = Init;
-    p_vout->pf_end = End;
-    p_vout->pf_manage = Manage;
-    p_vout->pf_render = NULL;
-    p_vout->pf_display = FirstDisplay;
-
-    p_vout->p_sys->p_ddobject = NULL;
-    p_vout->p_sys->p_display = NULL;
-    p_vout->p_sys->p_current_surface = NULL;
-    p_vout->p_sys->p_clipper = NULL;
-    p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
-    p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
-    p_vout->p_sys->i_changes = 0;
-    p_vout->p_sys->b_wallpaper = 0;
-    vlc_mutex_init( p_vout, &p_vout->p_sys->lock );
-    SetRectEmpty( &p_vout->p_sys->rect_display );
-    SetRectEmpty( &p_vout->p_sys->rect_parent );
-
-    /* Multimonitor stuff */
-    p_vout->p_sys->hmonitor = NULL;
-    p_vout->p_sys->p_display_driver = NULL;
-    p_vout->p_sys->MonitorFromWindow = NULL;
-    p_vout->p_sys->GetMonitorInfo = NULL;
-    if( (huser32 = GetModuleHandle( _T("USER32") ) ) )
-    {
-        p_vout->p_sys->MonitorFromWindow = (HMONITOR (WINAPI *)( HWND, DWORD ))
-            GetProcAddress( huser32, _T("MonitorFromWindow") );
-        p_vout->p_sys->GetMonitorInfo =
-#ifndef UNICODE
-            GetProcAddress( huser32, "GetMonitorInfoA" );
-#else
-            GetProcAddress( huser32, _T("GetMonitorInfoW") );
-#endif
-    }
-
-    var_Create( p_vout, "overlay", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "directx-use-sysmem", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "directx-hw-yuv", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "directx-3buffering", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "directx-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
-    var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
-
-    p_vout->p_sys->b_cursor_hidden = 0;
-    p_vout->p_sys->i_lastmoved = mdate();
-
-    /* Set main window's size */
-    p_vout->p_sys->i_window_width = p_vout->i_window_width;
-    p_vout->p_sys->i_window_height = p_vout->i_window_height;
-
-    /* Create the DirectXEventThread, this thread is created by us to isolate
-     * the Win32 PeekMessage function calls. We want to do this because
-     * Windows can stay blocked inside this call for a long time, and when
-     * this happens it thus blocks vlc's video_output thread.
-     * DirectXEventThread will take care of the creation of the video
-     * window (because PeekMessage has to be called from the same thread which
-     * created the window). */
-    msg_Dbg( p_vout, "creating DirectXEventThread" );
-    p_vout->p_sys->p_event =
-        vlc_object_create( p_vout, sizeof(event_thread_t) );
-    p_vout->p_sys->p_event->p_vout = p_vout;
-    if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread",
-                           E_(DirectXEventThread), 0, 1 ) )
-    {
-        msg_Err( p_vout, "cannot create DirectXEventThread" );
-        vlc_object_destroy( p_vout->p_sys->p_event );
-        p_vout->p_sys->p_event = NULL;
-        goto error;
-    }
-
-    if( p_vout->p_sys->p_event->b_error )
-    {
-        msg_Err( p_vout, "DirectXEventThread failed" );
-        goto error;
-    }
-
-    vlc_object_attach( p_vout->p_sys->p_event, p_vout );
-
-    msg_Dbg( p_vout, "DirectXEventThread running" );
-
-    /* Initialise DirectDraw */
-    if( DirectXInitDDraw( p_vout ) )
-    {
-        msg_Err( p_vout, "cannot initialize DirectDraw" );
-        goto error;
-    }
-
-    /* Create the directx display */
-    if( DirectXCreateDisplay( p_vout ) )
-    {
-        msg_Err( p_vout, "cannot initialize DirectDraw" );
-        goto error;
-    }
-
-    /* Variable to indicate if the window should be on top of others */
-    /* Trigger a callback right now */
-    var_Get( p_vout, "video-on-top", &val );
-    var_Set( p_vout, "video-on-top", val );
-
-    /* Variable to indicate if the window should be on top of others */
-    /* Trigger a callback right now */
-    var_Create( p_vout, "directx-wallpaper", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
-    val.psz_string = _("Wallpaper");
-    var_Change( p_vout, "directx-wallpaper", VLC_VAR_SETTEXT, &val, NULL );
-    var_AddCallback( p_vout, "directx-wallpaper", WallpaperCallback, NULL );
-    var_Get( p_vout, "directx-wallpaper", &val );
-    var_Set( p_vout, "directx-wallpaper", val );
-
-    /* disable screensaver by temporarily changing system settings */
-    p_vout->p_sys->i_spi_lowpowertimeout = 0;
-    p_vout->p_sys->i_spi_powerofftimeout = 0;
-    p_vout->p_sys->i_spi_screensavetimeout = 0;
-    var_Get( p_vout, "disable-screensaver", &val);
-    if( val.b_bool ) {
-        msg_Dbg(p_vout, "disabling screen saver");
-        SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT,
-            0, &(p_vout->p_sys->i_spi_lowpowertimeout), 0);
-        if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {
-            SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0);
-        }
-        SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0,
-            &(p_vout->p_sys->i_spi_powerofftimeout), 0);
-        if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
-            SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, 0, NULL, 0);
-        }
-        SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0,
-            &(p_vout->p_sys->i_spi_screensavetimeout), 0);
-        if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {
-            SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 0, NULL, 0);
-        }
-    }
-
-    return VLC_SUCCESS;
-
- error:
-    CloseVideo( VLC_OBJECT(p_vout) );
-    return VLC_EGENERIC;
-}
-
-/*****************************************************************************
- * 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 Init( vout_thread_t *p_vout )
-{
-    int i_chroma_backup;
-    vlc_value_t val;
-
-    /* Get a few default parameters */
-    var_Get( p_vout, "overlay", &val );
-    p_vout->p_sys->b_using_overlay = val.b_bool;
-    var_Get( p_vout, "directx-use-sysmem", &val );
-    p_vout->p_sys->b_use_sysmem = val.b_bool;
-    var_Get( p_vout, "directx-hw-yuv", &val );
-    p_vout->p_sys->b_hw_yuv = val.b_bool;
-    var_Get( p_vout, "directx-3buffering", &val );
-    p_vout->p_sys->b_3buf_overlay = val.b_bool;
-
-    /* Initialise DirectDraw if not already done.
-     * We do this here because on multi-monitor systems we may have to
-     * re-create the directdraw surfaces. */
-    if( !p_vout->p_sys->p_ddobject &&
-        DirectXInitDDraw( p_vout ) != VLC_SUCCESS )
-    {
-        msg_Err( p_vout, "cannot initialize DirectDraw" );
-        return VLC_EGENERIC;
-    }
-
-    /* Create the directx display */
-    if( !p_vout->p_sys->p_display &&
-        DirectXCreateDisplay( p_vout ) != VLC_SUCCESS )
-    {
-        msg_Err( p_vout, "cannot initialize DirectDraw" );
-        return VLC_EGENERIC;
-    }
-
-    /* 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;
-    p_vout->fmt_out = p_vout->fmt_in;
-    E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
-
-#define MAX_DIRECTBUFFERS 1
-    /* Right now we use only 1 directbuffer because we don't want the
-     * video decoder to decode directly into direct buffers as they are
-     * created into video memory and video memory is _really_ slow */
-
-    /* Choose the chroma we will try first. */
-    switch( p_vout->render.i_chroma )
-    {
-        case VLC_FOURCC('Y','U','Y','2'):
-        case VLC_FOURCC('Y','U','N','V'):
-            p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
-            break;
-        case VLC_FOURCC('U','Y','V','Y'):
-        case VLC_FOURCC('U','Y','N','V'):
-        case VLC_FOURCC('Y','4','2','2'):
-            p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
-            break;
-        case VLC_FOURCC('Y','V','Y','U'):
-            p_vout->output.i_chroma = VLC_FOURCC('Y','V','Y','U');
-            break;
-        default:
-            p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
-            break;
-    }
-
-    NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
-
-    i_chroma_backup = p_vout->output.i_chroma;
-
-    if( !I_OUTPUTPICTURES )
-    {
-        /* hmmm, it didn't work! Let's try commonly supported chromas */
-        if( p_vout->output.i_chroma != VLC_FOURCC('I','4','2','0') )
-        {
-            p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
-            NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
-        }
-        if( !I_OUTPUTPICTURES )
-        {
-            /* hmmm, it still didn't work! Let's try another one */
-            p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
-            NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
-        }
-    }
-
-    if( !I_OUTPUTPICTURES )
-    {
-        /* If it still didn't work then don't try to use an overlay */
-        p_vout->output.i_chroma = i_chroma_backup;
-        p_vout->p_sys->b_using_overlay = 0;
-        NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
-    }
-
-    /* Change the window title bar text */
-    PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
-
-    p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * End: terminate Sys video thread output method
- *****************************************************************************
- * Terminate an output method created by Create.
- * It is called at the end of the thread.
- *****************************************************************************/
-static void End( vout_thread_t *p_vout )
-{
-    FreePictureVec( p_vout, p_vout->p_picture, I_OUTPUTPICTURES );
-
-    DirectXCloseDisplay( p_vout );
-    DirectXCloseDDraw( p_vout );
-
-    return;
-}
-
-/*****************************************************************************
- * CloseVideo: destroy Sys video thread output method
- *****************************************************************************
- * Terminate an output method created by Create
- *****************************************************************************/
-static void CloseVideo( vlc_object_t *p_this )
-{
-    vout_thread_t * p_vout = (vout_thread_t *)p_this;
-
-    msg_Dbg( p_vout, "CloseVideo" );
-
-    if( p_vout->p_sys->p_event )
-    {
-        vlc_object_detach( p_vout->p_sys->p_event );
-
-        /* Kill DirectXEventThread */
-        p_vout->p_sys->p_event->b_die = VLC_TRUE;
-
-        /* we need to be sure DirectXEventThread won't stay stuck in
-         * GetMessage, so we send a fake message */
-        if( p_vout->p_sys->hwnd )
-        {
-            PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);
-        }
-
-        vlc_thread_join( p_vout->p_sys->p_event );
-        vlc_object_destroy( p_vout->p_sys->p_event );
-    }
-
-    vlc_mutex_destroy( &p_vout->p_sys->lock );
-
-    /* Make sure the wallpaper is restored */
-    SwitchWallpaperMode( p_vout, VLC_FALSE );
-
-    /* restore screensaver system settings */
-    if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {
-        SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT,
-            p_vout->p_sys->i_spi_lowpowertimeout, NULL, 0);
-    }
-    if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
-        SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT,
-            p_vout->p_sys->i_spi_powerofftimeout, NULL, 0);
-    }
-    if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {
-        SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT,
-            p_vout->p_sys->i_spi_screensavetimeout, NULL, 0);
-    }
-
-    if( p_vout->p_sys )
-    {
-        free( p_vout->p_sys );
-        p_vout->p_sys = NULL;
-    }
-}
-
-/*****************************************************************************
- * Manage: handle Sys events
- *****************************************************************************
- * This function should be called regularly by the video output thread.
- * It returns a non null value if an error occurred.
- *****************************************************************************/
-static int Manage( vout_thread_t *p_vout )
-{
-    /* If we do not control our window, we check for geometry changes
-     * ourselves because the parent might not send us its events. */
-    vlc_mutex_lock( &p_vout->p_sys->lock );
-    if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
-    {
-        RECT rect_parent;
-        POINT point;
-
-        vlc_mutex_unlock( &p_vout->p_sys->lock );
-
-        GetClientRect( p_vout->p_sys->hparent, &rect_parent );
-        point.x = point.y = 0;
-        ClientToScreen( p_vout->p_sys->hparent, &point );
-        OffsetRect( &rect_parent, point.x, point.y );
-
-        if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
-        {
-            p_vout->p_sys->rect_parent = rect_parent;
-
-            /* This one is to force the update even if only
-             * the position has changed */
-            SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1,
-                          rect_parent.right - rect_parent.left,
-                          rect_parent.bottom - rect_parent.top, 0 );
-
-            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
-                          rect_parent.right - rect_parent.left,
-                          rect_parent.bottom - rect_parent.top, 0 );
-        }
-    }
-    else
-    {
-        vlc_mutex_unlock( &p_vout->p_sys->lock );
-    }
-
-    /*
-     * Position Change
-     */
-    if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE )
-    {
-        p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
-
-        /* Check if we are still on the same monitor */
-        if( p_vout->p_sys->MonitorFromWindow &&
-            p_vout->p_sys->hmonitor !=
-                p_vout->p_sys->MonitorFromWindow( p_vout->p_sys->hwnd,
-                                                  MONITOR_DEFAULTTONEAREST ) )
-        {
-            /* This will force the vout core to recreate the picture buffers */
-            p_vout->i_changes |= VOUT_PICTURE_BUFFERS_CHANGE;
-        }
-    }
-
-    /* Check for cropping / aspect changes */
-    if( p_vout->i_changes & VOUT_CROP_CHANGE ||
-        p_vout->i_changes & VOUT_ASPECT_CHANGE )
-    {
-        p_vout->i_changes &= ~VOUT_CROP_CHANGE;
-        p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
-
-        p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset;
-        p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset;
-        p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width;
-        p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height;
-        p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect;
-        p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;
-        p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;
-        p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
-        E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
-    }
-
-    /* We used to call the Win32 PeekMessage function here to read the window
-     * messages. But since window can stay blocked into this function for a
-     * long time (for example when you move your window on the screen), I
-     * decided to isolate PeekMessage in another thread. */
-
-    if( p_vout->p_sys->i_changes & DX_WALLPAPER_CHANGE )
-    {
-        SwitchWallpaperMode( p_vout, !p_vout->p_sys->b_wallpaper );
-        p_vout->p_sys->i_changes &= ~DX_WALLPAPER_CHANGE;
-        E_(DirectXUpdateOverlay)( p_vout );
-    }
-
-    /*
-     * Fullscreen change
-     */
-    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
-        || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
-    {
-        Win32ToggleFullscreen( p_vout );
-
-        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
-        p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
-    }
-
-    /*
-     * Pointer change
-     */
-    if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&
-        (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 )
-    {
-        POINT point;
-        HWND hwnd;
-
-        /* Hide the cursor only if it is inside our window */
-        GetCursorPos( &point );
-        hwnd = WindowFromPoint(point);
-        if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )
-        {
-            PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
-        }
-        else
-        {
-            p_vout->p_sys->i_lastmoved = mdate();
-        }
-    }
-
-    /*
-     * "Always on top" status change
-     */
-    if( p_vout->p_sys->b_on_top_change )
-    {
-        vlc_value_t val;
-        HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
-
-        var_Get( p_vout, "video-on-top", &val );
-
-        /* Set the window on top if necessary */
-        if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
-                           & WS_EX_TOPMOST ) )
-        {
-            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
-                           MF_BYCOMMAND | MFS_CHECKED );
-            SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,
-                          SWP_NOSIZE | SWP_NOMOVE );
-        }
-        else
-        /* The window shouldn't be on top */
-        if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
-                           & WS_EX_TOPMOST ) )
-        {
-            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
-                           MF_BYCOMMAND | MFS_UNCHECKED );
-            SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
-                          SWP_NOSIZE | SWP_NOMOVE );
-        }
-
-        p_vout->p_sys->b_on_top_change = VLC_FALSE;
-    }
-
-    /* Check if the event thread is still running */
-    if( p_vout->p_sys->p_event->b_die )
-    {
-        return VLC_EGENERIC; /* exit */
-    }
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Display: displays previously rendered output
- *****************************************************************************
- * 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 Display( vout_thread_t *p_vout, picture_t *p_pic )
-{
-    HRESULT dxresult;
-
-    if( (p_vout->p_sys->p_display == NULL) )
-    {
-        msg_Warn( p_vout, "no display!" );
-        return;
-    }
-
-    /* Our surface can be lost so be sure to check this
-     * and restore it if need be */
-    if( IDirectDrawSurface2_IsLost( p_vout->p_sys->p_display )
-        == DDERR_SURFACELOST )
-    {
-        if( IDirectDrawSurface2_Restore( p_vout->p_sys->p_display ) == DD_OK &&
-            p_vout->p_sys->b_using_overlay )
-            E_(DirectXUpdateOverlay)( p_vout );
-    }
-
-    if( !p_vout->p_sys->b_using_overlay )
-    {
-        DDBLTFX  ddbltfx;
-
-        /* We ask for the "NOTEARING" option */
-        memset( &ddbltfx, 0, sizeof(DDBLTFX) );
-        ddbltfx.dwSize = sizeof(DDBLTFX);
-        ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
-
-        /* Blit video surface to display */
-        dxresult = IDirectDrawSurface2_Blt( p_vout->p_sys->p_display,
-                                            &p_vout->p_sys->rect_dest_clipped,
-                                            p_pic->p_sys->p_surface,
-                                            &p_vout->p_sys->rect_src_clipped,
-                                            DDBLT_ASYNC, &ddbltfx );
-        if( dxresult != DD_OK )
-        {
-            msg_Warn( p_vout, "could not blit surface (error %li)", dxresult );
-            return;
-        }
-    }
-    else /* using overlay */
-    {
-        /* Flip the overlay buffers if we are using back buffers */
-        if( p_pic->p_sys->p_front_surface == p_pic->p_sys->p_surface )
-        {
-            return;
-        }
-
-        dxresult = IDirectDrawSurface2_Flip( p_pic->p_sys->p_front_surface,
-                                             NULL, DDFLIP_WAIT );
-        if( dxresult != DD_OK )
-        {
-            msg_Warn( p_vout, "could not flip overlay (error %li)", dxresult );
-        }
-
-        /* set currently displayed pic */
-        p_vout->p_sys->p_current_surface = p_pic->p_sys->p_front_surface;
-
-        /* Lock surface to get all the required info */
-        if( DirectXLockSurface( p_vout, p_pic ) )
-        {
-            /* AAARRGG */
-            msg_Warn( p_vout, "cannot lock surface" );
-            return;
-        }
-        DirectXUnlockSurface( p_vout, p_pic );
-    }
-}
-
-/*
-** this function is only used once when the first picture is received
-** this function will show the video window once video is ready for
-** display.
-*/
-
-static void FirstDisplay( vout_thread_t *p_vout, picture_t *p_pic )
-{
-    /* get initial picture rendered on overlay surface */
-    Display(p_vout, p_pic);
-
-    IDirectDraw_WaitForVerticalBlank(p_vout->p_sys->p_ddobject,
-            DDWAITVB_BLOCKBEGIN, NULL);
-
-    if( p_vout->p_sys->b_using_overlay )
-    {
-        /* set the colorkey as the backgound brush for the video window */
-        SetClassLong( p_vout->p_sys->hvideownd, GCL_HBRBACKGROUND,
-                      (LONG)CreateSolidBrush( p_vout->p_sys->i_rgb_colorkey ) );
-    }
-    /*
-    ** Video window is initially hidden, show it now since we got a 
-    ** picture to show.
-    */
-    SetWindowPos( p_vout->p_sys->hvideownd, NULL, 0, 0, 0, 0, 
-        SWP_ASYNCWINDOWPOS|
-        SWP_FRAMECHANGED|
-        SWP_SHOWWINDOW|
-        SWP_NOMOVE|
-        SWP_NOSIZE|
-        SWP_NOZORDER );
-
-    /* use and restores proper display function for further pictures */
-    p_vout->pf_display = Display;
-}
-
-/* following functions are local */
-
-/*****************************************************************************
- * DirectXEnumCallback: Device enumeration
- *****************************************************************************
- * This callback function is called by DirectDraw once for each
- * available DirectDraw device.
- *****************************************************************************/
-BOOL WINAPI DirectXEnumCallback( GUID* p_guid, LPTSTR psz_desc,
-                                 LPTSTR psz_drivername, VOID* p_context,
-                                 HMONITOR hmon )
-{
-    vout_thread_t *p_vout = (vout_thread_t *)p_context;
-    vlc_value_t device;
-
-    msg_Dbg( p_vout, "DirectXEnumCallback: %s, %s", psz_desc, psz_drivername );
-
-    if( hmon )
-    {
-        var_Get( p_vout, "directx-device", &device );
-
-        if( ( !device.psz_string || !*device.psz_string ) &&
-            hmon == p_vout->p_sys->hmonitor )
-        {
-            if( device.psz_string ) free( device.psz_string );
-        }
-        else if( strcmp( psz_drivername, device.psz_string ) == 0 )
-        {
-            MONITORINFO monitor_info;
-            monitor_info.cbSize = sizeof( MONITORINFO );
-
-            if( p_vout->p_sys->GetMonitorInfo( hmon, &monitor_info ) )
-            {
-                RECT rect;
-
-                /* Move window to the right screen */
-                GetWindowRect( p_vout->p_sys->hwnd, &rect );
-                if( !IntersectRect( &rect, &rect, &monitor_info.rcWork ) )
-                {
-                    rect.left = monitor_info.rcWork.left;
-                    rect.top = monitor_info.rcWork.top;
-                    msg_Dbg( p_vout, "DirectXEnumCallback: setting window "
-                             "position to %ld,%ld", rect.left, rect.top );
-                    SetWindowPos( p_vout->p_sys->hwnd, NULL,
-                                  rect.left, rect.top, 0, 0,
-                                  SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
-                }
-            }
-
-            p_vout->p_sys->hmonitor = hmon;
-            if( device.psz_string ) free( device.psz_string );
-        }
-        else
-        {
-            if( device.psz_string ) free( device.psz_string );
-            return TRUE; /* Keep enumerating */
-        }
-
-        msg_Dbg( p_vout, "selecting %s, %s", psz_desc, psz_drivername );
-        p_vout->p_sys->p_display_driver = malloc( sizeof(GUID) );
-        if( p_vout->p_sys->p_display_driver )
-            memcpy( p_vout->p_sys->p_display_driver, p_guid, sizeof(GUID) );
-    }
-
-    return TRUE; /* Keep enumerating */
-}
-
-/*****************************************************************************
- * DirectXInitDDraw: Takes care of all the DirectDraw initialisations
- *****************************************************************************
- * This function initialise and allocate resources for DirectDraw.
- *****************************************************************************/
-static int DirectXInitDDraw( vout_thread_t *p_vout )
-{
-    HRESULT dxresult;
-    HRESULT (WINAPI *OurDirectDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
-    HRESULT (WINAPI *OurDirectDrawEnumerateEx)( LPDDENUMCALLBACKEXA, LPVOID,
-                                                DWORD );
-    LPDIRECTDRAW p_ddobject;
-
-    msg_Dbg( p_vout, "DirectXInitDDraw" );
-
-    /* Load direct draw DLL */
-    p_vout->p_sys->hddraw_dll = LoadLibrary(_T("DDRAW.DLL"));
-    if( p_vout->p_sys->hddraw_dll == NULL )
-    {
-        msg_Warn( p_vout, "DirectXInitDDraw failed loading ddraw.dll" );
-        goto error;
-    }
-
-    OurDirectDrawCreate =
-      (void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
-                              _T("DirectDrawCreate") );
-    if( OurDirectDrawCreate == NULL )
-    {
-        msg_Err( p_vout, "DirectXInitDDraw failed GetProcAddress" );
-        goto error;
-    }
-
-    OurDirectDrawEnumerateEx =
-      (void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
-#ifndef UNICODE
-                              "DirectDrawEnumerateExA" );
-#else
-                              _T("DirectDrawEnumerateExW") );
-#endif
-
-    if( OurDirectDrawEnumerateEx && p_vout->p_sys->MonitorFromWindow )
-    {
-        vlc_value_t device;
-
-        var_Get( p_vout, "directx-device", &device );
-        if( device.psz_string )
-        {
-            msg_Dbg( p_vout, "directx-device: %s", device.psz_string );
-            free( device.psz_string );
-        }
-
-        p_vout->p_sys->hmonitor =
-            p_vout->p_sys->MonitorFromWindow( p_vout->p_sys->hwnd,
-                                              MONITOR_DEFAULTTONEAREST );
-
-        /* Enumerate displays */
-        OurDirectDrawEnumerateEx( DirectXEnumCallback, p_vout,
-                                  DDENUM_ATTACHEDSECONDARYDEVICES );
-    }
-
-    /* Initialize DirectDraw now */
-    dxresult = OurDirectDrawCreate( p_vout->p_sys->p_display_driver,
-                                    &p_ddobject, NULL );
-    if( dxresult != DD_OK )
-    {
-        msg_Err( p_vout, "DirectXInitDDraw cannot initialize DDraw" );
-        goto error;
-    }
-
-    /* Get the IDirectDraw2 interface */
-    dxresult = IDirectDraw_QueryInterface( p_ddobject, &IID_IDirectDraw2,
-                                        (LPVOID *)&p_vout->p_sys->p_ddobject );
-    /* Release the unused interface */
-    IDirectDraw_Release( p_ddobject );
-    if( dxresult != DD_OK )
-    {
-        msg_Err( p_vout, "cannot get IDirectDraw2 interface" );
-        goto error;
-    }
-
-    /* Set DirectDraw Cooperative level, ie what control we want over Windows
-     * display */
-    dxresult = IDirectDraw2_SetCooperativeLevel( p_vout->p_sys->p_ddobject,
-                                                 NULL, DDSCL_NORMAL );
-    if( dxresult != DD_OK )
-    {
-        msg_Err( p_vout, "cannot set direct draw cooperative level" );
-        goto error;
-    }
-
-    /* Get the size of the current display device */
-    if( p_vout->p_sys->hmonitor && p_vout->p_sys->GetMonitorInfo )
-    {
-        MONITORINFO monitor_info;
-        monitor_info.cbSize = sizeof( MONITORINFO );
-        p_vout->p_sys->GetMonitorInfo( p_vout->p_sys->hmonitor,
-                                       &monitor_info );
-        p_vout->p_sys->rect_display = monitor_info.rcMonitor;
-    }
-    else
-    {
-        p_vout->p_sys->rect_display.left = 0;
-        p_vout->p_sys->rect_display.top = 0;
-        p_vout->p_sys->rect_display.right  = GetSystemMetrics(SM_CXSCREEN);
-        p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
-    }
-
-    msg_Dbg( p_vout, "screen dimensions (%lix%li,%lix%li)",
-             p_vout->p_sys->rect_display.left,
-             p_vout->p_sys->rect_display.top,
-             p_vout->p_sys->rect_display.right,
-             p_vout->p_sys->rect_display.bottom );
-
-    /* Probe the capabilities of the hardware */
-    DirectXGetDDrawCaps( p_vout );
-
-    msg_Dbg( p_vout, "End DirectXInitDDraw" );
-    return VLC_SUCCESS;
-
- error:
-    if( p_vout->p_sys->p_ddobject )
-        IDirectDraw2_Release( p_vout->p_sys->p_ddobject );
-    if( p_vout->p_sys->hddraw_dll )
-        FreeLibrary( p_vout->p_sys->hddraw_dll );
-    p_vout->p_sys->hddraw_dll = NULL;
-    p_vout->p_sys->p_ddobject = NULL;
-    return VLC_EGENERIC;
-}
-
-/*****************************************************************************
- * DirectXCreateDisplay: create the DirectDraw display.
- *****************************************************************************
- * Create and initialize display according to preferences specified in the vout
- * thread fields.
- *****************************************************************************/
-static int DirectXCreateDisplay( vout_thread_t *p_vout )
-{
-    HRESULT              dxresult;
-    DDSURFACEDESC        ddsd;
-    LPDIRECTDRAWSURFACE  p_display;
-
-    msg_Dbg( p_vout, "DirectXCreateDisplay" );
-
-    /* Now get the primary surface. This surface is what you actually see
-     * on your screen */
-    memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
-    ddsd.dwSize = sizeof(DDSURFACEDESC);
-    ddsd.dwFlags = DDSD_CAPS;
-    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
-
-    dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
-                                           &ddsd, &p_display, NULL );
-    if( dxresult != DD_OK )
-    {
-        msg_Err( p_vout, "cannot get primary surface (error %li)", dxresult );
-        return VLC_EGENERIC;
-    }
-
-    dxresult = IDirectDrawSurface_QueryInterface( p_display,
-                                         &IID_IDirectDrawSurface2,
-                                         (LPVOID *)&p_vout->p_sys->p_display );
-    /* Release the old interface */
-    IDirectDrawSurface_Release( p_display );
-    if ( dxresult != DD_OK )
-    {
-        msg_Err( p_vout, "cannot query IDirectDrawSurface2 interface "
-                         "(error %li)", dxresult );
-        return VLC_EGENERIC;
-    }
-
-    /* The clipper will be used only in non-overlay mode */
-    DirectXCreateClipper( p_vout );
-
-    /* Make sure the colorkey will be painted */
-    p_vout->p_sys->i_colorkey = 1;
-    p_vout->p_sys->i_rgb_colorkey =
-        DirectXFindColorkey( p_vout, &p_vout->p_sys->i_colorkey );
-
-    E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * 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;
-
-    msg_Dbg( p_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 )
-    {
-        msg_Warn( p_vout, "cannot create clipper (error %li)", dxresult );
-        goto error;
-    }
-
-    /* Associate the clipper to the window */
-    dxresult = IDirectDrawClipper_SetHWnd( p_vout->p_sys->p_clipper, 0,
-                                           p_vout->p_sys->hvideownd );
-    if( dxresult != DD_OK )
-    {
-        msg_Warn( p_vout, "cannot attach clipper to window (error %li)",
-                          dxresult );
-        goto error;
-    }
-
-    /* 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 )
-    {
-        msg_Warn( p_vout, "cannot attach clipper to surface (error %li)",
-                          dxresult );
-        goto error;
-    }
-
-    return VLC_SUCCESS;
-
- error:
-    if( p_vout->p_sys->p_clipper )
-    {
-        IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
-    }
-    p_vout->p_sys->p_clipper = NULL;
-    return VLC_EGENERIC;
-}
-
-/*****************************************************************************
- * DirectXCreateSurface: create an YUV overlay or RGB surface for the video.
- *****************************************************************************
- * The best method of display is with an YUV overlay because the YUV->RGB
- * conversion is done in hardware.
- * You can also create a plain RGB surface.
- * ( Maybe we could also try an RGB overlay surface, which could have hardware
- * scaling and which would also be faster in window mode because you don't
- * need to do any blitting to the main display...)
- *****************************************************************************/
-static int DirectXCreateSurface( vout_thread_t *p_vout,
-                                 LPDIRECTDRAWSURFACE2 *pp_surface_final,
-                                 int i_chroma, int b_overlay,
-                                 int i_backbuffers )
-{
-    HRESULT dxresult;
-    LPDIRECTDRAWSURFACE p_surface;
-    DDSURFACEDESC ddsd;
-
-    /* Create the video surface */
-    if( b_overlay )
-    {
-        /* Now try to create the YUV overlay surface.
-         * This overlay will be displayed on top of the primary surface.
-         * A color key is used to determine whether or not the overlay will be
-         * displayed, ie the overlay will be displayed in place of the primary
-         * surface wherever the primary surface will have this color.
-         * The video window has been created with a background of this color so
-         * the overlay will be only displayed on top of this window */
-
-        memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
-        ddsd.dwSize = sizeof(DDSURFACEDESC);
-        ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-        ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
-        ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
-        ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
-        ddsd.dwFlags |= (i_backbuffers ? DDSD_BACKBUFFERCOUNT : 0);
-        ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
-        ddsd.ddsCaps.dwCaps |= (i_backbuffers ? DDSCAPS_COMPLEX | DDSCAPS_FLIP
-                                : 0 );
-        ddsd.dwHeight = p_vout->render.i_height;
-        ddsd.dwWidth = p_vout->render.i_width;
-        ddsd.dwBackBufferCount = i_backbuffers;
-
-        dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
-                                               &ddsd, &p_surface, NULL );
-        if( dxresult != DD_OK )
-        {
-            *pp_surface_final = NULL;
-            return VLC_EGENERIC;
-        }
-    }
-
-    if( !b_overlay )
-    {
-        vlc_bool_t b_rgb_surface =
-            ( i_chroma == VLC_FOURCC('R','G','B','2') )
-          || ( i_chroma == VLC_FOURCC('R','V','1','5') )
-           || ( i_chroma == VLC_FOURCC('R','V','1','6') )
-            || ( i_chroma == VLC_FOURCC('R','V','2','4') )
-             || ( i_chroma == VLC_FOURCC('R','V','3','2') );
-
-        memset( &ddsd, 0, sizeof( DDSURFACEDESC ) );
-        ddsd.dwSize = sizeof(DDSURFACEDESC);
-        ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-        ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS;
-        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
-        ddsd.dwHeight = p_vout->render.i_height;
-        ddsd.dwWidth = p_vout->render.i_width;
-
-        if( p_vout->p_sys->b_use_sysmem )
-            ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
-        else
-            ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
-
-        if( !b_rgb_surface )
-        {
-            ddsd.dwFlags |= DDSD_PIXELFORMAT;
-            ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
-            ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
-        }
-
-        dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
-                                               &ddsd, &p_surface, NULL );
-        if( dxresult != DD_OK )
-        {
-            *pp_surface_final = NULL;
-            return VLC_EGENERIC;
-        }
-    }
-
-    /* Now that the surface is created, try to get a newer DirectX interface */
-    dxresult = IDirectDrawSurface_QueryInterface( p_surface,
-                                     &IID_IDirectDrawSurface2,
-                                     (LPVOID *)pp_surface_final );
-    IDirectDrawSurface_Release( p_surface );    /* Release the old interface */
-    if ( dxresult != DD_OK )
-    {
-        msg_Err( p_vout, "cannot query IDirectDrawSurface2 interface "
-                         "(error %li)", dxresult );
-        *pp_surface_final = NULL;
-        return VLC_EGENERIC;
-    }
-
-    if( b_overlay )
-    {
-        /* Check the overlay is useable as some graphics cards allow creating
-         * several overlays but only one can be used at one time. */
-        p_vout->p_sys->p_current_surface = *pp_surface_final;
-        if( E_(DirectXUpdateOverlay)( p_vout ) != VLC_SUCCESS )
-        {
-            IDirectDrawSurface2_Release( *pp_surface_final );
-            *pp_surface_final = NULL;
-            msg_Err( p_vout, "overlay unuseable (might already be in use)" );
-            return VLC_EGENERIC;
-        }
-    }
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * DirectXUpdateOverlay: Move or resize overlay surface on video display.
- *****************************************************************************
- * This function is used to move or resize an overlay surface on the screen.
- * Ususally the overlay is moved by the user and thus, by a move or resize
- * event (in Manage).
- *****************************************************************************/
-int E_(DirectXUpdateOverlay)( vout_thread_t *p_vout )
-{
-    DDOVERLAYFX     ddofx;
-    DWORD           dwFlags;
-    HRESULT         dxresult;
-    RECT            rect_src = p_vout->p_sys->rect_src_clipped;
-    RECT            rect_dest = p_vout->p_sys->rect_dest_clipped;
-
-    if( !p_vout->p_sys->b_using_overlay ) return VLC_EGENERIC;
-
-    if( p_vout->p_sys->b_wallpaper )
-    {
-        int i_x, i_y, i_width, i_height;
-
-        rect_src.left = p_vout->fmt_out.i_x_offset;
-        rect_src.top = p_vout->fmt_out.i_y_offset;
-        rect_src.right = rect_src.left + p_vout->fmt_out.i_visible_width;
-        rect_src.bottom = rect_src.top + p_vout->fmt_out.i_visible_height;
-
-        rect_dest = p_vout->p_sys->rect_display;
-        vout_PlacePicture( p_vout, rect_dest.right, rect_dest.bottom,
-                           &i_x, &i_y, &i_width, &i_height );
-
-        rect_dest.left += i_x;
-        rect_dest.right = rect_dest.left + i_width;
-        rect_dest.top += i_y;
-        rect_dest.bottom = rect_dest.top + i_height;
-    }
-
-    vlc_mutex_lock( &p_vout->p_sys->lock );
-    if( p_vout->p_sys->p_current_surface == NULL )
-    {
-        vlc_mutex_unlock( &p_vout->p_sys->lock );
-        return VLC_EGENERIC;
-    }
-
-    /* The new window dimensions should already have been computed by the
-     * caller of this function */
-
-    /* Position and show the overlay */
-    memset(&ddofx, 0, sizeof(DDOVERLAYFX));
-    ddofx.dwSize = sizeof(DDOVERLAYFX);
-    ddofx.dckDestColorkey.dwColorSpaceLowValue = p_vout->p_sys->i_colorkey;
-    ddofx.dckDestColorkey.dwColorSpaceHighValue = p_vout->p_sys->i_colorkey;
-
-    dwFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
-
-    dxresult = IDirectDrawSurface2_UpdateOverlay(
-                   p_vout->p_sys->p_current_surface,
-                   &rect_src, p_vout->p_sys->p_display, &rect_dest,
-                   dwFlags, &ddofx );
-
-    vlc_mutex_unlock( &p_vout->p_sys->lock );
-
-    if(dxresult != DD_OK)
-    {
-        msg_Warn( p_vout, "DirectXUpdateOverlay cannot move/resize overlay" );
-        return VLC_EGENERIC;
-    }
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * DirectXCloseDDraw: Release the DDraw object allocated by DirectXInitDDraw
- *****************************************************************************
- * This function returns all resources allocated by DirectXInitDDraw.
- *****************************************************************************/
-static void DirectXCloseDDraw( vout_thread_t *p_vout )
-{
-    msg_Dbg( p_vout, "DirectXCloseDDraw" );
-    if( p_vout->p_sys->p_ddobject != NULL )
-    {
-        IDirectDraw2_Release(p_vout->p_sys->p_ddobject);
-        p_vout->p_sys->p_ddobject = NULL;
-    }
-
-    if( p_vout->p_sys->hddraw_dll != NULL )
-    {
-        FreeLibrary( p_vout->p_sys->hddraw_dll );
-        p_vout->p_sys->hddraw_dll = NULL;
-    }
-
-    if( p_vout->p_sys->p_display_driver != NULL )
-    {
-        free( p_vout->p_sys->p_display_driver );
-        p_vout->p_sys->p_display_driver = NULL;
-    }
-
-    p_vout->p_sys->hmonitor = NULL;
-}
-
-/*****************************************************************************
- * DirectXCloseDisplay: close and reset the DirectX display device
- *****************************************************************************
- * This function returns all resources allocated by DirectXCreateDisplay.
- *****************************************************************************/
-static void DirectXCloseDisplay( vout_thread_t *p_vout )
-{
-    msg_Dbg( p_vout, "DirectXCloseDisplay" );
-
-    if( p_vout->p_sys->p_clipper != NULL )
-    {
-        msg_Dbg( p_vout, "DirectXCloseDisplay clipper" );
-        IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
-        p_vout->p_sys->p_clipper = NULL;
-    }
-
-    if( p_vout->p_sys->p_display != NULL )
-    {
-        msg_Dbg( p_vout, "DirectXCloseDisplay display" );
-        IDirectDrawSurface2_Release( p_vout->p_sys->p_display );
-        p_vout->p_sys->p_display = NULL;
-    }
-}
-
-/*****************************************************************************
- * DirectXCloseSurface: close the YUV overlay or RGB surface.
- *****************************************************************************
- * This function returns all resources allocated for the surface.
- *****************************************************************************/
-static void DirectXCloseSurface( vout_thread_t *p_vout,
-                                 LPDIRECTDRAWSURFACE2 p_surface )
-{
-    msg_Dbg( p_vout, "DirectXCloseSurface" );
-    if( p_surface != NULL )
-    {
-        IDirectDrawSurface2_Release( p_surface );
-    }
-}
-
-/*****************************************************************************
- * 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;
-    int i_ret = VLC_SUCCESS;
-    LPDIRECTDRAWSURFACE2 p_surface;
-
-    msg_Dbg( p_vout, "NewPictureVec overlay:%s chroma:%.4s",
-             p_vout->p_sys->b_using_overlay ? "yes" : "no",
-             (char *)&p_vout->output.i_chroma );
-
-    I_OUTPUTPICTURES = 0;
-
-    /* First we try to use an YUV overlay surface.
-     * The overlay surface that we create won't be used to decode directly
-     * into it because accessing video memory directly is way to slow (remember
-     * that pictures are decoded macroblock per macroblock). Instead the video
-     * will be decoded in picture buffers in system memory which will then be
-     * memcpy() to the overlay surface. */
-    if( p_vout->p_sys->b_using_overlay )
-    {
-        /* Triple buffering rocks! it doesn't have any processing overhead
-         * (you don't have to wait for the vsync) and provides for a very nice
-         * video quality (no tearing). */
-        if( p_vout->p_sys->b_3buf_overlay )
-            i_ret = DirectXCreateSurface( p_vout, &p_surface,
-                                          p_vout->output.i_chroma,
-                                          p_vout->p_sys->b_using_overlay,
-                                          2 /* number of backbuffers */ );
-
-        if( !p_vout->p_sys->b_3buf_overlay || i_ret != VLC_SUCCESS )
-        {
-            /* Try to reduce the number of backbuffers */
-            i_ret = DirectXCreateSurface( p_vout, &p_surface,
-                                          p_vout->output.i_chroma,
-                                          p_vout->p_sys->b_using_overlay,
-                                          0 /* number of backbuffers */ );
-        }
-
-        if( i_ret == VLC_SUCCESS )
-        {
-            DDSCAPS dds_caps;
-            picture_t front_pic;
-            picture_sys_t front_pic_sys;
-            front_pic.p_sys = &front_pic_sys;
-
-            /* Allocate internal structure */
-            p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
-            if( p_pic[0].p_sys == NULL )
-            {
-                DirectXCloseSurface( p_vout, p_surface );
-                return VLC_ENOMEM;
-            }
-
-            /* set front buffer */
-            p_pic[0].p_sys->p_front_surface = p_surface;
-
-            /* Get the back buffer */
-            memset( &dds_caps, 0, sizeof( DDSCAPS ) );
-            dds_caps.dwCaps = DDSCAPS_BACKBUFFER;
-            if( DD_OK != IDirectDrawSurface2_GetAttachedSurface(
-                                                p_surface, &dds_caps,
-                                                &p_pic[0].p_sys->p_surface ) )
-            {
-                msg_Warn( p_vout, "NewPictureVec could not get back buffer" );
-                /* front buffer is the same as back buffer */
-                p_pic[0].p_sys->p_surface = p_surface;
-            }
-
-
-            p_vout->p_sys->p_current_surface = front_pic.p_sys->p_surface =
-                p_pic[0].p_sys->p_front_surface;
-
-            /* Reset the front buffer memory */
-            if( DirectXLockSurface( p_vout, &front_pic ) == VLC_SUCCESS )
-            {
-                int i,j;
-                for( i = 0; i < front_pic.i_planes; i++ )
-                    for( j = 0; j < front_pic.p[i].i_visible_lines; j++)
-                        memset( front_pic.p[i].p_pixels + j *
-                                front_pic.p[i].i_pitch, 127,
-                                front_pic.p[i].i_visible_pitch );
-
-                DirectXUnlockSurface( p_vout, &front_pic );
-            }
-
-            E_(DirectXUpdateOverlay)( p_vout );
-            I_OUTPUTPICTURES = 1;
-            msg_Dbg( p_vout, "YUV overlay created successfully" );
-        }
-    }
-
-    /* As we can't have an overlay, we'll try to create a plain offscreen
-     * surface. This surface will reside in video memory because there's a
-     * better chance then that we'll be able to use some kind of hardware
-     * acceleration like rescaling, blitting or YUV->RGB conversions.
-     * We then only need to blit this surface onto the main display when we
-     * want to display it */
-    if( !p_vout->p_sys->b_using_overlay )
-    {
-        if( p_vout->p_sys->b_hw_yuv )
-        {
-            DWORD i_codes;
-            DWORD *pi_codes;
-            vlc_bool_t b_result = VLC_FALSE;
-
-            /* Check if the chroma is supported first. This is required
-             * because a few buggy drivers don't mind creating the surface
-             * even if they don't know about the chroma. */
-            if( IDirectDraw2_GetFourCCCodes( p_vout->p_sys->p_ddobject,
-                                             &i_codes, NULL ) == DD_OK )
-            {
-                pi_codes = malloc( i_codes * sizeof(DWORD) );
-                if( pi_codes && IDirectDraw2_GetFourCCCodes(
-                    p_vout->p_sys->p_ddobject, &i_codes, pi_codes ) == DD_OK )
-                {
-                    for( i = 0; i < (int)i_codes; i++ )
-                    {
-                        if( p_vout->output.i_chroma == pi_codes[i] )
-                        {
-                            b_result = VLC_TRUE;
-                            break;
-                        }
-                    }
-                }
-            }
-
-            if( b_result )
-                i_ret = DirectXCreateSurface( p_vout, &p_surface,
-                                              p_vout->output.i_chroma,
-                                              0 /* no overlay */,
-                                              0 /* no back buffers */ );
-            else
-                p_vout->p_sys->b_hw_yuv = VLC_FALSE;
-        }
-
-        if( i_ret || !p_vout->p_sys->b_hw_yuv )
-        {
-            /* Our last choice is to use a plain RGB surface */
-            DDPIXELFORMAT ddpfPixelFormat;
-
-            ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-            IDirectDrawSurface2_GetPixelFormat( p_vout->p_sys->p_display,
-                                                &ddpfPixelFormat );
-
-            if( ddpfPixelFormat.dwFlags & DDPF_RGB )
-            {
-                switch( ddpfPixelFormat.dwRGBBitCount )
-                {
-                case 8:
-                    p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
-                    p_vout->output.pf_setpalette = SetPalette;
-                    break;
-                case 15:
-                    p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
-                    break;
-                case 16:
-                    p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
-                    break;
-                case 24:
-                    p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
-                    break;
-                case 32:
-                    p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
-                    break;
-                default:
-                    msg_Err( p_vout, "unknown screen depth" );
-                    return VLC_EGENERIC;
-                }
-                p_vout->output.i_rmask = ddpfPixelFormat.dwRBitMask;
-                p_vout->output.i_gmask = ddpfPixelFormat.dwGBitMask;
-                p_vout->output.i_bmask = ddpfPixelFormat.dwBBitMask;
-            }
-
-            p_vout->p_sys->b_hw_yuv = 0;
-
-            i_ret = DirectXCreateSurface( p_vout, &p_surface,
-                                          p_vout->output.i_chroma,
-                                          0 /* no overlay */,
-                                          0 /* no back buffers */ );
-
-            if( i_ret && !p_vout->p_sys->b_use_sysmem )
-            {
-                /* Give it a last try with b_use_sysmem enabled */
-                p_vout->p_sys->b_use_sysmem = 1;
-
-                i_ret = DirectXCreateSurface( p_vout, &p_surface,
-                                              p_vout->output.i_chroma,
-                                              0 /* no overlay */,
-                                              0 /* no back buffers */ );
-            }
-        }
-
-        if( i_ret == VLC_SUCCESS )
-        {
-            /* 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 VLC_ENOMEM;
-            }
-
-            p_pic[0].p_sys->p_surface = p_pic[0].p_sys->p_front_surface
-                = p_surface;
-
-            I_OUTPUTPICTURES = 1;
-
-            msg_Dbg( p_vout, "created plain surface of chroma:%.4s",
-                     (char *)&p_vout->output.i_chroma );
-        }
-    }
-
-
-    /* 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;
-        p_pic[i].b_slow   = VLC_TRUE;
-        p_pic[i].pf_lock  = DirectXLockSurface;
-        p_pic[i].pf_unlock = DirectXUnlockSurface;
-        PP_OUTPUTPICTURE[i] = &p_pic[i];
-
-        if( DirectXLockSurface( p_vout, &p_pic[i] ) != VLC_SUCCESS )
-        {
-            /* AAARRGG */
-            FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
-            I_OUTPUTPICTURES = 0;
-            msg_Err( p_vout, "cannot lock surface" );
-            return VLC_EGENERIC;
-        }
-        DirectXUnlockSurface( p_vout, &p_pic[i] );
-    }
-
-    msg_Dbg( p_vout, "End NewPictureVec (%s)",
-             I_OUTPUTPICTURES ? "succeeded" : "failed" );
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * FreePicture: destroy a picture vector allocated with NewPictureVec
- *****************************************************************************
- *
- *****************************************************************************/
-static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic,
-                            int i_num_pics )
-{
-    int i;
-
-    vlc_mutex_lock( &p_vout->p_sys->lock );
-    p_vout->p_sys->p_current_surface = 0;
-    vlc_mutex_unlock( &p_vout->p_sys->lock );
-
-    for( i = 0; i < i_num_pics; i++ )
-    {
-        DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_front_surface );
-
-        for( i = 0; i < i_num_pics; i++ )
-        {
-            free( p_pic[i].p_sys );
-        }
-    }
-}
-
-/*****************************************************************************
- * 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 VLC_FOURCC('R','G','B','2'):
-        case VLC_FOURCC('R','V','1','5'):
-        case VLC_FOURCC('R','V','1','6'):
-        case VLC_FOURCC('R','V','2','4'):
-        case VLC_FOURCC('R','V','3','2'):
-            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_visible_lines = p_vout->output.i_height;
-            p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
-            switch( p_vout->output.i_chroma )
-            {
-                case VLC_FOURCC('R','G','B','2'):
-                    p_pic->p->i_pixel_pitch = 1;
-                    break;
-                case VLC_FOURCC('R','V','1','5'):
-                case VLC_FOURCC('R','V','1','6'):
-                    p_pic->p->i_pixel_pitch = 2;
-                    break;
-                case VLC_FOURCC('R','V','2','4'):
-                    p_pic->p->i_pixel_pitch = 3;
-                    break;
-                case VLC_FOURCC('R','V','3','2'):
-                    p_pic->p->i_pixel_pitch = 4;
-                    break;
-                default:
-                    return VLC_EGENERIC;
-            }
-            p_pic->p->i_visible_pitch = p_vout->output.i_width *
-              p_pic->p->i_pixel_pitch;
-            p_pic->i_planes = 1;
-            break;
-
-        case VLC_FOURCC('Y','V','1','2'):
-        case VLC_FOURCC('I','4','2','0'):
-
-            /* U and V inverted compared to I420
-             * Fixme: this should be handled by the vout core */
-            p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0');
-
-            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_visible_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_pitch = 1;
-            p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
-              p_pic->p[Y_PLANE].i_pixel_pitch;
-
-            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_visible_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_pitch = 1;
-            p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
-              p_pic->p[V_PLANE].i_pixel_pitch;
-
-            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_visible_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_pitch = 1;
-            p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
-              p_pic->p[U_PLANE].i_pixel_pitch;
-
-            p_pic->i_planes = 3;
-            break;
-
-        case VLC_FOURCC('I','Y','U','V'):
-
-            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_visible_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_pitch = 1;
-            p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
-              p_pic->p[Y_PLANE].i_pixel_pitch;
-
-            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_visible_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_pitch = 1;
-            p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
-              p_pic->p[U_PLANE].i_pixel_pitch;
-
-            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_visible_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_pitch = 1;
-            p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
-              p_pic->p[V_PLANE].i_pixel_pitch;
-
-            p_pic->i_planes = 3;
-            break;
-
-        case VLC_FOURCC('U','Y','V','Y'):
-        case VLC_FOURCC('Y','U','Y','2'):
-
-            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_visible_lines = p_vout->output.i_height;
-            p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
-            p_pic->p->i_pixel_pitch = 2;
-            p_pic->p->i_visible_pitch = p_vout->output.i_width *
-              p_pic->p->i_pixel_pitch;
-
-            p_pic->i_planes = 1;
-            break;
-
-        default:
-            /* Unknown chroma, tell the guy to get lost */
-            msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",
-                     p_vout->output.i_chroma,
-                     (char*)&p_vout->output.i_chroma );
-            return VLC_EGENERIC;
-    }
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * 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 )
-    {
-        msg_Warn( p_vout, "cannot get caps" );
-    }
-    else
-    {
-        vlc_bool_t bHasOverlay, bHasOverlayFourCC, bCanDeinterlace,
-             bHasColorKey, bCanStretch, bCanBltFourcc,
-             bAlignBoundarySrc, bAlignBoundaryDest,
-             bAlignSizeSrc, bAlignSizeDest;
-
-        /* Determine if the hardware supports overlay surfaces */
-        bHasOverlay = (ddcaps.dwCaps & DDCAPS_OVERLAY) ? 1 : 0;
-        /* Determine if the hardware supports overlay surfaces */
-        bHasOverlayFourCC = (ddcaps.dwCaps & DDCAPS_OVERLAYFOURCC) ? 1 : 0;
-        /* Determine if the hardware supports overlay deinterlacing */
-        bCanDeinterlace = (ddcaps.dwCaps & DDCAPS2_CANFLIPODDEVEN) ? 1 : 0;
-        /* Determine if the hardware supports colorkeying */
-        bHasColorKey = (ddcaps.dwCaps & DDCAPS_COLORKEY) ? 1 : 0;
-        /* Determine if the hardware supports scaling of the overlay surface */
-        bCanStretch = (ddcaps.dwCaps & DDCAPS_OVERLAYSTRETCH) ? 1 : 0;
-        /* Determine if the hardware supports color conversion during a blit */
-        bCanBltFourcc = (ddcaps.dwCaps & DDCAPS_BLTFOURCC) ? 1 : 0;
-        /* Determine overlay source boundary alignment */
-        bAlignBoundarySrc = (ddcaps.dwCaps & DDCAPS_ALIGNBOUNDARYSRC) ? 1 : 0;
-        /* Determine overlay destination boundary alignment */
-        bAlignBoundaryDest = (ddcaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST) ? 1:0;
-        /* Determine overlay destination size alignment */
-        bAlignSizeSrc = (ddcaps.dwCaps & DDCAPS_ALIGNSIZESRC) ? 1 : 0;
-        /* Determine overlay destination size alignment */
-        bAlignSizeDest = (ddcaps.dwCaps & DDCAPS_ALIGNSIZEDEST) ? 1 : 0;
-        msg_Dbg( p_vout, "DirectDraw Capabilities: overlay=%i yuvoverlay=%i "
-                         "can_deinterlace_overlay=%i colorkey=%i stretch=%i "
-                         "bltfourcc=%i",
-                         bHasOverlay, bHasOverlayFourCC, bCanDeinterlace,
-                         bHasColorKey, bCanStretch, bCanBltFourcc );
-
-        if( bAlignBoundarySrc || bAlignBoundaryDest ||
-            bAlignSizeSrc || bAlignSizeDest )
-        {
-            if( bAlignBoundarySrc ) p_vout->p_sys->i_align_src_boundary =
-                ddcaps.dwAlignBoundarySrc;
-            if( bAlignBoundaryDest ) p_vout->p_sys->i_align_dest_boundary =
-                ddcaps.dwAlignBoundaryDest;
-            if( bAlignSizeDest ) p_vout->p_sys->i_align_src_size =
-                ddcaps.dwAlignSizeSrc;
-            if( bAlignSizeDest ) p_vout->p_sys->i_align_dest_size =
-                ddcaps.dwAlignSizeDest;
-
-            msg_Dbg( p_vout, "align_boundary_src=%i,%i "
-                     "align_boundary_dest=%i,%i "
-                     "align_size_src=%i,%i align_size_dest=%i,%i",
-                     bAlignBoundarySrc, p_vout->p_sys->i_align_src_boundary,
-                     bAlignBoundaryDest, p_vout->p_sys->i_align_dest_boundary,
-                     bAlignSizeSrc, p_vout->p_sys->i_align_src_size,
-                     bAlignSizeDest, p_vout->p_sys->i_align_dest_size );
-        }
-
-        /* Don't ask for troubles */
-        if( !bCanBltFourcc ) p_vout->p_sys->b_hw_yuv = FALSE;
-    }
-}
-
-/*****************************************************************************
- * DirectXLockSurface: Lock surface and get picture data pointer
- *****************************************************************************
- * This function locks a surface and get the surface descriptor which amongst
- * other things has the pointer to the picture data.
- *****************************************************************************/
-static int DirectXLockSurface( vout_thread_t *p_vout, 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 = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface,
-                                         NULL, &p_pic->p_sys->ddsd,
-                                         DDLOCK_NOSYSLOCK | DDLOCK_WAIT,
-                                         NULL );
-    if( dxresult != DD_OK )
-    {
-        if( dxresult == DDERR_INVALIDPARAMS )
-        {
-            /* DirectX 3 doesn't support the DDLOCK_NOSYSLOCK flag, resulting
-             * in an invalid params error */
-            dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface, NULL,
-                                             &p_pic->p_sys->ddsd,
-                                             DDLOCK_WAIT, NULL);
-        }
-        if( dxresult == DDERR_SURFACELOST )
-        {
-            /* Your surface can be lost so be sure
-             * to check this and restore it if needed */
-
-            /* When using overlays with back-buffers, we need to restore
-             * the front buffer so the back-buffers get restored as well. */
-            if( p_vout->p_sys->b_using_overlay  )
-                IDirectDrawSurface2_Restore( p_pic->p_sys->p_front_surface );
-            else
-                IDirectDrawSurface2_Restore( p_pic->p_sys->p_surface );
-
-            dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface, NULL,
-                                                 &p_pic->p_sys->ddsd,
-                                                 DDLOCK_WAIT, NULL);
-#if 0
-            if( dxresult == DDERR_SURFACELOST )
-                msg_Dbg( p_vout, "DirectXLockSurface: DDERR_SURFACELOST" );
-#endif
-        }
-        if( dxresult != DD_OK )
-        {
-            return VLC_EGENERIC;
-        }
-    }
-
-    /* Now we have a pointer to the surface memory, we can update our picture
-     * structure. */
-    if( UpdatePictureStruct( p_vout, p_pic, p_vout->output.i_chroma )
-        != VLC_SUCCESS )
-    {
-        DirectXUnlockSurface( p_vout, p_pic );
-        return VLC_EGENERIC;
-    }
-    else
-        return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * DirectXUnlockSurface: Unlock a surface locked by DirectXLockSurface().
- *****************************************************************************/
-static int DirectXUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )
-{
-    /* Unlock the Surface */
-    if( IDirectDrawSurface2_Unlock( p_pic->p_sys->p_surface, NULL ) == DD_OK )
-        return VLC_SUCCESS;
-    else
-        return VLC_EGENERIC;
-}
-
-/*****************************************************************************
- * DirectXFindColorkey: Finds out the 32bits RGB pixel value of the colorkey
- *****************************************************************************/
-static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *pi_color )
-{
-    DDSURFACEDESC ddsd;
-    HRESULT dxresult;
-    COLORREF i_rgb = 0;
-    uint32_t i_pixel_backup;
-    HDC hdc;
-
-    ddsd.dwSize = sizeof(ddsd);
-    dxresult = IDirectDrawSurface2_Lock( p_vout->p_sys->p_display, NULL,
-                                         &ddsd, DDLOCK_WAIT, NULL );
-    if( dxresult != DD_OK ) return 0;
-
-    i_pixel_backup = *(uint32_t *)ddsd.lpSurface;
-
-    switch( ddsd.ddpfPixelFormat.dwRGBBitCount )
-    {
-    case 4:
-        *(uint8_t *)ddsd.lpSurface = *pi_color | (*pi_color << 4);
-        break;
-    case 8:
-        *(uint8_t *)ddsd.lpSurface = *pi_color;
-        break;
-    case 15:
-    case 16:
-        *(uint16_t *)ddsd.lpSurface = *pi_color;
-        break;
-    case 24:
-        /* Seems to be problematic so we'll just put black as the colorkey */
-        *pi_color = 0;
-    default:
-        *(uint32_t *)ddsd.lpSurface = *pi_color;
-        break;
-    }
-
-    IDirectDrawSurface2_Unlock( p_vout->p_sys->p_display, NULL );
-
-    if( IDirectDrawSurface2_GetDC( p_vout->p_sys->p_display, &hdc ) == DD_OK )
-    {
-        i_rgb = GetPixel( hdc, 0, 0 );
-        IDirectDrawSurface2_ReleaseDC( p_vout->p_sys->p_display, hdc );
-    }
-
-    ddsd.dwSize = sizeof(ddsd);
-    dxresult = IDirectDrawSurface2_Lock( p_vout->p_sys->p_display, NULL,
-                                         &ddsd, DDLOCK_WAIT, NULL );
-    if( dxresult != DD_OK ) return i_rgb;
-
-    *(uint32_t *)ddsd.lpSurface = i_pixel_backup;
-
-    IDirectDrawSurface2_Unlock( p_vout->p_sys->p_display, NULL );
-
-    return i_rgb;
-}
-
-/*****************************************************************************
- * A few toolbox functions
- *****************************************************************************/
-void SwitchWallpaperMode( vout_thread_t *p_vout, vlc_bool_t b_on )
-{
-    HWND hwnd;
-
-    if( p_vout->p_sys->b_wallpaper == b_on ) return; /* Nothing to do */
-
-    hwnd = FindWindow( _T("Progman"), NULL );
-    if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SHELLDLL_DefView"), NULL );
-    if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SysListView32"), NULL );
-    if( !hwnd )
-    {
-        msg_Warn( p_vout, "couldn't find \"SysListView32\" window, "
-                  "wallpaper mode not supported" );
-        return;
-    }
-
-    p_vout->p_sys->b_wallpaper = b_on;
-
-    msg_Dbg( p_vout, "wallpaper mode %s", b_on ? "enabled" : "disabled" );
-
-    if( p_vout->p_sys->b_wallpaper )
-    {
-        p_vout->p_sys->color_bkg = ListView_GetBkColor( hwnd );
-        p_vout->p_sys->color_bkgtxt = ListView_GetTextBkColor( hwnd );
-
-        ListView_SetBkColor( hwnd, p_vout->p_sys->i_rgb_colorkey );
-        ListView_SetTextBkColor( hwnd, p_vout->p_sys->i_rgb_colorkey );
-    }
-    else if( hwnd )
-    {
-        ListView_SetBkColor( hwnd, p_vout->p_sys->color_bkg );
-        ListView_SetTextBkColor( hwnd, p_vout->p_sys->color_bkgtxt );
-    }
-
-    /* Update desktop */
-    InvalidateRect( hwnd, NULL, TRUE );            
-    UpdateWindow( hwnd );
-}
-
-/*****************************************************************************
- * config variable callback
- *****************************************************************************/
-BOOL WINAPI DirectXEnumCallback2( GUID* p_guid, LPTSTR psz_desc,
-                                  LPTSTR psz_drivername, VOID* p_context,
-                                  HMONITOR hmon )
-{
-    module_config_t *p_item = (module_config_t *)p_context;
-
-    p_item->ppsz_list =
-        (char **)realloc( p_item->ppsz_list,
-                          (p_item->i_list+2) * sizeof(char *) );
-    p_item->ppsz_list_text =
-        (char **)realloc( p_item->ppsz_list_text,
-                          (p_item->i_list+2) * sizeof(char *) );
-
-    p_item->ppsz_list[p_item->i_list] = strdup( psz_drivername );
-    p_item->ppsz_list_text[p_item->i_list] = NULL;
-    p_item->i_list++;
-    p_item->ppsz_list[p_item->i_list] = NULL;
-    p_item->ppsz_list_text[p_item->i_list] = NULL;
-
-    return TRUE; /* Keep enumerating */
-}
-
-static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
-                               vlc_value_t newval, vlc_value_t oldval, void *d)
-{
-    HRESULT (WINAPI *OurDirectDrawEnumerateEx)( LPDDENUMCALLBACKEXA, LPVOID,
-                                                DWORD );
-    HINSTANCE hddraw_dll;
-
-    module_config_t *p_item;
-    int i;
-
-    p_item = config_FindConfig( p_this, psz_name );
-    if( !p_item ) return VLC_SUCCESS;
-
-    /* Clear-up the current list */
-    if( p_item->i_list )
-    {
-        /* Keep the first entry */
-        for( i = 1; i < p_item->i_list; i++ )
-        {
-            free( p_item->ppsz_list[i] );
-            free( p_item->ppsz_list_text[i] );
-        }
-        /* TODO: Remove when no more needed */
-        p_item->ppsz_list[i] = NULL;
-        p_item->ppsz_list_text[i] = NULL;
-    }
-    p_item->i_list = 1;
-
-    /* Load direct draw DLL */
-    hddraw_dll = LoadLibrary(_T("DDRAW.DLL"));
-    if( hddraw_dll == NULL ) return VLC_SUCCESS;
-
-    OurDirectDrawEnumerateEx =
-#ifndef UNICODE
-      (void *)GetProcAddress( hddraw_dll, "DirectDrawEnumerateExA" );
-#else
-      (void *)GetProcAddress( hddraw_dll, _T("DirectDrawEnumerateExW") );
-#endif
-
-    if( OurDirectDrawEnumerateEx )
-    {
-        /* Enumerate displays */
-        OurDirectDrawEnumerateEx( DirectXEnumCallback2, p_item,
-                                  DDENUM_ATTACHEDSECONDARYDEVICES );
-    }
-
-    FreeLibrary( hddraw_dll );
-
-    /* Signal change to the interface */
-    p_item->b_dirty = VLC_TRUE;
-
-    return VLC_SUCCESS;
-}
-
-static int WallpaperCallback( vlc_object_t *p_this, char const *psz_cmd,
-                              vlc_value_t oldval, vlc_value_t newval,
-                              void *p_data )
-{
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-
-    if( (newval.b_bool && !p_vout->p_sys->b_wallpaper) ||
-        (!newval.b_bool && p_vout->p_sys->b_wallpaper) )
-    {
-        playlist_t *p_playlist;
-
-        p_playlist =
-            (playlist_t *)vlc_object_find( p_this, VLC_OBJECT_PLAYLIST,
-                                           FIND_PARENT );
-        if( p_playlist )
-        {
-            /* Modify playlist as well because the vout might have to be
-             * restarted */
-            var_Create( p_playlist, "directx-wallpaper", VLC_VAR_BOOL );
-            var_Set( p_playlist, "directx-wallpaper", newval );
-
-            vlc_object_release( p_playlist );
-        }
-
-        p_vout->p_sys->i_changes |= DX_WALLPAPER_CHANGE;
-    }
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * SetPalette: sets an 8 bpp palette
- *****************************************************************************/
-static void SetPalette( vout_thread_t *p_vout,
-                        uint16_t *red, uint16_t *green, uint16_t *blue )
-{
-    msg_Err( p_vout, "FIXME: SetPalette unimplemented" );
-}
diff --git a/modules/video_output/directx/events.c b/modules/video_output/directx/events.c
deleted file mode 100644 (file)
index 646563e..0000000
+++ /dev/null
@@ -1,1179 +0,0 @@
-/*****************************************************************************
- * events.c: Windows DirectX video output events handler
- *****************************************************************************
- * Copyright (C) 2001-2004 the VideoLAN team
- * $Id$
- *
- * Authors: Gildas Bazin <gbazin@videolan.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-
-/*****************************************************************************
- * Preamble: This file contains the functions related to the creation of
- *             a window and the handling of its messages (events).
- *****************************************************************************/
-#include <errno.h>                                                 /* ENOMEM */
-#include <stdlib.h>                                                /* free() */
-#include <ctype.h>                                              /* tolower() */
-#include <string.h>                                            /* strerror() */
-
-#ifndef _WIN32_WINNT
-#   define _WIN32_WINNT 0x0500
-#endif
-
-#include <vlc/vlc.h>
-#include <vlc_interface.h>
-#include <vlc_playlist.h>
-#include <vlc_vout.h>
-
-#include <windows.h>
-#include <windowsx.h>
-#include <shellapi.h>
-
-#ifdef MODULE_NAME_IS_vout_directx
-#include <ddraw.h>
-#endif
-#ifdef MODULE_NAME_IS_direct3d
-#include <d3d9.h>
-#endif
-#ifdef MODULE_NAME_IS_glwin32
-#include <GL/gl.h>
-#endif
-
-#include "vlc_keys.h"
-#include "vout.h"
-
-/*****************************************************************************
- * Local prototypes.
- *****************************************************************************/
-static int  DirectXCreateWindow( vout_thread_t *p_vout );
-static void DirectXCloseWindow ( vout_thread_t *p_vout );
-static long FAR PASCAL DirectXEventProc( HWND, UINT, WPARAM, LPARAM );
-
-static int Control( vout_thread_t *p_vout, int i_query, va_list args );
-
-static void DirectXPopupMenu( event_thread_t *p_event, vlc_bool_t b_open )
-{
-    playlist_t *p_playlist =
-        vlc_object_find( p_event, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
-    if( p_playlist != NULL )
-    {
-        vlc_value_t val;
-        val.b_bool = b_open;
-        var_Set( p_playlist, "intf-popupmenu", val );
-        vlc_object_release( p_playlist );
-    }
-}
-
-static int DirectXConvertKey( int i_key );
-
-/*****************************************************************************
- * DirectXEventThread: Create video window & handle its messages
- *****************************************************************************
- * This function creates a video window and then enters an infinite loop
- * that handles the messages sent to that window.
- * The main goal of this thread is to isolate the Win32 PeekMessage function
- * because this one can block for a long time.
- *****************************************************************************/
-void E_(DirectXEventThread)( event_thread_t *p_event )
-{
-    MSG msg;
-    POINT old_mouse_pos = {0,0}, mouse_pos;
-    vlc_value_t val;
-    int i_width, i_height, i_x, i_y;
-    HMODULE hkernel32;
-
-    /* Initialisation */
-    p_event->p_vout->pf_control = Control;
-
-    /* Create a window for the video */
-    /* Creating a window under Windows also initializes the thread's event
-     * message queue */
-    if( DirectXCreateWindow( p_event->p_vout ) )
-    {
-        msg_Err( p_event, "out of memory" );
-        p_event->b_dead = VLC_TRUE;
-    }
-
-    /* Signal the creation of the window */
-    vlc_thread_ready( p_event );
-
-    /* Set power management stuff */
-    if( (hkernel32 = GetModuleHandle( _T("KERNEL32") ) ) )
-    {
-        ULONG (WINAPI* OurSetThreadExecutionState)( ULONG );
-
-        OurSetThreadExecutionState = (ULONG (WINAPI*)( ULONG ))
-            GetProcAddress( hkernel32, _T("SetThreadExecutionState") );
-
-        if( OurSetThreadExecutionState )
-            /* Prevent monitor from powering off */
-            OurSetThreadExecutionState( ES_DISPLAY_REQUIRED | ES_CONTINUOUS );
-        else
-            msg_Dbg( p_event, "no support for SetThreadExecutionState()" );
-    }
-
-    /* Main loop */
-    /* GetMessage will sleep if there's no message in the queue */
-    while( !p_event->b_die && GetMessage( &msg, 0, 0, 0 ) )
-    {
-        /* Check if we are asked to exit */
-        if( p_event->b_die )
-            break;
-
-        switch( msg.message )
-        {
-
-        case WM_MOUSEMOVE:
-            vout_PlacePicture( p_event->p_vout,
-                               p_event->p_vout->p_sys->i_window_width,
-                               p_event->p_vout->p_sys->i_window_height,
-                               &i_x, &i_y, &i_width, &i_height );
-
-            if( msg.hwnd == p_event->p_vout->p_sys->hvideownd )
-            {
-                /* Child window */
-                i_x = i_y = 0;
-            }
-
-            if( i_width && i_height )
-            {
-                val.i_int = ( GET_X_LPARAM(msg.lParam) - i_x ) *
-                    p_event->p_vout->fmt_in.i_visible_width / i_width +
-                    p_event->p_vout->fmt_in.i_x_offset;
-                var_Set( p_event->p_vout, "mouse-x", val );
-                val.i_int = ( GET_Y_LPARAM(msg.lParam) - i_y ) *
-                    p_event->p_vout->fmt_in.i_visible_height / i_height +
-                    p_event->p_vout->fmt_in.i_y_offset;
-                var_Set( p_event->p_vout, "mouse-y", val );
-
-                val.b_bool = VLC_TRUE;
-                var_Set( p_event->p_vout, "mouse-moved", val );
-            }
-
-        case WM_NCMOUSEMOVE:
-            GetCursorPos( &mouse_pos );
-            if( (abs(mouse_pos.x - old_mouse_pos.x) > 2 ||
-                (abs(mouse_pos.y - old_mouse_pos.y)) > 2 ) )
-            {
-                GetCursorPos( &old_mouse_pos );
-                p_event->p_vout->p_sys->i_lastmoved = mdate();
-
-                if( p_event->p_vout->p_sys->b_cursor_hidden )
-                {
-                    p_event->p_vout->p_sys->b_cursor_hidden = 0;
-                    ShowCursor( TRUE );
-                }
-            }
-            break;
-
-        case WM_VLC_HIDE_MOUSE:
-            if( p_event->p_vout->p_sys->b_cursor_hidden ) break;
-            p_event->p_vout->p_sys->b_cursor_hidden = VLC_TRUE;
-            GetCursorPos( &old_mouse_pos );
-            ShowCursor( FALSE );
-            break;
-
-        case WM_VLC_SHOW_MOUSE:
-            if( !p_event->p_vout->p_sys->b_cursor_hidden ) break;
-            p_event->p_vout->p_sys->b_cursor_hidden = VLC_FALSE;
-            GetCursorPos( &old_mouse_pos );
-            ShowCursor( TRUE );
-            break;
-
-        case WM_LBUTTONDOWN:
-            var_Get( p_event->p_vout, "mouse-button-down", &val );
-            val.i_int |= 1;
-            var_Set( p_event->p_vout, "mouse-button-down", val );
-            DirectXPopupMenu( p_event, VLC_FALSE );
-            break;
-
-        case WM_LBUTTONUP:
-            var_Get( p_event->p_vout, "mouse-button-down", &val );
-            val.i_int &= ~1;
-            var_Set( p_event->p_vout, "mouse-button-down", val );
-
-            val.b_bool = VLC_TRUE;
-            var_Set( p_event->p_vout, "mouse-clicked", val );
-            break;
-
-        case WM_LBUTTONDBLCLK:
-            p_event->p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
-            break;
-
-        case WM_MBUTTONDOWN:
-            var_Get( p_event->p_vout, "mouse-button-down", &val );
-            val.i_int |= 2;
-            var_Set( p_event->p_vout, "mouse-button-down", val );
-            DirectXPopupMenu( p_event, VLC_FALSE );
-            break;
-
-        case WM_MBUTTONUP:
-            var_Get( p_event->p_vout, "mouse-button-down", &val );
-            val.i_int &= ~2;
-            var_Set( p_event->p_vout, "mouse-button-down", val );
-            break;
-
-        case WM_RBUTTONDOWN:
-            var_Get( p_event->p_vout, "mouse-button-down", &val );
-            val.i_int |= 4;
-            var_Set( p_event->p_vout, "mouse-button-down", val );
-            DirectXPopupMenu( p_event, VLC_FALSE );
-            break;
-
-        case WM_RBUTTONUP:
-            var_Get( p_event->p_vout, "mouse-button-down", &val );
-            val.i_int &= ~4;
-            var_Set( p_event->p_vout, "mouse-button-down", val );
-            DirectXPopupMenu( p_event, VLC_TRUE );
-            break;
-
-        case WM_KEYDOWN:
-        case WM_SYSKEYDOWN:
-            /* The key events are first processed here and not translated
-             * into WM_CHAR events because we need to know the status of the
-             * modifier keys. */
-            val.i_int = DirectXConvertKey( msg.wParam );
-            if( !val.i_int )
-            {
-                /* This appears to be a "normal" (ascii) key */
-                val.i_int = tolower( MapVirtualKey( msg.wParam, 2 ) );
-            }
-
-            if( val.i_int )
-            {
-                if( GetKeyState(VK_CONTROL) & 0x8000 )
-                {
-                    val.i_int |= KEY_MODIFIER_CTRL;
-                }
-                if( GetKeyState(VK_SHIFT) & 0x8000 )
-                {
-                    val.i_int |= KEY_MODIFIER_SHIFT;
-                }
-                if( GetKeyState(VK_MENU) & 0x8000 )
-                {
-                    val.i_int |= KEY_MODIFIER_ALT;
-                }
-
-                var_Set( p_event->p_libvlc, "key-pressed", val );
-            }
-            break;
-
-        case WM_MOUSEWHEEL:
-            if( GET_WHEEL_DELTA_WPARAM( msg.wParam ) > 0 )
-            {
-                val.i_int = KEY_MOUSEWHEELUP;
-            }
-            else
-            {
-                val.i_int = KEY_MOUSEWHEELDOWN;
-            }
-            if( val.i_int )
-            {
-                if( GetKeyState(VK_CONTROL) & 0x8000 )
-                {
-                    val.i_int |= KEY_MODIFIER_CTRL;
-                }
-                if( GetKeyState(VK_SHIFT) & 0x8000 )
-                {
-                    val.i_int |= KEY_MODIFIER_SHIFT;
-                }
-                if( GetKeyState(VK_MENU) & 0x8000 )
-                {
-                    val.i_int |= KEY_MODIFIER_ALT;
-                }
-
-                var_Set( p_event->p_libvlc, "key-pressed", val );
-            }
-            break;
-
-        case WM_VLC_CHANGE_TEXT:
-            var_Get( p_event->p_vout, "video-title", &val );
-            if( !val.psz_string || !*val.psz_string ) /* Default video title */
-            {
-                if( val.psz_string ) free( val.psz_string );
-
-#ifdef MODULE_NAME_IS_glwin32
-                val.psz_string = strdup( VOUT_TITLE " (OpenGL output)" );
-#endif
-#ifdef MODULE_NAME_IS_direct3d
-                val.psz_string = strdup( VOUT_TITLE " (Direct3D output)" );
-#endif
-#ifdef MODULE_NAME_IS_vout_directx
-                if( p_event->p_vout->p_sys->b_using_overlay ) val.psz_string = 
-                strdup( VOUT_TITLE " (hardware YUV overlay DirectX output)" );
-                else if( p_event->p_vout->p_sys->b_hw_yuv ) val.psz_string = 
-                strdup( VOUT_TITLE " (hardware YUV DirectX output)" );
-                else val.psz_string = 
-                strdup( VOUT_TITLE " (software RGB DirectX output)" );
-#endif
-            }
-
-#ifdef UNICODE
-            {
-                wchar_t *psz_title = malloc( strlen(val.psz_string) * 2 + 2 );
-                mbstowcs( psz_title, val.psz_string, strlen(val.psz_string)*2);
-                psz_title[strlen(val.psz_string)] = 0;
-                free( val.psz_string ); val.psz_string = (char *)psz_title;
-            }
-#endif
-
-            SetWindowText( p_event->p_vout->p_sys->hwnd,
-                           (LPCTSTR)val.psz_string );
-            if( p_event->p_vout->p_sys->hfswnd )
-                SetWindowText( p_event->p_vout->p_sys->hfswnd,
-                               (LPCTSTR)val.psz_string );
-            free( val.psz_string );
-            break;
-
-        default:
-            /* Messages we don't handle directly are dispatched to the
-             * window procedure */
-            TranslateMessage(&msg);
-            DispatchMessage(&msg);
-            break;
-
-        } /* End Switch */
-
-    } /* End Main loop */
-
-    /* Check for WM_QUIT if we created the window */
-    if( !p_event->p_vout->p_sys->hparent && msg.message == WM_QUIT )
-    {
-        msg_Warn( p_event, "WM_QUIT... should not happen!!" );
-        p_event->p_vout->p_sys->hwnd = NULL; /* Window already destroyed */
-    }
-
-    msg_Dbg( p_event, "DirectXEventThread terminating" );
-
-    /* clear the changes formerly signaled */
-    p_event->p_vout->p_sys->i_changes = 0;
-
-    DirectXCloseWindow( p_event->p_vout );
-}
-
-
-/* following functions are local */
-
-/*****************************************************************************
- * DirectXCreateWindow: create a window for the video.
- *****************************************************************************
- * Before creating a direct draw surface, we need to create a window in which
- * the video will be displayed. This window will also allow us to capture the
- * events.
- *****************************************************************************/
-static int DirectXCreateWindow( vout_thread_t *p_vout )
-{
-    HINSTANCE  hInstance;
-    HMENU      hMenu;
-    RECT       rect_window;
-    WNDCLASS   wc;                            /* window class components */
-    HICON      vlc_icon = NULL;
-    char       vlc_path[MAX_PATH+1];
-    int        i_style, i_stylex;
-
-    msg_Dbg( p_vout, "DirectXCreateWindow" );
-
-    /* Get this module's instance */
-    hInstance = GetModuleHandle(NULL);
-
-    /* If an external window was specified, we'll draw in it. */
-    p_vout->p_sys->hparent =
-        vout_RequestWindow( p_vout, &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 );
-
-    /* We create the window ourself, there is no previous window proc. */
-    p_vout->p_sys->pf_wndproc = NULL;
-
-    /* Get the Icon from the main app */
-    vlc_icon = NULL;
-#ifndef UNDER_CE
-    if( GetModuleFileName( NULL, vlc_path, MAX_PATH ) )
-    {
-        vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
-    }
-#endif
-
-    /* Fill in the window class structure */
-    wc.style         = CS_OWNDC|CS_DBLCLKS;          /* style: dbl click */
-    wc.lpfnWndProc   = (WNDPROC)DirectXEventProc;       /* event handler */
-    wc.cbClsExtra    = 0;                         /* no extra class data */
-    wc.cbWndExtra    = 0;                        /* no extra window data */
-    wc.hInstance     = hInstance;                            /* instance */
-    wc.hIcon         = vlc_icon;                /* load the vlc big icon */
-    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);    /* default cursor */
-    wc.hbrBackground = GetStockObject(BLACK_BRUSH);  /* background color */
-    wc.lpszMenuName  = NULL;                                  /* no menu */
-    wc.lpszClassName = _T("VLC DirectX");         /* use a special class */
-
-    /* Register the window class */
-    if( !RegisterClass(&wc) )
-    {
-        WNDCLASS wndclass;
-
-        if( vlc_icon ) DestroyIcon( vlc_icon );
-
-        /* Check why it failed. If it's because one already exists
-         * then fine, otherwise return with an error. */
-        if( !GetClassInfo( hInstance, _T("VLC DirectX"), &wndclass ) )
-        {
-            msg_Err( p_vout, "DirectXCreateWindow RegisterClass FAILED (err=%lu)", GetLastError() );
-            return VLC_EGENERIC;
-        }
-    }
-
-    /* Register the video sub-window class */
-    wc.lpszClassName = _T("VLC DirectX video"); wc.hIcon = 0;
-    wc.hbrBackground = NULL; /* no background color */
-    if( !RegisterClass(&wc) )
-    {
-        WNDCLASS wndclass;
-
-        /* Check why it failed. If it's because one already exists
-         * then fine, otherwise return with an error. */
-        if( !GetClassInfo( hInstance, _T("VLC DirectX video"), &wndclass ) )
-        {
-            msg_Err( p_vout, "DirectXCreateWindow RegisterClass FAILED (err=%lu)", GetLastError() );
-            return VLC_EGENERIC;
-        }
-    }
-
-    /* When you create a window you give the dimensions you wish it to
-     * have. Unfortunatly these dimensions will include the borders and
-     * titlebar. We use the following function to find out the size of
-     * the window corresponding to the useable surface we want */
-    rect_window.top    = 10;
-    rect_window.left   = 10;
-    rect_window.right  = rect_window.left + p_vout->p_sys->i_window_width;
-    rect_window.bottom = rect_window.top + p_vout->p_sys->i_window_height;
-
-    if( var_GetBool( p_vout, "video-deco" ) )
-    {
-        /* Open with window decoration */
-        AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 );
-        i_style = WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_VISIBLE|WS_CLIPCHILDREN;
-        i_stylex = 0;
-    }
-    else
-    {
-        /* No window decoration */
-        AdjustWindowRect( &rect_window, WS_POPUP, 0 );
-        i_style = WS_POPUP|WS_VISIBLE|WS_CLIPCHILDREN;
-        i_stylex = 0; // WS_EX_TOOLWINDOW; Is TOOLWINDOW really needed ?
-                      // It messes up the fullscreen window.
-    }
-
-    if( p_vout->p_sys->hparent )
-    {
-        i_style = WS_VISIBLE|WS_CLIPCHILDREN|WS_CHILD;
-        i_stylex = 0;
-    }
-
-    p_vout->p_sys->i_window_style = i_style;
-
-    /* Create the window */
-    p_vout->p_sys->hwnd =
-        CreateWindowEx( WS_EX_NOPARENTNOTIFY | i_stylex,
-                    _T("VLC DirectX"),               /* name of window class */
-                    _T(VOUT_TITLE) _T(" (DirectX Output)"),  /* window title */
-                    i_style,                                 /* window style */
-                    (p_vout->p_sys->i_window_x < 0) ? CW_USEDEFAULT :
-                        (UINT)p_vout->p_sys->i_window_x,   /* default X coordinate */
-                    (p_vout->p_sys->i_window_y < 0) ? CW_USEDEFAULT :
-                        (UINT)p_vout->p_sys->i_window_y,   /* default Y coordinate */
-                    rect_window.right - rect_window.left,    /* window width */
-                    rect_window.bottom - rect_window.top,   /* window height */
-                    p_vout->p_sys->hparent,                 /* parent window */
-                    NULL,                          /* no menu in this window */
-                    hInstance,            /* handle of this program instance */
-                    (LPVOID)p_vout );            /* send p_vout to WM_CREATE */
-
-    if( !p_vout->p_sys->hwnd )
-    {
-        msg_Warn( p_vout, "DirectXCreateWindow create window FAILED (err=%lu)", GetLastError() );
-        return VLC_EGENERIC;
-    }
-
-    if( p_vout->p_sys->hparent )
-    {
-        LONG i_style;
-
-        /* We don't want the window owner to overwrite our client area */
-        i_style = GetWindowLong( p_vout->p_sys->hparent, GWL_STYLE );
-
-        if( !(i_style & WS_CLIPCHILDREN) )
-            /* Hmmm, apparently this is a blocking call... */
-            SetWindowLong( p_vout->p_sys->hparent, GWL_STYLE,
-                           i_style | WS_CLIPCHILDREN );
-
-        /* Create our fullscreen window */
-        p_vout->p_sys->hfswnd =
-            CreateWindowEx( WS_EX_APPWINDOW, _T("VLC DirectX"),
-                            _T(VOUT_TITLE) _T(" (DirectX Output)"),
-                            WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_SIZEBOX,
-                            CW_USEDEFAULT, CW_USEDEFAULT,
-                            CW_USEDEFAULT, CW_USEDEFAULT,
-                            NULL, NULL, hInstance, NULL );
-    }
-
-    /* Append a "Always On Top" entry in the system menu */
-    hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
-    AppendMenu( hMenu, MF_SEPARATOR, 0, _T("") );
-    AppendMenu( hMenu, MF_STRING | MF_UNCHECKED,
-                       IDM_TOGGLE_ON_TOP, _T("Always on &Top") );
-
-    /* Create video sub-window. This sub window will always exactly match
-     * the size of the video, which allows us to use crazy overlay colorkeys
-     * without having them shown outside of the video area. */
-    p_vout->p_sys->hvideownd =
-    CreateWindow( _T("VLC DirectX video"), _T(""),   /* window class */
-        WS_CHILD,                   /* window style, not visible initially */
-        0, 0,
-        p_vout->render.i_width,         /* default width */
-        p_vout->render.i_height,        /* default height */
-        p_vout->p_sys->hwnd,                    /* parent window */
-        NULL, hInstance,
-        (LPVOID)p_vout );            /* send p_vout to WM_CREATE */
-
-    if( !p_vout->p_sys->hvideownd )
-        msg_Warn( p_vout, "can't create video sub-window" );
-    else
-        msg_Dbg( p_vout, "created video sub-window" );
-
-    /* Now display the window */
-    ShowWindow( p_vout->p_sys->hwnd, SW_SHOW );
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * DirectXCloseWindow: close the window created by DirectXCreateWindow
- *****************************************************************************
- * This function returns all resources allocated by DirectXCreateWindow.
- *****************************************************************************/
-static void DirectXCloseWindow( vout_thread_t *p_vout )
-{
-    msg_Dbg( p_vout, "DirectXCloseWindow" );
-
-    DestroyWindow( p_vout->p_sys->hwnd );
-    if( p_vout->p_sys->hfswnd ) DestroyWindow( p_vout->p_sys->hfswnd );
-
-    if( p_vout->p_sys->hparent )
-        vout_ReleaseWindow( p_vout, (void *)p_vout->p_sys->hparent );
-
-    p_vout->p_sys->hwnd = NULL;
-
-    /* We don't unregister the Window Class because it could lead to race
-     * conditions and it will be done anyway by the system when the app will
-     * exit */
-}
-
-/*****************************************************************************
- * DirectXUpdateRects: update clipping rectangles
- *****************************************************************************
- * This function is called when the window position or size are changed, and
- * its job is to update the source and destination RECTs used to display the
- * picture.
- *****************************************************************************/
-void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
-{
-#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
-
-    int i_width, i_height, i_x, i_y;
-
-    RECT  rect;
-    POINT point;
-
-    /* Retrieve the window size */
-    GetClientRect( p_vout->p_sys->hwnd, &rect );
-
-    /* Retrieve the window position */
-    point.x = point.y = 0;
-    ClientToScreen( p_vout->p_sys->hwnd, &point );
-
-    /* If nothing changed, we can return */
-    if( !b_force
-         && p_vout->p_sys->i_window_width == rect.right
-         && p_vout->p_sys->i_window_height == rect.bottom
-         && p_vout->p_sys->i_window_x == point.x
-         && p_vout->p_sys->i_window_y == point.y )
-    {
-        return;
-    }
-
-    /* Update the window position and size */
-    p_vout->p_sys->i_window_x = point.x;
-    p_vout->p_sys->i_window_y = point.y;
-    p_vout->p_sys->i_window_width = rect.right;
-    p_vout->p_sys->i_window_height = rect.bottom;
-
-    vout_PlacePicture( p_vout, rect.right, rect.bottom,
-                       &i_x, &i_y, &i_width, &i_height );
-
-    if( p_vout->p_sys->hvideownd )
-        SetWindowPos( p_vout->p_sys->hvideownd, 0,
-                      i_x, i_y, i_width, i_height,
-                      SWP_NOCOPYBITS|SWP_NOZORDER|SWP_ASYNCWINDOWPOS );
-
-    /* Destination image position and dimensions */
-    rect_dest.left = point.x + i_x;
-    rect_dest.right = rect_dest.left + i_width;
-    rect_dest.top = point.y + i_y;
-    rect_dest.bottom = rect_dest.top + i_height;
-
-#ifdef MODULE_NAME_IS_vout_directx
-    /* Apply overlay hardware constraints */
-    if( p_vout->p_sys->b_using_overlay )
-    {
-        if( p_vout->p_sys->i_align_dest_boundary )
-            rect_dest.left = ( rect_dest.left +
-                p_vout->p_sys->i_align_dest_boundary / 2 ) & 
-                ~p_vout->p_sys->i_align_dest_boundary;
-
-        if( p_vout->p_sys->i_align_dest_size )
-            rect_dest.right = (( rect_dest.right - rect_dest.left +
-                p_vout->p_sys->i_align_dest_size / 2 ) & 
-                ~p_vout->p_sys->i_align_dest_size) + rect_dest.left;
-    }
-
-    /* UpdateOverlay directdraw function doesn't automatically clip to the
-     * display size so we need to do it otherwise it will fail */
-
-    /* Clip the destination window */
-    if( !IntersectRect( &rect_dest_clipped, &rect_dest,
-                        &p_vout->p_sys->rect_display ) )
-    {
-        SetRectEmpty( &rect_src_clipped );
-        return;
-    }
-
-#if 0
-    msg_Dbg( p_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 );
-#endif
-
-    /* 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;
-    }
-#else /* MODULE_NAME_IS_vout_directx */
-
-    /* AFAIK, there are no clipping constraints in Direct3D or OpenGL */
-    rect_dest_clipped = rect_dest;
-
-#endif
-
-    /* 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 = p_vout->fmt_out.i_x_offset +
-      (rect_dest_clipped.left - rect_dest.left) *
-      p_vout->fmt_out.i_visible_width / (rect_dest.right - rect_dest.left);
-    rect_src_clipped.right = p_vout->fmt_out.i_x_offset +
-      p_vout->fmt_out.i_visible_width -
-      (rect_dest.right - rect_dest_clipped.right) *
-      p_vout->fmt_out.i_visible_width / (rect_dest.right - rect_dest.left);
-    rect_src_clipped.top = p_vout->fmt_out.i_y_offset +
-      (rect_dest_clipped.top - rect_dest.top) *
-      p_vout->fmt_out.i_visible_height / (rect_dest.bottom - rect_dest.top);
-    rect_src_clipped.bottom = p_vout->fmt_out.i_y_offset +
-      p_vout->fmt_out.i_visible_height -
-      (rect_dest.bottom - rect_dest_clipped.bottom) *
-      p_vout->fmt_out.i_visible_height / (rect_dest.bottom - rect_dest.top);
-
-#ifdef MODULE_NAME_IS_vout_directx
-    /* Apply overlay hardware constraints */
-    if( p_vout->p_sys->b_using_overlay )
-    {
-        if( p_vout->p_sys->i_align_src_boundary )
-            rect_src_clipped.left = ( rect_src_clipped.left +
-                p_vout->p_sys->i_align_src_boundary / 2 ) & 
-                ~p_vout->p_sys->i_align_src_boundary;
-
-        if( p_vout->p_sys->i_align_src_size )
-            rect_src_clipped.right = (( rect_src_clipped.right -
-                rect_src_clipped.left +
-                p_vout->p_sys->i_align_src_size / 2 ) & 
-                ~p_vout->p_sys->i_align_src_size) + rect_src_clipped.left;
-    }
-#endif
-
-#if 0
-    msg_Dbg( p_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 );
-#endif
-
-#ifdef MODULE_NAME_IS_vout_directx
-    /* The destination coordinates need to be relative to the current
-     * directdraw primary surface (display) */
-    rect_dest_clipped.left -= p_vout->p_sys->rect_display.left;
-    rect_dest_clipped.right -= p_vout->p_sys->rect_display.left;
-    rect_dest_clipped.top -= p_vout->p_sys->rect_display.top;
-    rect_dest_clipped.bottom -= p_vout->p_sys->rect_display.top;
-
-    if( p_vout->p_sys->b_using_overlay )
-        E_(DirectXUpdateOverlay)( p_vout );
-#endif
-
-    /* Signal the change in size/position */
-    p_vout->p_sys->i_changes |= DX_POSITION_CHANGE;
-
-#undef rect_src
-#undef rect_src_clipped
-#undef rect_dest
-#undef rect_dest_clipped
-}
-
-/*****************************************************************************
- * DirectXEventProc: This is the window event processing function.
- *****************************************************************************
- * On Windows, when you create a window you have to attach an event processing
- * function to it. The aim of this function is to manage "Queued Messages" and
- * "Nonqueued Messages".
- * Queued Messages are those picked up and retransmitted by vout_Manage
- * (using the GetMessage and DispatchMessage functions).
- * Nonqueued Messages are those that Windows will send directly to this
- * procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...)
- *****************************************************************************/
-static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
-                                         WPARAM wParam, LPARAM lParam )
-{
-    vout_thread_t *p_vout;
-
-    if( message == WM_CREATE )
-    {
-        /* Store p_vout for future use */
-        p_vout = (vout_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams;
-        SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)p_vout );
-        return TRUE;
-    }
-    else
-    {
-        p_vout = (vout_thread_t *)GetWindowLongPtr( hwnd, GWLP_USERDATA );
-        if( !p_vout )
-        {
-            /* Hmmm mozilla does manage somehow to save the pointer to our
-             * windowproc and still calls it after the vout has been closed. */
-            return DefWindowProc(hwnd, message, wParam, lParam);
-        }
-    }
-
-    /* Catch the screensaver and the monitor turn-off */
-    if( message == WM_SYSCOMMAND &&
-        ( (wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER ) )
-    {
-        //if( p_vout ) msg_Dbg( p_vout, "WinProc WM_SYSCOMMAND screensaver" );
-        return 0; /* this stops them from happening */
-    }
-
-    if( hwnd == p_vout->p_sys->hvideownd )
-    {
-        switch( message )
-        {
-#ifdef MODULE_NAME_IS_vout_directx
-        case WM_ERASEBKGND:
-        /* For overlay, we need to erase background */
-            return !p_vout->p_sys->b_using_overlay ?
-                1 : DefWindowProc(hwnd, message, wParam, lParam);
-        case WM_PAINT:
-        /*
-        ** For overlay, DefWindowProc() will erase dirty regions
-        ** with colorkey.
-        ** For non-overlay, vout will paint the whole window at 
-        ** regular interval, therefore dirty regions can be ignored
-        ** to minimize repaint.
-        */
-            if( !p_vout->p_sys->b_using_overlay )
-            {
-                ValidateRect(hwnd, NULL);
-            }
-            // fall through to default
-#else
-        /*
-        ** For OpenGL and Direct3D, vout will update the whole
-        ** window at regular interval, therefore dirty region
-        ** can be ignored to minimize repaint.
-        */
-        case WM_ERASEBKGND:
-            /* nothing to erase */
-            return 1;
-        case WM_PAINT:
-            /* nothing to repaint */
-            ValidateRect(hwnd, NULL);
-            // fall through
-#endif 
-        default:
-            return DefWindowProc(hwnd, message, wParam, lParam);
-        }
-    }
-
-    switch( message )
-    {
-
-    case WM_WINDOWPOSCHANGED:
-        E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
-        return 0;
-
-    /* the user wants to close the window */
-    case WM_CLOSE:
-    {
-        playlist_t * p_playlist =
-            (playlist_t *)vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST,
-                                           FIND_ANYWHERE );
-        if( p_playlist == NULL )
-        {
-            return 0;
-        }
-
-        playlist_Stop( p_playlist );
-        vlc_object_release( p_playlist );
-        return 0;
-    }
-
-    /* the window has been closed so shut down everything now */
-    case WM_DESTROY:
-        msg_Dbg( p_vout, "WinProc WM_DESTROY" );
-        /* just destroy the window */
-        PostQuitMessage( 0 );
-        return 0;
-
-    case WM_SYSCOMMAND:
-        switch (wParam)
-        {
-            case IDM_TOGGLE_ON_TOP:            /* toggle the "on top" status */
-            {
-                vlc_value_t val;
-                msg_Dbg( p_vout, "WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP");
-
-                /* Change the current value */
-                var_Get( p_vout, "video-on-top", &val );
-                val.b_bool = !val.b_bool;
-                var_Set( p_vout, "video-on-top", val );
-                return 0;
-            }
-        }
-        break;
-
-    case WM_PAINT:
-    case WM_NCPAINT:
-    case WM_ERASEBKGND:
-        return DefWindowProc(hwnd, message, wParam, lParam);
-
-    default:
-        //msg_Dbg( p_vout, "WinProc WM Default %i", message );
-        break;
-    }
-
-    /* Let windows handle the message */
-    return DefWindowProc(hwnd, message, wParam, lParam);
-}
-
-static struct
-{
-    int i_dxkey;
-    int i_vlckey;
-
-} dxkeys_to_vlckeys[] =
-{
-    { VK_F1, KEY_F1 }, { VK_F2, KEY_F2 }, { VK_F3, KEY_F3 }, { VK_F4, KEY_F4 },
-    { VK_F5, KEY_F5 }, { VK_F6, KEY_F6 }, { VK_F7, KEY_F7 }, { VK_F8, KEY_F8 },
-    { VK_F9, KEY_F9 }, { VK_F10, KEY_F10 }, { VK_F11, KEY_F11 },
-    { VK_F12, KEY_F12 },
-
-    { VK_RETURN, KEY_ENTER },
-    { VK_SPACE, KEY_SPACE },
-    { VK_ESCAPE, KEY_ESC },
-
-    { VK_LEFT, KEY_LEFT },
-    { VK_RIGHT, KEY_RIGHT },
-    { VK_UP, KEY_UP },
-    { VK_DOWN, KEY_DOWN },
-
-    { VK_HOME, KEY_HOME },
-    { VK_END, KEY_END },
-    { VK_PRIOR, KEY_PAGEUP },
-    { VK_NEXT, KEY_PAGEDOWN },
-
-    { VK_INSERT, KEY_INSERT },
-    { VK_DELETE, KEY_DELETE },
-
-    { VK_CONTROL, 0 },
-    { VK_SHIFT, 0 },
-    { VK_MENU, 0 },
-
-    { VK_BROWSER_BACK, KEY_BROWSER_BACK },
-    { VK_BROWSER_FORWARD, KEY_BROWSER_FORWARD },
-    { VK_BROWSER_REFRESH, KEY_BROWSER_REFRESH },
-    { VK_BROWSER_STOP, KEY_BROWSER_STOP },
-    { VK_BROWSER_SEARCH, KEY_BROWSER_SEARCH },
-    { VK_BROWSER_FAVORITES, KEY_BROWSER_FAVORITES },
-    { VK_BROWSER_HOME, KEY_BROWSER_HOME },
-    { VK_VOLUME_MUTE, KEY_VOLUME_MUTE },
-    { VK_VOLUME_DOWN, KEY_VOLUME_DOWN },
-    { VK_VOLUME_UP, KEY_VOLUME_UP },
-    { VK_MEDIA_NEXT_TRACK, KEY_MEDIA_NEXT_TRACK },
-    { VK_MEDIA_PREV_TRACK, KEY_MEDIA_PREV_TRACK },
-    { VK_MEDIA_STOP, KEY_MEDIA_STOP },
-    { VK_MEDIA_PLAY_PAUSE, KEY_MEDIA_PLAY_PAUSE },
-
-    { 0, 0 }
-};
-
-static int DirectXConvertKey( int i_key )
-{
-    int i;
-
-    for( i = 0; dxkeys_to_vlckeys[i].i_dxkey != 0; i++ )
-    {
-        if( dxkeys_to_vlckeys[i].i_dxkey == i_key )
-        {
-            return dxkeys_to_vlckeys[i].i_vlckey;
-        }
-    }
-
-    return 0;
-}
-
-/*****************************************************************************
- * Control: control facility for the vout
- *****************************************************************************/
-static int Control( vout_thread_t *p_vout, int i_query, va_list args )
-{
-    unsigned int *pi_width, *pi_height;
-    RECT rect_window;
-    POINT point;
-
-    switch( i_query )
-    {
-    case VOUT_GET_SIZE:
-        if( p_vout->p_sys->hparent )
-            return vout_ControlWindow( p_vout,
-                    (void *)p_vout->p_sys->hparent, i_query, args );
-
-        pi_width  = va_arg( args, unsigned int * );
-        pi_height = va_arg( args, unsigned int * );
-
-        GetClientRect( p_vout->p_sys->hwnd, &rect_window );
-
-        *pi_width  = rect_window.right - rect_window.left;
-        *pi_height = rect_window.bottom - rect_window.top;
-        return VLC_SUCCESS;
-
-    case VOUT_SET_SIZE:
-        if( p_vout->p_sys->hparent )
-            return vout_ControlWindow( p_vout,
-                    (void *)p_vout->p_sys->hparent, i_query, args );
-
-        /* Update dimensions */
-        rect_window.top = rect_window.left = 0;
-        rect_window.right  = va_arg( args, unsigned int );
-        rect_window.bottom = va_arg( args, unsigned int );
-        if( !rect_window.right ) rect_window.right = p_vout->i_window_width;
-        if( !rect_window.bottom ) rect_window.bottom = p_vout->i_window_height;
-        AdjustWindowRect( &rect_window, p_vout->p_sys->i_window_style, 0 );
-
-        SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
-                      rect_window.right - rect_window.left,
-                      rect_window.bottom - rect_window.top, SWP_NOMOVE );
-
-        return VLC_SUCCESS;
-
-    case VOUT_CLOSE:
-        ShowWindow( p_vout->p_sys->hwnd, SW_HIDE );
-    case VOUT_REPARENT:
-        /* Retrieve the window position */
-        point.x = point.y = 0;
-        ClientToScreen( p_vout->p_sys->hwnd, &point );
-
-        HWND d = 0;
-
-        if( i_query == VOUT_REPARENT ) d = (HWND)va_arg( args, int );
-        if( !d )
-        {
-            vlc_mutex_lock( &p_vout->p_sys->lock );
-            p_vout->p_sys->hparent = 0;
-            vlc_mutex_unlock( &p_vout->p_sys->lock );
-            SetParent( p_vout->p_sys->hwnd, 0 );
-            p_vout->p_sys->i_window_style =
-                WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
-            SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE,
-                           p_vout->p_sys->i_window_style |
-                           (i_query == VOUT_CLOSE ? 0 : WS_VISIBLE) );
-            SetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW );
-            SetWindowPos( p_vout->p_sys->hwnd, 0, point.x, point.y, 0, 0,
-                          SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED );
-        }
-        else
-        {
-            vlc_mutex_lock( &p_vout->p_sys->lock );
-            p_vout->p_sys->hparent = d;
-            vlc_mutex_unlock( &p_vout->p_sys->lock );
-
-            SetParent( p_vout->p_sys->hwnd, d );
-            p_vout->p_sys->i_window_style = WS_CLIPCHILDREN;
-            SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE,
-                           p_vout->p_sys->i_window_style |
-                           (i_query == VOUT_CLOSE ? 0 : WS_VISIBLE) );
-            SetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW );
-
-            /* Retrieve the parent size */
-            RECT  rect;
-            GetClientRect( d, &rect );
-            SetWindowPos( p_vout->p_sys->hwnd, d, point.x, point.y, rect.right, rect.bottom,
-                          SWP_FRAMECHANGED );
-        }
-
-        return vout_vaControlDefault( p_vout, i_query, args );
-
-    case VOUT_SET_STAY_ON_TOP:
-        if( p_vout->p_sys->hparent && !var_GetBool( p_vout, "fullscreen" ) )
-            return vout_ControlWindow( p_vout,
-                    (void *)p_vout->p_sys->hparent, i_query, args );
-
-        p_vout->p_sys->b_on_top_change = VLC_TRUE;
-        return VLC_SUCCESS;
-
-    default:
-        return vout_vaControlDefault( p_vout, i_query, args );
-    }
-}
-
-
-/* Internal wrapper over GetWindowPlacement / SetWindowPlacement */ 
-static void SetWindowState(HWND hwnd, int nShowCmd)
-{
-    WINDOWPLACEMENT window_placement;
-    window_placement.length = sizeof(WINDOWPLACEMENT);
-    GetWindowPlacement( hwnd, &window_placement );
-    window_placement.showCmd = nShowCmd;
-    SetWindowPlacement( hwnd, &window_placement );
-    SetWindowPos( hwnd, 0, 0, 0, 0, 0,
-        SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
-}
-
-/* Internal wrapper to call vout_ControlWindow for hparent */
-static void ControlParentWindow( vout_thread_t *p_vout, int i_query, ... )
-{
-    va_list args;
-    va_start( args, i_query );
-    vout_ControlWindow( p_vout,
-        (void *)p_vout->p_sys->hparent, i_query, args );
-    va_end( args );
-}
-
-void Win32ToggleFullscreen( vout_thread_t *p_vout )
-{
-    HWND hwnd = (p_vout->p_sys->hparent && p_vout->p_sys->hfswnd) ?
-        p_vout->p_sys->hfswnd : p_vout->p_sys->hwnd;
-
-    p_vout->b_fullscreen = ! p_vout->b_fullscreen;
-
-    if( p_vout->b_fullscreen )
-    {
-        msg_Dbg( p_vout, "entering fullscreen mode" );
-        /* Change window style, no borders and no title bar */
-        int i_style = WS_CLIPCHILDREN | WS_VISIBLE;
-        SetWindowLong( hwnd, GWL_STYLE, i_style );
-
-        if( p_vout->p_sys->hparent )
-        {
-            /* Retrieve current window position so fullscreen will happen
-            * on the right screen */
-            POINT point = {0,0};
-            RECT rect;
-            ClientToScreen( p_vout->p_sys->hwnd, &point );
-            GetClientRect( p_vout->p_sys->hwnd, &rect );
-            SetWindowPos( hwnd, 0, point.x, point.y,
-                          rect.right, rect.bottom,
-                          SWP_NOZORDER|SWP_FRAMECHANGED );
-        }
-
-        /* Maximize window */
-        SetWindowState( hwnd, SW_SHOWMAXIMIZED );
-
-        if( p_vout->p_sys->hparent )
-        {
-            RECT rect;
-            GetClientRect( hwnd, &rect );
-            SetParent( p_vout->p_sys->hwnd, hwnd );
-            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
-                          rect.right, rect.bottom,
-                          SWP_NOZORDER|SWP_FRAMECHANGED );
-
-            HWND topLevelParent = GetAncestor( p_vout->p_sys->hparent, GA_ROOT );
-            ShowWindow( topLevelParent, SW_HIDE );
-        }
-
-        SetForegroundWindow( hwnd );
-    }
-    else
-    {
-        msg_Dbg( p_vout, "leaving fullscreen mode" );
-        /* Change window style, no borders and no title bar */
-        SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style );
-
-        /* Normal window */
-        SetWindowState( hwnd, SW_SHOWNORMAL );
-
-        if( p_vout->p_sys->hparent )
-        {
-            RECT rect;
-            GetClientRect( p_vout->p_sys->hparent, &rect );
-            SetParent( p_vout->p_sys->hwnd, p_vout->p_sys->hparent );
-            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
-                          rect.right, rect.bottom,
-                          SWP_NOZORDER|SWP_FRAMECHANGED );
-
-            HWND topLevelParent = GetAncestor( p_vout->p_sys->hparent, GA_ROOT );
-            ShowWindow( topLevelParent, SW_SHOW );
-            SetForegroundWindow( p_vout->p_sys->hparent );
-            ShowWindow( hwnd, SW_HIDE );
-
-            /* Update "video-on-top" status for main interface window, it
-            needs to be updated as we were hiding VOUT_SET_STAY_ON_TOP
-            queries from it while we were in fullscreen mode */
-            int b_ontop = var_GetBool( p_vout, "video-on-top" );
-            ControlParentWindow( p_vout, VOUT_SET_STAY_ON_TOP, b_ontop );
-        }
-
-        /* Make sure the mouse cursor is displayed */
-        PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 );
-    }
-
-    {
-        vlc_value_t val;
-        /* Update the object variable and trigger callback */
-        val.b_bool = p_vout->b_fullscreen;
-        var_Set( p_vout, "fullscreen", val );
-    }
-}
diff --git a/modules/video_output/directx/glwin32.c b/modules/video_output/directx/glwin32.c
deleted file mode 100644 (file)
index 14fe9b2..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-/*****************************************************************************
- * glwin32.c: Windows OpenGL provider
- *****************************************************************************
- * Copyright (C) 2001-2004 the VideoLAN team
- * $Id$
- *
- * Authors: Gildas Bazin <gbazin@videolan.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#include <errno.h>                                                 /* ENOMEM */
-#include <stdlib.h>                                                /* free() */
-#include <string.h>                                            /* strerror() */
-
-#include <vlc/vlc.h>
-#include <vlc_interface.h>
-#include <vlc_vout.h>
-
-#include <windows.h>
-#include <ddraw.h>
-#include <commctrl.h>
-
-#include <multimon.h>
-#undef GetSystemMetrics
-
-#ifndef MONITOR_DEFAULTTONEAREST
-#   define MONITOR_DEFAULTTONEAREST 2
-#endif
-
-#include <GL/gl.h>
-
-#include "vout.h"
-
-/*****************************************************************************
- * Local prototypes.
- *****************************************************************************/
-static int  OpenVideo  ( vlc_object_t * );
-static void CloseVideo ( vlc_object_t * );
-
-static int  Init      ( vout_thread_t * );
-static void End       ( vout_thread_t * );
-static int  Manage    ( vout_thread_t * );
-static void GLSwapBuffers( vout_thread_t * );
-static void FirstSwap( vout_thread_t * );
-
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-vlc_module_begin();
-    set_category( CAT_VIDEO );
-    set_subcategory( SUBCAT_VIDEO_VOUT );
-    set_shortname( "OpenGL" );
-    set_description( _("OpenGL video output") );
-    set_capability( "opengl provider", 100 );
-    add_shortcut( "glwin32" );
-    set_callbacks( OpenVideo, CloseVideo );
-
-    /* FIXME: Hack to avoid unregistering our window class */
-    linked_with_a_crap_library_which_uses_atexit( );
-vlc_module_end();
-
-#if 0 /* FIXME */
-    /* check if we registered a window class because we need to
-     * unregister it */
-    WNDCLASS wndclass;
-    if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )
-        UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );
-#endif
-
-/*****************************************************************************
- * OpenVideo: allocate OpenGL provider
- *****************************************************************************
- * This function creates and initializes a video window.
- *****************************************************************************/
-static int OpenVideo( vlc_object_t *p_this )
-{
-    vout_thread_t * p_vout = (vout_thread_t *)p_this;
-    vlc_value_t val;
-
-    /* Allocate structure */
-    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
-    if( p_vout->p_sys == NULL )
-    {
-        msg_Err( p_vout, "out of memory" );
-        return VLC_ENOMEM;
-    }
-    memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
-
-    /* Initialisations */
-    p_vout->pf_init = Init;
-    p_vout->pf_end = End;
-    p_vout->pf_manage = Manage;
-    p_vout->pf_swap = FirstSwap;
-
-    p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
-    p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
-    p_vout->p_sys->i_changes = 0;
-    p_vout->p_sys->b_wallpaper = 0;
-    vlc_mutex_init( p_vout, &p_vout->p_sys->lock );
-    SetRectEmpty( &p_vout->p_sys->rect_display );
-    SetRectEmpty( &p_vout->p_sys->rect_parent );
-
-    var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
-
-    p_vout->p_sys->b_cursor_hidden = 0;
-    p_vout->p_sys->i_lastmoved = mdate();
-
-    /* Set main window's size */
-    p_vout->p_sys->i_window_width = p_vout->i_window_width;
-    p_vout->p_sys->i_window_height = p_vout->i_window_height;
-
-    /* Create the DirectXEventThread, this thread is created by us to isolate
-     * the Win32 PeekMessage function calls. We want to do this because
-     * Windows can stay blocked inside this call for a long time, and when
-     * this happens it thus blocks vlc's video_output thread.
-     * DirectXEventThread will take care of the creation of the video
-     * window (because PeekMessage has to be called from the same thread which
-     * created the window). */
-    msg_Dbg( p_vout, "creating DirectXEventThread" );
-    p_vout->p_sys->p_event =
-        vlc_object_create( p_vout, sizeof(event_thread_t) );
-    p_vout->p_sys->p_event->p_vout = p_vout;
-    if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread",
-                           E_(DirectXEventThread), 0, 1 ) )
-    {
-        msg_Err( p_vout, "cannot create DirectXEventThread" );
-        vlc_object_destroy( p_vout->p_sys->p_event );
-        p_vout->p_sys->p_event = NULL;
-        goto error;
-    }
-
-    if( p_vout->p_sys->p_event->b_error )
-    {
-        msg_Err( p_vout, "DirectXEventThread failed" );
-        goto error;
-    }
-
-    vlc_object_attach( p_vout->p_sys->p_event, p_vout );
-
-    msg_Dbg( p_vout, "DirectXEventThread running" );
-
-    /* Variable to indicate if the window should be on top of others */
-    /* Trigger a callback right now */
-    var_Get( p_vout, "video-on-top", &val );
-    var_Set( p_vout, "video-on-top", val );
-
-    return VLC_SUCCESS;
-
- error:
-    CloseVideo( VLC_OBJECT(p_vout) );
-    return VLC_EGENERIC;
-}
-
-/*****************************************************************************
- * Init: initialize video thread output method
- *****************************************************************************/
-static int Init( vout_thread_t *p_vout )
-{
-    PIXELFORMATDESCRIPTOR pfd;
-    int iFormat;
-
-    /* Change the window title bar text */
-    PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
-
-    p_vout->p_sys->hGLDC = GetDC( p_vout->p_sys->hvideownd );
-
-    /* Set the pixel format for the DC */
-    memset( &pfd, 0, sizeof( pfd ) );
-    pfd.nSize = sizeof( pfd );
-    pfd.nVersion = 1;
-    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
-    pfd.iPixelType = PFD_TYPE_RGBA;
-    pfd.cColorBits = 24;
-    pfd.cDepthBits = 16;
-    pfd.iLayerType = PFD_MAIN_PLANE;
-    iFormat = ChoosePixelFormat( p_vout->p_sys->hGLDC, &pfd );
-    SetPixelFormat( p_vout->p_sys->hGLDC, iFormat, &pfd );
-
-    /* Create and enable the render context */
-    p_vout->p_sys->hGLRC = wglCreateContext( p_vout->p_sys->hGLDC );
-    wglMakeCurrent( p_vout->p_sys->hGLDC, p_vout->p_sys->hGLRC );
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * End: terminate Sys video thread output method
- *****************************************************************************
- * Terminate an output method created by Create.
- * It is called at the end of the thread.
- *****************************************************************************/
-static void End( vout_thread_t *p_vout )
-{
-    wglMakeCurrent( NULL, NULL );
-    wglDeleteContext( p_vout->p_sys->hGLRC );
-    ReleaseDC( p_vout->p_sys->hvideownd, p_vout->p_sys->hGLDC );
-    return;
-}
-
-/*****************************************************************************
- * CloseVideo: destroy Sys video thread output method
- *****************************************************************************
- * Terminate an output method created by Create
- *****************************************************************************/
-static void CloseVideo( vlc_object_t *p_this )
-{
-    vout_thread_t * p_vout = (vout_thread_t *)p_this;
-
-    msg_Dbg( p_vout, "closing video" );
-
-    if( p_vout->p_sys->p_event )
-    {
-        vlc_object_detach( p_vout->p_sys->p_event );
-
-        /* Kill DirectXEventThread */
-        p_vout->p_sys->p_event->b_die = VLC_TRUE;
-
-        /* we need to be sure DirectXEventThread won't stay stuck in
-         * GetMessage, so we send a fake message */
-        if( p_vout->p_sys->hwnd )
-        {
-            PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);
-        }
-
-        vlc_thread_join( p_vout->p_sys->p_event );
-        vlc_object_destroy( p_vout->p_sys->p_event );
-    }
-
-    vlc_mutex_destroy( &p_vout->p_sys->lock );
-
-    if( p_vout->p_sys )
-    {
-        free( p_vout->p_sys );
-        p_vout->p_sys = NULL;
-    }
-}
-
-/*****************************************************************************
- * Manage: handle Sys events
- *****************************************************************************
- * This function should be called regularly by the video output thread.
- * It returns a non null value if an error occurred.
- *****************************************************************************/
-static int Manage( vout_thread_t *p_vout )
-{
-    int i_width = p_vout->p_sys->rect_dest.right -
-        p_vout->p_sys->rect_dest.left;
-    int i_height = p_vout->p_sys->rect_dest.bottom -
-        p_vout->p_sys->rect_dest.top;
-    glViewport( 0, 0, i_width, i_height );
-
-    /* If we do not control our window, we check for geometry changes
-     * ourselves because the parent might not send us its events. */
-    vlc_mutex_lock( &p_vout->p_sys->lock );
-    if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
-    {
-        RECT rect_parent;
-        POINT point;
-
-        vlc_mutex_unlock( &p_vout->p_sys->lock );
-
-        GetClientRect( p_vout->p_sys->hparent, &rect_parent );
-        point.x = point.y = 0;
-        ClientToScreen( p_vout->p_sys->hparent, &point );
-        OffsetRect( &rect_parent, point.x, point.y );
-
-        if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
-        {
-            p_vout->p_sys->rect_parent = rect_parent;
-
-            /* This one is to force the update even if only
-             * the position has changed */
-            SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1,
-                          rect_parent.right - rect_parent.left,
-                          rect_parent.bottom - rect_parent.top, 0 );
-
-            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
-                          rect_parent.right - rect_parent.left,
-                          rect_parent.bottom - rect_parent.top, 0 );
-        }
-    }
-    else
-    {
-        vlc_mutex_unlock( &p_vout->p_sys->lock );
-    }
-
-    /* Check for cropping / aspect changes */
-    if( p_vout->i_changes & VOUT_CROP_CHANGE ||
-        p_vout->i_changes & VOUT_ASPECT_CHANGE )
-    {
-        p_vout->i_changes &= ~VOUT_CROP_CHANGE;
-        p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
-
-        p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset;
-        p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset;
-        p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width;
-        p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height;
-        p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect;
-        p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;
-        p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;
-        p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
-        E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
-    }
-
-    /* We used to call the Win32 PeekMessage function here to read the window
-     * messages. But since window can stay blocked into this function for a
-     * long time (for example when you move your window on the screen), I
-     * decided to isolate PeekMessage in another thread. */
-
-    /*
-     * Fullscreen change
-     */
-    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
-        || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
-    {
-        Win32ToggleFullscreen( p_vout );
-
-        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
-        p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
-    }
-
-    /*
-     * Pointer change
-     */
-    if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&
-        (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 )
-    {
-        POINT point;
-        HWND hwnd;
-
-        /* Hide the cursor only if it is inside our window */
-        GetCursorPos( &point );
-        hwnd = WindowFromPoint(point);
-        if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )
-        {
-            PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
-        }
-        else
-        {
-            p_vout->p_sys->i_lastmoved = mdate();
-        }
-    }
-
-    /*
-     * "Always on top" status change
-     */
-    if( p_vout->p_sys->b_on_top_change )
-    {
-        vlc_value_t val;
-        HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
-
-        var_Get( p_vout, "video-on-top", &val );
-
-        /* Set the window on top if necessary */
-        if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
-                           & WS_EX_TOPMOST ) )
-        {
-            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
-                           MF_BYCOMMAND | MFS_CHECKED );
-            SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,
-                          SWP_NOSIZE | SWP_NOMOVE );
-        }
-        else
-        /* The window shouldn't be on top */
-        if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
-                           & WS_EX_TOPMOST ) )
-        {
-            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
-                           MF_BYCOMMAND | MFS_UNCHECKED );
-            SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
-                          SWP_NOSIZE | SWP_NOMOVE );
-        }
-
-        p_vout->p_sys->b_on_top_change = VLC_FALSE;
-    }
-
-    /* Check if the event thread is still running */
-    if( p_vout->p_sys->p_event->b_die )
-    {
-        return VLC_EGENERIC; /* exit */
-    }
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * GLSwapBuffers: swap front/back buffers
- *****************************************************************************/
-static void GLSwapBuffers( vout_thread_t *p_vout )
-{
-    SwapBuffers( p_vout->p_sys->hGLDC );
-}
-
-/*
-** this function is only used once when the first picture is received
-** this function will show the video window once a picture is ready
-*/
-
-static void FirstSwap( vout_thread_t *p_vout )
-{
-    /* get initial picture buffer swapped to front buffer */
-    GLSwapBuffers( p_vout );
-
-    /*
-    ** Video window is initially hidden, show it now since we got a 
-    ** picture to show.
-    */
-    SetWindowPos( p_vout->p_sys->hvideownd, NULL, 0, 0, 0, 0, 
-        SWP_ASYNCWINDOWPOS|
-        SWP_FRAMECHANGED|
-        SWP_SHOWWINDOW|
-        SWP_NOMOVE|
-        SWP_NOSIZE|
-        SWP_NOZORDER );
-
-    /* use and restores proper swap function for further pictures */
-    p_vout->pf_swap = GLSwapBuffers;
-}
diff --git a/modules/video_output/directx/vout.h b/modules/video_output/directx/vout.h
deleted file mode 100644 (file)
index 5fe7d98..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/*****************************************************************************
- * vout.h: Windows DirectX video output header file
- *****************************************************************************
- * Copyright (C) 2001-2004 the VideoLAN team
- * $Id$
- *
- * Authors: Gildas Bazin <gbazin@videolan.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * event_thread_t: DirectX event thread
- *****************************************************************************/
-typedef struct event_thread_t
-{
-    VLC_COMMON_MEMBERS
-
-    vout_thread_t * p_vout;
-
-} event_thread_t;
-
-/*****************************************************************************
- * vout_sys_t: video output DirectX method descriptor
- *****************************************************************************
- * This structure is part of the video output thread descriptor.
- * It describes the DirectX specific properties of an output thread.
- *****************************************************************************/
-struct vout_sys_t
-{
-    HWND                 hwnd;                  /* Handle of the main window */
-    HWND                 hvideownd;        /* Handle of the video sub-window */
-    HWND                 hparent;             /* Handle of the parent window */
-    HWND                 hfswnd;          /* Handle of the fullscreen window */
-    WNDPROC              pf_wndproc;             /* Window handling callback */
-
-    /* Multi-monitor support */
-    HMONITOR             hmonitor;          /* handle of the current monitor */
-    GUID                 *p_display_driver;
-    HMONITOR             (WINAPI* MonitorFromWindow)( HWND, DWORD );
-    BOOL                 (WINAPI* GetMonitorInfo)( HMONITOR, LPMONITORINFO );
-
-    /* size of the display */
-    RECT         rect_display;
-    int          i_display_depth;
-
-    /* size of the overall window (including black bands) */
-    RECT         rect_parent;
-
-    /* Window position and size */
-    int          i_window_x;
-    int          i_window_y;
-    int          i_window_width;
-    int          i_window_height;
-    int          i_window_style;
-
-    volatile uint16_t i_changes;        /* changes made to the video display */
-
-    /* Mouse */
-    volatile vlc_bool_t b_cursor_hidden;
-    volatile mtime_t    i_lastmoved;
-
-    /* Misc */
-    vlc_bool_t      b_on_top_change;
-
-    vlc_bool_t      b_wallpaper;
-
-    /* screensaver system settings to be restored when vout is closed */
-    UINT i_spi_lowpowertimeout;
-    UINT i_spi_powerofftimeout;
-    UINT i_spi_screensavetimeout;
-
-    /* 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;
-
-    vlc_bool_t   b_hw_yuv;    /* Should we use hardware YUV->RGB conversions */
-
-#ifdef MODULE_NAME_IS_vout_directx
-    /* Overlay alignment restrictions */
-    int          i_align_src_boundary;
-    int          i_align_src_size;
-    int          i_align_dest_boundary;
-    int          i_align_dest_size;
-
-    vlc_bool_t   b_using_overlay;         /* Are we using an overlay surface */
-    vlc_bool_t   b_use_sysmem;   /* Should we use system memory for surfaces */
-    vlc_bool_t   b_3buf_overlay;   /* Should we use triple buffered overlays */
-
-    /* DDraw capabilities */
-    int          b_caps_overlay_clipping;
-
-    int          i_rgb_colorkey;      /* colorkey in RGB used by the overlay */
-    int          i_colorkey;                 /* colorkey used by the overlay */
-
-    COLORREF        color_bkg;
-    COLORREF        color_bkgtxt;
-
-    LPDIRECTDRAW2        p_ddobject;                    /* DirectDraw object */
-    LPDIRECTDRAWSURFACE2 p_display;                        /* Display device */
-    LPDIRECTDRAWSURFACE2 p_current_surface;   /* surface currently displayed */
-    LPDIRECTDRAWCLIPPER  p_clipper;             /* clipper used for blitting */
-    HINSTANCE            hddraw_dll;       /* handle of the opened ddraw dll */
-#endif
-
-#ifdef MODULE_NAME_IS_glwin32
-    HDC hGLDC;
-    HGLRC hGLRC;
-#endif
-
-#ifdef MODULE_NAME_IS_direct3d
-    // core objects
-    HINSTANCE               hd3d9_dll;       /* handle of the opened d3d9 dll */
-    LPDIRECT3D9             p_d3dobj;
-    LPDIRECT3DDEVICE9       p_d3ddev;
-    D3DFORMAT               bbFormat;
-    // scene objects
-    LPDIRECT3DTEXTURE9      p_d3dtex;
-    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc;
-#endif
-
-    event_thread_t *p_event;
-    vlc_mutex_t    lock;
-};
-
-/*****************************************************************************
- * Prototypes from vout.c
- *****************************************************************************/
-int E_(DirectXUpdateOverlay)( vout_thread_t *p_vout );
-
-/*****************************************************************************
- * Prototypes from events.c
- *****************************************************************************/
-void E_(DirectXEventThread) ( event_thread_t *p_event );
-void E_(DirectXUpdateRects) ( vout_thread_t *p_vout, vlc_bool_t b_force );
-void Win32ToggleFullscreen ( vout_thread_t *p_vout );
-
-/*****************************************************************************
- * Constants
- *****************************************************************************/
-#define WM_VLC_HIDE_MOUSE WM_APP
-#define WM_VLC_SHOW_MOUSE WM_APP + 1
-#define WM_VLC_CHANGE_TEXT WM_APP + 2
-#define IDM_TOGGLE_ON_TOP WM_USER + 1
-#define DX_POSITION_CHANGE 0x1000
-#define DX_WALLPAPER_CHANGE 0x2000
-
-/*****************************************************************************
- * WinCE helpers
- *****************************************************************************/
-#ifdef UNDER_CE
-
-#define AdjustWindowRect(a,b,c)
-
-#ifndef GCL_HBRBACKGROUND
-#   define GCL_HBRBACKGROUND (-10)
-#endif
-
-#define FindWindowEx(a,b,c,d) 0
-
-#define GetWindowPlacement(a,b)
-#define SetWindowPlacement(a,b)
-typedef struct _WINDOWPLACEMENT {
-    UINT length;
-    UINT flags;
-    UINT showCmd;
-    POINT ptMinPosition;
-    POINT ptMaxPosition;
-    RECT rcNormalPosition;
-} WINDOWPLACEMENT;
-
-#ifndef WM_NCMOUSEMOVE
-#   define WM_NCMOUSEMOVE 160
-#endif
-#ifndef CS_OWNDC
-#   define CS_OWNDC 32
-#endif
-#ifndef SC_SCREENSAVE
-#   define SC_SCREENSAVE 0xF140
-#endif
-#ifndef SC_MONITORPOWER
-#   define SC_MONITORPOWER 0xF170
-#endif
-#ifndef WM_NCPAINT
-#   define WM_NCPAINT 133
-#endif
-#ifndef WS_OVERLAPPEDWINDOW
-#   define WS_OVERLAPPEDWINDOW 0xcf0000
-#endif
-#ifndef WS_EX_NOPARENTNOTIFY
-#   define WS_EX_NOPARENTNOTIFY 4
-#endif
-#ifndef WS_EX_APPWINDOW
-#define WS_EX_APPWINDOW 0x40000
-#endif
-
-#define SetWindowLongPtr SetWindowLong
-#define GetWindowLongPtr GetWindowLong
-#define GWLP_USERDATA GWL_USERDATA
-
-#endif //UNDER_CE
diff --git a/modules/video_output/msw/Modules.am b/modules/video_output/msw/Modules.am
new file mode 100644 (file)
index 0000000..ba1636b
--- /dev/null
@@ -0,0 +1,29 @@
+SOURCES_vout_directx = \
+       directx.c \
+       vout.h \
+       events.c \
+       $(NULL)
+
+SOURCES_direct3d = \
+       direct3d.c \
+       vout.h \
+       events.c \
+       $(NULL)
+
+SOURCES_glwin32 = \
+       glwin32.c \
+       vout.h \
+       events.c \
+       $(NULL)
+
+SOURCES_wingdi = \
+       wingdi.c \
+       vout.h \
+       events.c \
+       $(NULL)
+
+SOURCES_wingapi = \
+       windi.c \
+       vout.h \
+       events.c \
+       $(NULL)
diff --git a/modules/video_output/msw/direct3d.c b/modules/video_output/msw/direct3d.c
new file mode 100644 (file)
index 0000000..5077c7a
--- /dev/null
@@ -0,0 +1,1522 @@
+/*****************************************************************************
+ * direct3d.c: Windows Direct3D video output module
+ *****************************************************************************
+ * Copyright (C) 2006 the VideoLAN team
+ *$Id$
+ *
+ * Authors: Damien Fouilleul <damienf@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble:
+ *
+ * This plugin will use YUV surface if supported, using YUV will result in
+ * the best video quality (hardware filering when rescaling the picture)
+ * and the fastest display as it requires less processing.
+ *
+ * If YUV overlay is not supported this plugin will use RGB offscreen video
+ * surfaces that will be blitted onto the primary surface (display) to
+ * effectively display the pictures.
+ *
+ *****************************************************************************/
+#include <errno.h>                                                 /* ENOMEM */
+#include <stdlib.h>                                                /* free() */
+#include <string.h>                                            /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc_interface.h>
+#include <vlc_playlist.h>
+#include <vlc_vout.h>
+
+#include <windows.h>
+#include <d3d9.h>
+
+#include "vout.h"
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int  OpenVideo  ( vlc_object_t * );
+static void CloseVideo ( vlc_object_t * );
+
+static int  Init      ( vout_thread_t * );
+static void End       ( vout_thread_t * );
+static int  Manage    ( vout_thread_t * );
+static void Display   ( vout_thread_t *, picture_t * );
+static void FirstDisplay( vout_thread_t *, picture_t * );
+
+static int Direct3DVoutCreate     ( vout_thread_t * );
+static void Direct3DVoutRelease   ( vout_thread_t * );
+
+static int  Direct3DVoutOpen      ( vout_thread_t * );
+static void Direct3DVoutClose     ( vout_thread_t * );
+
+static int Direct3DVoutResetDevice( vout_thread_t * );
+
+static int Direct3DVoutCreatePictures   ( vout_thread_t *, size_t );
+static void Direct3DVoutReleasePictures ( vout_thread_t * );
+
+static int Direct3DVoutLockSurface  ( vout_thread_t *, picture_t * );
+static int Direct3DVoutUnlockSurface( vout_thread_t *, picture_t * );
+
+static int Direct3DVoutCreateScene      ( vout_thread_t * );
+static void Direct3DVoutReleaseScene    ( vout_thread_t * );
+static void Direct3DVoutRenderScene     ( vout_thread_t *, picture_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+static vlc_bool_t _got_vista_or_above;
+
+static int get_capability_for_osversion(void)
+{
+    OSVERSIONINFO winVer;
+    winVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+    if( GetVersionEx(&winVer) )
+    {
+        if( winVer.dwMajorVersion > 5 )
+        {
+            /* Windows Vista or above, make this module the default */
+           _got_vista_or_above = VLC_TRUE;
+            return 150;
+        }
+    }
+    /* Windows XP or lower, make sure this module isn't the default */
+    _got_vista_or_above = VLC_FALSE;
+    return 50;
+}
+
+vlc_module_begin();
+    set_shortname( "Direct3D" );
+    set_category( CAT_VIDEO );
+    set_subcategory( SUBCAT_VIDEO_VOUT );
+    set_description( _("DirectX 3D video output") );
+    set_capability( "video output", get_capability_for_osversion() );
+    add_shortcut( "direct3d" );
+    set_callbacks( OpenVideo, CloseVideo );
+
+    /* FIXME: Hack to avoid unregistering our window class */
+    linked_with_a_crap_library_which_uses_atexit( );
+vlc_module_end();
+
+#if 0 /* FIXME */
+    /* check if we registered a window class because we need to
+     * unregister it */
+    WNDCLASS wndclass;
+    if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )
+        UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );
+#endif
+
+/*****************************************************************************
+ * CUSTOMVERTEX: 
+ *****************************************************************************
+ *****************************************************************************/
+typedef struct 
+{
+    FLOAT       x,y,z;      // vertex untransformed position 
+    FLOAT       rhw;        // eye distance
+    D3DCOLOR    diffuse;    // diffuse color
+    FLOAT       tu, tv;     // texture relative coordinates
+} CUSTOMVERTEX;
+
+#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
+
+/*****************************************************************************
+ * OpenVideo: allocate Vout video thread output method
+ *****************************************************************************
+ * This function allocates and initialize the Direct3D vout method.
+ *****************************************************************************/
+static int OpenVideo( vlc_object_t *p_this )
+{
+    vout_thread_t * p_vout = (vout_thread_t *)p_this;
+    vlc_value_t val;
+
+    /* Allocate structure */
+    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+    if( p_vout->p_sys == NULL )
+    {
+        msg_Err( p_vout, "out of memory" );
+        return VLC_ENOMEM;
+    }
+    memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
+
+    if( VLC_SUCCESS != Direct3DVoutCreate( p_vout ) )
+    {
+        msg_Err( p_vout, "Direct3D could not be initialized !");
+        goto error;
+    }
+
+    /* Initialisations */
+    p_vout->pf_init = Init;
+    p_vout->pf_end = End;
+    p_vout->pf_manage = Manage;
+    p_vout->pf_render = Direct3DVoutRenderScene;
+    p_vout->pf_display = FirstDisplay;
+
+    p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
+    p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
+    p_vout->p_sys->i_changes = 0;
+    vlc_mutex_init( p_vout, &p_vout->p_sys->lock );
+    SetRectEmpty( &p_vout->p_sys->rect_display );
+    SetRectEmpty( &p_vout->p_sys->rect_parent );
+
+    var_Create( p_vout, "directx-hw-yuv", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+    var_Create( p_vout, "directx-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
+
+    p_vout->p_sys->b_cursor_hidden = 0;
+    p_vout->p_sys->i_lastmoved = mdate();
+
+    var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
+    var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+
+    /* Set main window's size */
+    p_vout->p_sys->i_window_width = p_vout->i_window_width;
+    p_vout->p_sys->i_window_height = p_vout->i_window_height;
+
+    /* Create the Vout EventThread, this thread is created by us to isolate
+     * the Win32 PeekMessage function calls. We want to do this because
+     * Windows can stay blocked inside this call for a long time, and when
+     * this happens it thus blocks vlc's video_output thread.
+     * Vout EventThread will take care of the creation of the video
+     * window (because PeekMessage has to be called from the same thread which
+     * created the window). */
+    msg_Dbg( p_vout, "creating Vout EventThread" );
+    p_vout->p_sys->p_event =
+        vlc_object_create( p_vout, sizeof(event_thread_t) );
+    p_vout->p_sys->p_event->p_vout = p_vout;
+    if( vlc_thread_create( p_vout->p_sys->p_event, "Vout Events Thread",
+                           E_(EventThread), 0, 1 ) )
+    {
+        msg_Err( p_vout, "cannot create Vout EventThread" );
+        vlc_object_destroy( p_vout->p_sys->p_event );
+        p_vout->p_sys->p_event = NULL;
+        goto error;
+    }
+
+    if( p_vout->p_sys->p_event->b_error )
+    {
+        msg_Err( p_vout, "Vout EventThread failed" );
+        goto error;
+    }
+
+    vlc_object_attach( p_vout->p_sys->p_event, p_vout );
+
+    msg_Dbg( p_vout, "Vout EventThread running" );
+
+    /* Variable to indicate if the window should be on top of others */
+    /* Trigger a callback right now */
+    var_Get( p_vout, "video-on-top", &val );
+    var_Set( p_vout, "video-on-top", val );
+
+    /* disable screensaver by temporarily changing system settings */
+    p_vout->p_sys->i_spi_lowpowertimeout = 0;
+    p_vout->p_sys->i_spi_powerofftimeout = 0;
+    p_vout->p_sys->i_spi_screensavetimeout = 0;
+    var_Get( p_vout, "disable-screensaver", &val);
+    if( val.b_bool ) {
+        msg_Dbg(p_vout, "disabling screen saver");
+        SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT,
+            0, &(p_vout->p_sys->i_spi_lowpowertimeout), 0);
+        if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {
+            SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0);
+        }
+        SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0,
+            &(p_vout->p_sys->i_spi_powerofftimeout), 0);
+        if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
+            SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, 0, NULL, 0);
+        }
+        SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0,
+            &(p_vout->p_sys->i_spi_screensavetimeout), 0);
+        if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {
+            SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 0, NULL, 0);
+        }
+    }
+    return VLC_SUCCESS;
+
+ error:
+    CloseVideo( VLC_OBJECT(p_vout) );
+    return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * CloseVideo: destroy Sys video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create
+ *****************************************************************************/
+static void CloseVideo( vlc_object_t *p_this )
+{
+    vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+    Direct3DVoutRelease( p_vout );
+
+    if( p_vout->p_sys->p_event )
+    {
+        vlc_object_detach( p_vout->p_sys->p_event );
+
+        /* Kill Vout EventThread */
+        p_vout->p_sys->p_event->b_die = VLC_TRUE;
+
+        /* we need to be sure Vout EventThread won't stay stuck in
+         * GetMessage, so we send a fake message */
+        if( p_vout->p_sys->hwnd )
+        {
+            PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);
+        }
+
+        vlc_thread_join( p_vout->p_sys->p_event );
+        vlc_object_destroy( p_vout->p_sys->p_event );
+    }
+
+    vlc_mutex_destroy( &p_vout->p_sys->lock );
+
+    /* restore screensaver system settings */
+    if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {
+        SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT,
+            p_vout->p_sys->i_spi_lowpowertimeout, NULL, 0);
+    }
+    if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
+        SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT,
+            p_vout->p_sys->i_spi_powerofftimeout, NULL, 0);
+    }
+    if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {
+        SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT,
+            p_vout->p_sys->i_spi_screensavetimeout, NULL, 0);
+    }
+
+    if( p_vout->p_sys )
+    {
+        free( p_vout->p_sys );
+        p_vout->p_sys = NULL;
+    }
+}
+
+/*****************************************************************************
+ * Init: initialize Direct3D video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+    int i_ret;
+    vlc_value_t val;
+
+    var_Get( p_vout, "directx-hw-yuv", &val );
+    p_vout->p_sys->b_hw_yuv = val.b_bool;
+
+    /* Initialise Direct3D */
+    if( VLC_SUCCESS != Direct3DVoutOpen( p_vout ) )
+    {
+        msg_Err( p_vout, "cannot initialize Direct3D" );
+        return VLC_EGENERIC;
+    }
+
+    /* Initialize the output structure.
+     * Since Direct3D 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;
+    p_vout->fmt_out = p_vout->fmt_in;
+    E_(UpdateRects)( p_vout, VLC_TRUE );
+
+    /*  create picture pool */
+    i_ret = Direct3DVoutCreatePictures(p_vout, 1);
+    if( VLC_SUCCESS != i_ret )
+    {
+        msg_Err(p_vout, "Direct3D picture pool initialization failed !");
+        return i_ret;
+    }
+
+    /* create scene */
+    i_ret = Direct3DVoutCreateScene(p_vout);
+    if( VLC_SUCCESS != i_ret )
+    {
+        msg_Err(p_vout, "Direct3D scene initialization failed !");
+        Direct3DVoutReleasePictures(p_vout);
+        return i_ret;
+    }
+
+    /* Change the window title bar text */
+    PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
+
+    p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * End: terminate Sys video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create.
+ * It is called at the end of the thread.
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+    Direct3DVoutReleaseScene(p_vout);
+    Direct3DVoutReleasePictures(p_vout);
+    Direct3DVoutClose( p_vout );
+}
+
+/*****************************************************************************
+ * Manage: handle Sys events
+ *****************************************************************************
+ * This function should be called regularly by the video output thread.
+ * It returns a non null value if an error occurred.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+    /* If we do not control our window, we check for geometry changes
+     * ourselves because the parent might not send us its events. */
+    vlc_mutex_lock( &p_vout->p_sys->lock );
+    if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
+    {
+        RECT rect_parent;
+        POINT point;
+
+        vlc_mutex_unlock( &p_vout->p_sys->lock );
+
+        GetClientRect( p_vout->p_sys->hparent, &rect_parent );
+        point.x = point.y = 0;
+        ClientToScreen( p_vout->p_sys->hparent, &point );
+        OffsetRect( &rect_parent, point.x, point.y );
+
+        if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
+        {
+            p_vout->p_sys->rect_parent = rect_parent;
+
+            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
+                          rect_parent.right - rect_parent.left,
+                          rect_parent.bottom - rect_parent.top,
+                          SWP_NOZORDER );
+        }
+    }
+    else
+    {
+        vlc_mutex_unlock( &p_vout->p_sys->lock );
+    }
+
+    /*
+     * Position Change
+     */
+    if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE )
+    {
+#if 0 /* need that when bicubic filter is available */
+        RECT rect;
+        UINT width, height;
+
+        GetClientRect(p_vout->p_sys->hvideownd, &rect);
+        width  = rect.right-rect.left;
+        height = rect.bottom-rect.top;
+
+        if( (width != p_vout->p_sys->d3dpp.BackBufferWidth)
+         || (height != p_vout->p_sys->d3dpp.BackBufferHeight) )
+        {
+            msg_Dbg(p_vout, "resizing device back buffers to (%lux%lu)", width, height);
+            // need to reset D3D device to resize back buffer
+            if( VLC_SUCCESS != Direct3DVoutResetDevice(p_vout, width, height) )
+                return VLC_EGENERIC;
+        }
+#endif
+        p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
+    }
+
+    /* Check for cropping / aspect changes */
+    if( p_vout->i_changes & VOUT_CROP_CHANGE ||
+        p_vout->i_changes & VOUT_ASPECT_CHANGE )
+    {
+        p_vout->i_changes &= ~VOUT_CROP_CHANGE;
+        p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
+
+        p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset;
+        p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset;
+        p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width;
+        p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height;
+        p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect;
+        p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;
+        p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;
+        p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
+        E_(UpdateRects)( p_vout, VLC_TRUE );
+    }
+
+    /* We used to call the Win32 PeekMessage function here to read the window
+     * messages. But since window can stay blocked into this function for a
+     * long time (for example when you move your window on the screen), I
+     * decided to isolate PeekMessage in another thread. */
+
+    /*
+     * Fullscreen change
+     */
+    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
+        || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
+    {
+        Win32ToggleFullscreen( p_vout );
+
+        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+        p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+    }
+
+    /*
+     * Pointer change
+     */
+    if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&
+        (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 )
+    {
+        POINT point;
+        HWND hwnd;
+
+        /* Hide the cursor only if it is inside our window */
+        GetCursorPos( &point );
+        hwnd = WindowFromPoint(point);
+        if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )
+        {
+            PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
+        }
+        else
+        {
+            p_vout->p_sys->i_lastmoved = mdate();
+        }
+    }
+
+    /*
+     * "Always on top" status change
+     */
+    if( p_vout->p_sys->b_on_top_change )
+    {
+        vlc_value_t val;
+        HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
+
+        var_Get( p_vout, "video-on-top", &val );
+
+        /* Set the window on top if necessary */
+        if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
+                           & WS_EX_TOPMOST ) )
+        {
+            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
+                           MF_BYCOMMAND | MFS_CHECKED );
+            SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,
+                          SWP_NOSIZE | SWP_NOMOVE );
+        }
+        else
+        /* The window shouldn't be on top */
+        if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
+                           & WS_EX_TOPMOST ) )
+        {
+            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
+                           MF_BYCOMMAND | MFS_UNCHECKED );
+            SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
+                          SWP_NOSIZE | SWP_NOMOVE );
+        }
+
+        p_vout->p_sys->b_on_top_change = VLC_FALSE;
+    }
+
+    /* Check if the event thread is still running */
+    if( p_vout->p_sys->p_event->b_die )
+    {
+        return VLC_EGENERIC; /* exit */
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Display: displays previously rendered output
+ *****************************************************************************
+ * 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 Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    LPDIRECT3DDEVICE9       p_d3ddev = p_vout->p_sys->p_d3ddev;
+    // Present the back buffer contents to the display
+    // stretching and filtering happens here
+    HRESULT hr = IDirect3DDevice9_Present(p_d3ddev,
+                    &(p_vout->p_sys->rect_src_clipped),
+                    NULL, NULL, NULL);
+    if( FAILED(hr) )
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+}
+
+/*
+** this function is only used once when the first picture is received
+** this function will show the video window once a picture is ready
+*/
+
+static void FirstDisplay( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    /* get initial picture presented through D3D */
+    Display(p_vout, p_pic);
+
+    /*
+    ** Video window is initially hidden, show it now since we got a 
+    ** picture to show.
+    */
+    SetWindowPos( p_vout->p_sys->hvideownd, 0, 0, 0, 0, 0, 
+        SWP_ASYNCWINDOWPOS|
+        SWP_FRAMECHANGED|
+        SWP_SHOWWINDOW|
+        SWP_NOMOVE|
+        SWP_NOSIZE|
+        SWP_NOZORDER );
+
+    /* use and restores proper display function for further pictures */
+    p_vout->pf_display = Display;
+}
+
+/*****************************************************************************
+ * DirectD3DVoutCreate: Initialize and instance of Direct3D9 
+ *****************************************************************************
+ * This function initialize Direct3D and analyze available resources from
+ * default adapter.
+ *****************************************************************************/
+static int Direct3DVoutCreate( vout_thread_t *p_vout )
+{
+    HRESULT hr;
+    LPDIRECT3D9 p_d3dobj;
+    D3DCAPS9 d3dCaps;
+
+    LPDIRECT3D9 (WINAPI *OurDirect3DCreate9)(UINT SDKVersion);
+
+    p_vout->p_sys->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
+    if( NULL == p_vout->p_sys->hd3d9_dll )
+    {
+        msg_Warn( p_vout, "cannot load d3d9.dll, aborting" );
+        return VLC_EGENERIC;
+    }
+
+    OurDirect3DCreate9 =
+      (void *)GetProcAddress( p_vout->p_sys->hd3d9_dll,
+                              TEXT("Direct3DCreate9") );
+    if( OurDirect3DCreate9 == NULL )
+    {
+        msg_Err( p_vout, "Cannot locate reference to Direct3DCreate9 ABI in DLL" );
+        return VLC_EGENERIC;
+    }
+
+    /* Create the D3D object. */
+    p_d3dobj = OurDirect3DCreate9( D3D_SDK_VERSION );
+    if( NULL == p_d3dobj )
+    {
+       msg_Err( p_vout, "Could not create Direct3D9 instance.");
+       return VLC_EGENERIC;
+    }
+    p_vout->p_sys->p_d3dobj = p_d3dobj;
+
+    /*
+    ** Get device capabilities
+    */
+    ZeroMemory(&d3dCaps, sizeof(d3dCaps));
+    hr = IDirect3D9_GetDeviceCaps(p_d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps);
+    if( FAILED(hr) )
+    {
+       msg_Err( p_vout, "Could not read adapter capabilities. (hr=0x%lX)", hr);
+       return VLC_EGENERIC;
+    }
+    /* TODO: need to test device capabilities and select the right render function */
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * DirectD3DVoutRelease: release an instance of Direct3D9
+ *****************************************************************************/
+
+static void Direct3DVoutRelease( vout_thread_t *p_vout )
+{
+    if( p_vout->p_sys->p_d3dobj )
+    {
+       IDirect3D9_Release(p_vout->p_sys->p_d3dobj);
+       p_vout->p_sys->p_d3dobj = NULL;
+    }
+    if( NULL != p_vout->p_sys->hd3d9_dll )
+    {
+        FreeLibrary(p_vout->p_sys->hd3d9_dll);
+        p_vout->p_sys->hd3d9_dll = NULL;
+    }
+}
+
+static int Direct3DFillPresentationParameters(vout_thread_t *p_vout, D3DPRESENT_PARAMETERS *d3dpp)
+{
+    LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj;
+    D3DDISPLAYMODE d3ddm;
+    HRESULT hr;
+
+    /*
+    ** Get the current desktop display mode, so we can set up a back
+    ** buffer of the same format
+    */
+    hr = IDirect3D9_GetAdapterDisplayMode(p_d3dobj, D3DADAPTER_DEFAULT, &d3ddm );
+    if( FAILED(hr))
+    {
+       msg_Err( p_vout, "Could not read adapter display mode. (hr=0x%lX)", hr);
+       return VLC_EGENERIC;
+    }
+
+    /* keep a copy of current desktop format */
+    p_vout->p_sys->bbFormat = d3ddm.Format;
+
+    /* Set up the structure used to create the D3DDevice. */
+    ZeroMemory( d3dpp, sizeof(D3DPRESENT_PARAMETERS) );
+    d3dpp->Flags                  = D3DPRESENTFLAG_VIDEO;
+    d3dpp->Windowed               = TRUE;
+    d3dpp->hDeviceWindow          = p_vout->p_sys->hvideownd;
+    d3dpp->BackBufferWidth        = p_vout->output.i_width;
+    d3dpp->BackBufferHeight       = p_vout->output.i_height;
+    d3dpp->SwapEffect             = D3DSWAPEFFECT_COPY;
+    d3dpp->MultiSampleType        = D3DMULTISAMPLE_NONE;
+    d3dpp->PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT;
+    d3dpp->BackBufferFormat       = d3ddm.Format;
+    d3dpp->BackBufferCount        = 1;
+    d3dpp->EnableAutoDepthStencil = FALSE;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * DirectD3DVoutOpen: Takes care of all the Direct3D9 initialisations
+ *****************************************************************************
+ * This function creates Direct3D device
+ * this must be called from the vout thread for performance reason, as
+ * all Direct3D Device APIs are used in a non multithread safe environment
+ *****************************************************************************/
+static int Direct3DVoutOpen( vout_thread_t *p_vout )
+{
+    LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj;
+    LPDIRECT3DDEVICE9 p_d3ddev;
+    D3DPRESENT_PARAMETERS d3dpp;
+    HRESULT hr;
+
+    if( VLC_SUCCESS != Direct3DFillPresentationParameters(p_vout, &d3dpp) )
+        return VLC_EGENERIC;
+
+    // Create the D3DDevice
+    hr = IDirect3D9_CreateDevice(p_d3dobj, D3DADAPTER_DEFAULT,
+                                 D3DDEVTYPE_HAL, p_vout->p_sys->hvideownd,
+                                 D3DCREATE_SOFTWARE_VERTEXPROCESSING|
+                                 D3DCREATE_MULTITHREADED,
+                                 &d3dpp, &p_d3ddev );
+    if( FAILED(hr) )                                      
+    {
+       msg_Err(p_vout, "Could not create the D3D device! (hr=0x%lX)", hr);
+       return VLC_EGENERIC;
+    }
+    p_vout->p_sys->p_d3ddev = p_d3ddev;
+
+    msg_Dbg( p_vout, "Direct3D device adapter successfully initialized" );
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * DirectD3DClose: release the Direct3D9 device 
+ *****************************************************************************/
+static void Direct3DVoutClose( vout_thread_t *p_vout )
+{
+    if( p_vout->p_sys->p_d3ddev )
+    {
+       IDirect3DDevice9_Release(p_vout->p_sys->p_d3ddev);
+       p_vout->p_sys->p_d3ddev = NULL;
+    }
+       
+    p_vout->p_sys->hmonitor = NULL;
+}
+
+/*****************************************************************************
+ * DirectD3DClose: reset the Direct3D9 device 
+ *****************************************************************************
+ * All resources must be deallocated before the reset occur, they will be
+ * realllocated once the reset has been performed successfully
+ *****************************************************************************/
+static int Direct3DVoutResetDevice( vout_thread_t *p_vout )
+{
+    LPDIRECT3DDEVICE9       p_d3ddev = p_vout->p_sys->p_d3ddev;
+    D3DPRESENT_PARAMETERS   d3dpp;
+    HRESULT hr;
+
+    if( VLC_SUCCESS != Direct3DFillPresentationParameters(p_vout, &d3dpp) )
+        return VLC_EGENERIC;
+
+    // release all D3D objects
+    Direct3DVoutReleaseScene( p_vout );
+    Direct3DVoutReleasePictures( p_vout );
+
+    hr = IDirect3DDevice9_Reset(p_d3ddev, &d3dpp);
+    if( SUCCEEDED(hr) )
+    {
+        // re-create them
+        if( (VLC_SUCCESS != Direct3DVoutCreatePictures(p_vout, 1))
+         || (VLC_SUCCESS != Direct3DVoutCreateScene(p_vout)) )
+        {
+            msg_Dbg(p_vout, "%s failed !", __FUNCTION__);
+            return VLC_EGENERIC;
+        }
+    }
+    else {
+        msg_Err(p_vout, "%s failed ! (hr=%08lX)", __FUNCTION__, hr);
+        return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
+static D3DFORMAT Direct3DVoutSelectFormat( vout_thread_t *p_vout, D3DFORMAT target,
+    const D3DFORMAT *formats, size_t count)
+{
+    LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj;
+    size_t c;
+
+    for( c=0; c<count; ++c )
+    {
+        HRESULT hr;
+        D3DFORMAT format = formats[c];
+        /* test whether device can create a surface of that format */
+        hr = IDirect3D9_CheckDeviceFormat(p_d3dobj, D3DADAPTER_DEFAULT,
+                D3DDEVTYPE_HAL, target, 0, D3DRTYPE_SURFACE, format);
+        if( SUCCEEDED(hr) )
+        {
+            /* test whether device can perform color-conversion
+            ** from that format to target format
+            */
+            hr = IDirect3D9_CheckDeviceFormatConversion(p_d3dobj,
+                    D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
+                    format, target);
+        }
+        if( SUCCEEDED(hr) )
+        {
+            // found a compatible format
+            switch( format )
+            {
+                case D3DFMT_UYVY:
+                    msg_Dbg( p_vout, "selected surface pixel format is UYVY");
+                    break;
+                case D3DFMT_YUY2:
+                    msg_Dbg( p_vout, "selected surface pixel format is YUY2");
+                    break;
+                case D3DFMT_X8R8G8B8:
+                    msg_Dbg( p_vout, "selected surface pixel format is X8R8G8B8");
+                    break;
+                case D3DFMT_A8R8G8B8:
+                    msg_Dbg( p_vout, "selected surface pixel format is A8R8G8B8");
+                    break;
+                case D3DFMT_R8G8B8:
+                    msg_Dbg( p_vout, "selected surface pixel format is R8G8B8");
+                    break;
+                case D3DFMT_R5G6B5:
+                    msg_Dbg( p_vout, "selected surface pixel format is R5G6B5");
+                    break;
+                case D3DFMT_X1R5G5B5:
+                    msg_Dbg( p_vout, "selected surface pixel format is X1R5G5B5");
+                    break;
+                default:
+                    msg_Dbg( p_vout, "selected surface pixel format is 0x%0X", format);
+                    break;
+            }
+            return format;
+        }
+        else if( D3DERR_NOTAVAILABLE != hr )
+        {
+            msg_Err( p_vout, "Could not query adapter supported formats. (hr=0x%lX)", hr);
+            break;
+        }
+    }
+    return D3DFMT_UNKNOWN;
+}
+
+static D3DFORMAT Direct3DVoutFindFormat(vout_thread_t *p_vout, int i_chroma, D3DFORMAT target)
+{
+    if( p_vout->p_sys->b_hw_yuv && ! _got_vista_or_above )
+    {
+       /* it sounds like vista does not support YUV surfaces at all */
+        switch( i_chroma )
+        {
+            case VLC_FOURCC('U','Y','V','Y'):
+            case VLC_FOURCC('U','Y','N','V'):
+            case VLC_FOURCC('Y','4','2','2'):
+            {
+                static const D3DFORMAT formats[] =
+                    { D3DFMT_UYVY, D3DFMT_YUY2, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };
+                return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
+            }
+            case VLC_FOURCC('I','4','2','0'):
+            case VLC_FOURCC('I','4','2','2'):
+            case VLC_FOURCC('Y','V','1','2'):
+            {
+                /* typically 3D textures don't support planar format
+                ** fallback to packed version and use CPU for the conversion
+                */
+                static const D3DFORMAT formats[] = 
+                    { D3DFMT_YUY2, D3DFMT_UYVY, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };
+                return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
+            }
+            case VLC_FOURCC('Y','U','Y','2'):
+            case VLC_FOURCC('Y','U','N','V'):
+            {
+                static const D3DFORMAT formats[] = 
+                    { D3DFMT_YUY2, D3DFMT_UYVY, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };
+                return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
+            }
+        }
+    }
+
+    switch( i_chroma )
+    {
+        case VLC_FOURCC('R', 'V', '1', '5'):
+        {
+            static const D3DFORMAT formats[] = 
+                { D3DFMT_X1R5G5B5 };
+            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
+        }
+        case VLC_FOURCC('R', 'V', '1', '6'):
+        {
+            static const D3DFORMAT formats[] = 
+                { D3DFMT_R5G6B5 };
+            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
+        }
+        case VLC_FOURCC('R', 'V', '2', '4'):
+        {
+            static const D3DFORMAT formats[] = 
+                { D3DFMT_R8G8B8, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8 };
+            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
+        }
+        case VLC_FOURCC('R', 'V', '3', '2'):
+        {
+            static const D3DFORMAT formats[] = 
+                { D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 };
+            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
+        }
+        default:
+        {
+            /* use display default format */
+            LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj;
+            D3DDISPLAYMODE d3ddm;
+
+            HRESULT hr = IDirect3D9_GetAdapterDisplayMode(p_d3dobj, D3DADAPTER_DEFAULT, &d3ddm );
+            if( SUCCEEDED(hr))
+            {
+                /*
+                ** some professional cards could use some advanced pixel format as default, 
+                ** make sure we stick with chromas that we can handle internally
+                */
+                switch( d3ddm.Format )
+                {
+                    case D3DFMT_R8G8B8:
+                    case D3DFMT_X8R8G8B8:
+                    case D3DFMT_A8R8G8B8:
+                        msg_Dbg( p_vout, "defaulting to adpater pixel format");
+                        return Direct3DVoutSelectFormat(p_vout, target, &d3ddm.Format, 1);
+                    default:
+                    {
+                        /* if we fall here, that probably means that we need to render some YUV format */
+                        static const D3DFORMAT formats[] = 
+                            { D3DFMT_R8G8B8, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8 };
+                        msg_Dbg( p_vout, "defaulting to built-in pixel format");
+                        return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
+                    }
+                }
+            }
+        }
+    }
+    return D3DFMT_UNKNOWN;
+}
+
+static int Direct3DVoutSetOutputFormat(vout_thread_t *p_vout, D3DFORMAT format)
+{
+    switch( format )
+    {
+        case D3DFMT_YUY2:
+            p_vout->output.i_chroma = VLC_FOURCC('Y', 'U', 'Y', '2');
+            break;
+        case D3DFMT_UYVY:
+            p_vout->output.i_chroma = VLC_FOURCC('U', 'Y', 'V', 'Y');
+            break;
+        case D3DFMT_R8G8B8:
+            p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '2', '4');
+            break;
+        case D3DFMT_X8R8G8B8:
+        case D3DFMT_A8R8G8B8:
+            p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '3', '2');
+            p_vout->output.i_rmask = 0x00ff0000;
+            p_vout->output.i_gmask = 0x0000ff00;
+            p_vout->output.i_bmask = 0x000000ff;
+#       if defined( WORDS_BIGENDIAN )
+            p_vout->output.i_rrshift = 0;
+            p_vout->output.i_lrshift = 24;
+            p_vout->output.i_rgshift = 0;
+            p_vout->output.i_lgshift = 16;
+            p_vout->output.i_rbshift = 0;
+            p_vout->output.i_lbshift = 8;
+#       else
+            p_vout->output.i_rrshift = 0;
+            p_vout->output.i_lrshift = 8;
+            p_vout->output.i_rgshift = 0;
+            p_vout->output.i_lgshift = 16;
+            p_vout->output.i_rbshift = 0;
+            p_vout->output.i_lbshift = 24;
+#       endif
+            break;
+        case D3DFMT_R5G6B5:
+            p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '1', '6');
+            p_vout->output.i_rmask = (0x1fL)<<11;
+            p_vout->output.i_gmask = (0x3fL)<<5;
+            p_vout->output.i_bmask = (0x1fL)<<0;
+#       if defined( WORDS_BIGENDIAN )
+            p_vout->output.i_rrshift = 0;
+            p_vout->output.i_lrshift = 11;
+            p_vout->output.i_rgshift = 0;
+            p_vout->output.i_lgshift = 5;
+            p_vout->output.i_rbshift = 0;
+            p_vout->output.i_lbshift = 0;
+#       else
+            /* FIXME: since components are not byte aligned,
+                      there is no chance that this will work */
+            p_vout->output.i_rrshift = 0;
+            p_vout->output.i_lrshift = 0;
+            p_vout->output.i_rgshift = 0;
+            p_vout->output.i_lgshift = 5;
+            p_vout->output.i_rbshift = 0;
+            p_vout->output.i_lbshift = 11;
+#       endif
+            break;
+        case D3DFMT_X1R5G5B5:
+            p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '1', '5');
+            p_vout->output.i_rmask = (0x1fL)<<10;
+            p_vout->output.i_gmask = (0x1fL)<<5;
+            p_vout->output.i_bmask = (0x1fL)<<0;
+#       if defined( WORDS_BIGENDIAN )
+            p_vout->output.i_rrshift = 0;
+            p_vout->output.i_lrshift = 10;
+            p_vout->output.i_rgshift = 0;
+            p_vout->output.i_lgshift = 5;
+            p_vout->output.i_rbshift = 0;
+            p_vout->output.i_lbshift = 0;
+#       else
+            /* FIXME: since components are not byte aligned,
+                      there is no chance that this will work */
+            p_vout->output.i_rrshift = 0;
+            p_vout->output.i_lrshift = 1;
+            p_vout->output.i_rgshift = 0;
+            p_vout->output.i_lgshift = 5;
+            p_vout->output.i_rbshift = 0;
+            p_vout->output.i_lbshift = 11;
+#       endif
+            break;
+        default:
+            return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Direct3DVoutCreatePictures: allocate a vector of identical pictures
+ *****************************************************************************
+ * Each picture has an associated offscreen surface in video memory
+ * depending on hardware capabilities the picture chroma will be as close
+ * as possible to the orginal render chroma to reduce CPU conversion overhead
+ * and delegate this work to video card GPU
+ *****************************************************************************/
+static int Direct3DVoutCreatePictures( vout_thread_t *p_vout, size_t i_num_pics )
+{
+    LPDIRECT3DDEVICE9       p_d3ddev  = p_vout->p_sys->p_d3ddev;
+    D3DFORMAT               format;
+    HRESULT hr;
+    size_t c;
+
+    I_OUTPUTPICTURES = 0;
+
+    /*
+    ** find the appropriate D3DFORMAT for the render chroma, the format will be the closest to
+    ** the requested chroma which is usable by the hardware in an offscreen surface, as they
+    ** typically support more formats than textures
+    */ 
+    format = Direct3DVoutFindFormat(p_vout, p_vout->render.i_chroma, p_vout->p_sys->bbFormat);
+    if( VLC_SUCCESS != Direct3DVoutSetOutputFormat(p_vout, format) )
+    {
+        msg_Err(p_vout, "surface pixel format is not supported.");
+        return VLC_EGENERIC;
+    }
+
+    for( c=0; c<i_num_pics; )
+    {
+
+        LPDIRECT3DSURFACE9 p_d3dsurf;
+        picture_t *p_pic = p_vout->p_picture+c; 
+
+        hr = IDirect3DDevice9_CreateOffscreenPlainSurface(p_d3ddev, 
+                p_vout->render.i_width,
+                p_vout->render.i_height,
+                format,
+                D3DPOOL_DEFAULT,
+                &p_d3dsurf,
+                NULL);
+        if( FAILED(hr) )
+        {
+            msg_Err(p_vout, "Failed to create picture surface. (hr=0x%lx)", hr);
+            Direct3DVoutReleasePictures(p_vout);
+            return VLC_EGENERIC;
+        }
+
+        /* fill surface with black color */
+        IDirect3DDevice9_ColorFill(p_d3ddev, p_d3dsurf, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0) );
+        
+        /* assign surface to internal structure */
+        p_pic->p_sys = (void *)p_d3dsurf;
+
+        /* Now that we've got our direct-buffer, we can finish filling in the
+         * picture_t structures */
+        switch( p_vout->output.i_chroma )
+        {
+            case VLC_FOURCC('R','G','B','2'):
+                p_pic->p->i_lines = p_vout->output.i_height;
+                p_pic->p->i_visible_lines = p_vout->output.i_height;
+                p_pic->p->i_pixel_pitch = 1;
+                p_pic->p->i_visible_pitch = p_vout->output.i_width *
+                    p_pic->p->i_pixel_pitch;
+                p_pic->i_planes = 1;
+            break;
+            case VLC_FOURCC('R','V','1','5'):
+            case VLC_FOURCC('R','V','1','6'):
+                p_pic->p->i_lines = p_vout->output.i_height;
+                p_pic->p->i_visible_lines = p_vout->output.i_height;
+                p_pic->p->i_pixel_pitch = 2;
+                p_pic->p->i_visible_pitch = p_vout->output.i_width *
+                    p_pic->p->i_pixel_pitch;
+                p_pic->i_planes = 1;
+            break;
+            case VLC_FOURCC('R','V','2','4'):
+                p_pic->p->i_lines = p_vout->output.i_height;
+                p_pic->p->i_visible_lines = p_vout->output.i_height;
+                p_pic->p->i_pixel_pitch = 3;
+                p_pic->p->i_visible_pitch = p_vout->output.i_width *
+                    p_pic->p->i_pixel_pitch;
+                p_pic->i_planes = 1;
+            break;
+            case VLC_FOURCC('R','V','3','2'):
+                p_pic->p->i_lines = p_vout->output.i_height;
+                p_pic->p->i_visible_lines = p_vout->output.i_height;
+                p_pic->p->i_pixel_pitch = 4;
+                p_pic->p->i_visible_pitch = p_vout->output.i_width *
+                    p_pic->p->i_pixel_pitch;
+                p_pic->i_planes = 1;
+                break;
+            case VLC_FOURCC('U','Y','V','Y'):
+            case VLC_FOURCC('Y','U','Y','2'):
+                p_pic->p->i_lines = p_vout->output.i_height;
+                p_pic->p->i_visible_lines = p_vout->output.i_height;
+                p_pic->p->i_pixel_pitch = 2;
+                p_pic->p->i_visible_pitch = p_vout->output.i_width *
+                    p_pic->p->i_pixel_pitch;
+                p_pic->i_planes = 1;
+                break;
+            default:
+                Direct3DVoutReleasePictures(p_vout);
+                return VLC_EGENERIC;
+        }
+        p_pic->i_status = DESTROYED_PICTURE;
+        p_pic->i_type   = DIRECT_PICTURE;
+        p_pic->b_slow   = VLC_TRUE;
+        p_pic->pf_lock  = Direct3DVoutLockSurface;
+        p_pic->pf_unlock = Direct3DVoutUnlockSurface;
+        PP_OUTPUTPICTURE[c] = p_pic;
+
+        I_OUTPUTPICTURES = ++c;
+    }
+
+    msg_Dbg( p_vout, "%u Direct3D pictures created successfully", c );
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Direct3DVoutReleasePictures: destroy a picture vector 
+ *****************************************************************************
+ * release all video resources used for pictures
+ *****************************************************************************/
+static void Direct3DVoutReleasePictures( vout_thread_t *p_vout)
+{
+    size_t i_num_pics = I_OUTPUTPICTURES;
+    size_t c;
+    for( c=0; c<i_num_pics; ++c )
+    {
+        picture_t *p_pic = p_vout->p_picture+c; 
+        if( p_pic->p_sys )
+        {
+            LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;
+
+            p_pic->p_sys = NULL;
+
+            if( p_d3dsurf )
+            {
+                IDirect3DSurface9_Release(p_d3dsurf);
+            }
+        }
+    }
+    msg_Dbg( p_vout, "%u Direct3D pictures released.", c);
+
+    I_OUTPUTPICTURES = 0;
+}
+
+/*****************************************************************************
+ * Direct3DVoutLockSurface: Lock surface and get picture data pointer
+ *****************************************************************************
+ * This function locks a surface and get the surface descriptor which amongst
+ * other things has the pointer to the picture data.
+ *****************************************************************************/
+static int Direct3DVoutLockSurface( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    HRESULT hr;
+    D3DLOCKED_RECT d3drect;
+    LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;
+
+    if( NULL == p_d3dsurf )
+        return VLC_EGENERIC;
+
+    /* Lock the surface to get a valid pointer to the picture buffer */
+    hr = IDirect3DSurface9_LockRect(p_d3dsurf, &d3drect, NULL, 0);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        return VLC_EGENERIC;
+    }
+
+    /* fill in buffer info in first plane */
+    p_pic->p->p_pixels = d3drect.pBits;
+    p_pic->p->i_pitch  = d3drect.Pitch;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Direct3DVoutUnlockSurface: Unlock a surface locked by Direct3DLockSurface().
+ *****************************************************************************/
+static int Direct3DVoutUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    HRESULT hr;
+    LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;
+
+    if( NULL == p_d3dsurf )
+        return VLC_EGENERIC;
+
+    /* Unlock the Surface */
+    hr = IDirect3DSurface9_UnlockRect(p_d3dsurf);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Direct3DVoutCreateScene: allocate and initialize a 3D scene
+ *****************************************************************************
+ * for advanced blending/filtering a texture needs be used in a 3D scene.
+ *****************************************************************************/
+
+static int Direct3DVoutCreateScene( vout_thread_t *p_vout )
+{
+    LPDIRECT3DDEVICE9       p_d3ddev  = p_vout->p_sys->p_d3ddev;
+    LPDIRECT3DTEXTURE9      p_d3dtex;
+    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc;
+
+    HRESULT hr;
+
+    /*
+    ** Create a texture for use when rendering a scene
+    ** for performance reason, texture format is identical to backbuffer
+    ** which would usually be a RGB format
+    */
+    hr = IDirect3DDevice9_CreateTexture(p_d3ddev, 
+            p_vout->render.i_width,
+            p_vout->render.i_height,
+            1,
+            D3DUSAGE_RENDERTARGET, 
+            p_vout->p_sys->bbFormat,
+            D3DPOOL_DEFAULT,
+            &p_d3dtex, 
+            NULL);
+    if( FAILED(hr))
+    {
+        msg_Err(p_vout, "Failed to create texture. (hr=0x%lx)", hr);
+        return VLC_EGENERIC;
+    }
+
+    /*
+    ** Create a vertex buffer for use when rendering scene
+    */
+    hr = IDirect3DDevice9_CreateVertexBuffer(p_d3ddev,
+            sizeof(CUSTOMVERTEX)*4,
+            D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
+            D3DFVF_CUSTOMVERTEX,
+            D3DPOOL_DEFAULT,
+            &p_d3dvtc,
+            NULL);
+    if( FAILED(hr) )
+    {
+        msg_Err(p_vout, "Failed to create vertex buffer. (hr=0x%lx)", hr);
+            IDirect3DTexture9_Release(p_d3dtex);
+        return VLC_EGENERIC;
+    }
+
+    p_vout->p_sys->p_d3dtex = p_d3dtex;
+    p_vout->p_sys->p_d3dvtc = p_d3dvtc;
+
+    // Texture coordinates outside the range [0.0, 1.0] are set 
+    // to the texture color at 0.0 or 1.0, respectively.
+    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+
+    // Set linear filtering quality
+    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
+    // set maximum ambient light
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255));
+
+    // Turn off culling
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_CULLMODE, D3DCULL_NONE);
+
+    // Turn off the zbuffer
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ZENABLE, D3DZB_FALSE);
+
+    // Turn off lights
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_LIGHTING, FALSE);
+
+    // Enable dithering
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_DITHERENABLE, TRUE);
+
+    // disable stencil
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_STENCILENABLE, FALSE);
+
+    // manage blending
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHABLENDENABLE, TRUE);
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHATESTENABLE,TRUE);
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHAREF, 0x10);
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHAFUNC,D3DCMP_GREATER);
+
+    // Set texture states
+    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_COLOROP,D3DTOP_MODULATE);
+    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_COLORARG1,D3DTA_TEXTURE);
+    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_COLORARG2,D3DTA_DIFFUSE);
+
+    // turn off alpha operation
+    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+
+    msg_Dbg( p_vout, "Direct3D scene created successfully");
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Direct3DVoutReleaseScene
+ *****************************************************************************/
+static void Direct3DVoutReleaseScene( vout_thread_t *p_vout )
+{
+    LPDIRECT3DTEXTURE9      p_d3dtex = p_vout->p_sys->p_d3dtex;
+    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc = p_vout->p_sys->p_d3dvtc;
+
+    if( p_d3dvtc )
+    {
+        IDirect3DVertexBuffer9_Release(p_d3dvtc);
+        p_vout->p_sys->p_d3dvtc = NULL;
+    }
+
+    if( p_d3dtex )
+    {
+        IDirect3DTexture9_Release(p_d3dtex);
+        p_vout->p_sys->p_d3dtex = NULL;
+    }
+    msg_Dbg( p_vout, "Direct3D scene released successfully");
+}
+
+/*****************************************************************************
+ * Render: copy picture surface into a texture and render into a scene
+ *****************************************************************************
+ * This function is intented for higher end 3D cards, with pixel shader support
+ * and at least 64 MB of video RAM.
+ *****************************************************************************/
+static void Direct3DVoutRenderScene( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    LPDIRECT3DDEVICE9       p_d3ddev  = p_vout->p_sys->p_d3ddev;
+    LPDIRECT3DTEXTURE9      p_d3dtex;
+    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc;
+    LPDIRECT3DSURFACE9      p_d3dsrc, p_d3ddest;
+    CUSTOMVERTEX            *p_vertices;
+    HRESULT hr;
+    float f_width, f_height;
+
+    // check if device is still available    
+    hr = IDirect3DDevice9_TestCooperativeLevel(p_d3ddev);
+    if( FAILED(hr) )
+    {
+        if( (D3DERR_DEVICENOTRESET != hr)
+         || (VLC_SUCCESS != Direct3DVoutResetDevice(p_vout)) )
+        {
+            // device is not usable at present (lost device, out of video mem ?)
+            return;
+        }
+    }
+    p_d3dtex  = p_vout->p_sys->p_d3dtex;
+    p_d3dvtc  = p_vout->p_sys->p_d3dvtc;
+
+    /* Clear the backbuffer and the zbuffer */
+    hr = IDirect3DDevice9_Clear( p_d3ddev, 0, NULL, D3DCLEAR_TARGET,
+                              D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0 );
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        return;
+    }
+
+    /*  retrieve picture surface */
+    p_d3dsrc = (LPDIRECT3DSURFACE9)p_pic->p_sys;
+    if( NULL == p_d3dsrc )
+    {
+        msg_Dbg( p_vout, "no surface to render ?");
+        return;
+    }
+
+    /* retrieve texture top-level surface */
+    hr = IDirect3DTexture9_GetSurfaceLevel(p_d3dtex, 0, &p_d3ddest);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        return;
+    }
+
+    /* Copy picture surface into texture surface, color space conversion happens here */
+    hr = IDirect3DDevice9_StretchRect(p_d3ddev, p_d3dsrc, NULL, p_d3ddest, NULL, D3DTEXF_NONE);
+    IDirect3DSurface9_Release(p_d3ddest);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        return;
+    }
+
+    /* Update the vertex buffer */
+    hr = IDirect3DVertexBuffer9_Lock(p_d3dvtc, 0, 0, (VOID **)(&p_vertices), D3DLOCK_DISCARD);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        return;
+    }
+
+    /* Setup vertices */
+    f_width  = (float)(p_vout->output.i_width);
+    f_height = (float)(p_vout->output.i_height);
+
+    p_vertices[0].x       = 0.0f;       // left
+    p_vertices[0].y       = 0.0f;       // top
+    p_vertices[0].z       = 0.0f;
+    p_vertices[0].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
+    p_vertices[0].rhw     = 1.0f;
+    p_vertices[0].tu      = 0.0f;
+    p_vertices[0].tv      = 0.0f;
+    p_vertices[1].x       = f_width;    // right
+    p_vertices[1].y       = 0.0f;       // top
+    p_vertices[1].z       = 0.0f;
+    p_vertices[1].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
+    p_vertices[1].rhw     = 1.0f;
+    p_vertices[1].tu      = 1.0f;
+    p_vertices[1].tv      = 0.0f;
+    p_vertices[2].x       = f_width;    // right
+    p_vertices[2].y       = f_height;   // bottom
+    p_vertices[2].z       = 0.0f;
+    p_vertices[2].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
+    p_vertices[2].rhw     = 1.0f;
+    p_vertices[2].tu      = 1.0f;
+    p_vertices[2].tv      = 1.0f;
+    p_vertices[3].x       = 0.0f;       // left
+    p_vertices[3].y       = f_height;   // bottom
+    p_vertices[3].z       = 0.0f;
+    p_vertices[3].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
+    p_vertices[3].rhw     = 1.0f;
+    p_vertices[3].tu      = 0.0f;
+    p_vertices[3].tv      = 1.0f;
+    hr= IDirect3DVertexBuffer9_Unlock(p_d3dvtc);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        return;
+    }
+
+    // Begin the scene
+    hr = IDirect3DDevice9_BeginScene(p_d3ddev);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        return;
+    }
+
+    // Setup our texture. Using textures introduces the texture stage states,
+    // which govern how textures get blended together (in the case of multiple
+    // textures) and lighting information. In this case, we are modulating
+    // (blending) our texture with the diffuse color of the vertices.
+    hr = IDirect3DDevice9_SetTexture(p_d3ddev, 0, (LPDIRECT3DBASETEXTURE9)p_d3dtex);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        IDirect3DDevice9_EndScene(p_d3ddev);
+        return;
+    }
+
+    // Render the vertex buffer contents
+    hr = IDirect3DDevice9_SetStreamSource(p_d3ddev, 0, p_d3dvtc, 0, sizeof(CUSTOMVERTEX));
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        IDirect3DDevice9_EndScene(p_d3ddev);
+        return;
+    }
+    // we use FVF instead of vertex shader
+    hr = IDirect3DDevice9_SetVertexShader(p_d3ddev, NULL);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        IDirect3DDevice9_EndScene(p_d3ddev);
+        return;
+    }
+
+    hr = IDirect3DDevice9_SetFVF(p_d3ddev, D3DFVF_CUSTOMVERTEX);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        IDirect3DDevice9_EndScene(p_d3ddev);
+        return;
+    }
+
+    // draw rectangle
+    hr = IDirect3DDevice9_DrawPrimitive(p_d3ddev, D3DPT_TRIANGLEFAN, 0, 2);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        IDirect3DDevice9_EndScene(p_d3ddev);
+        return;
+    }
+
+    // End the scene
+    hr = IDirect3DDevice9_EndScene(p_d3ddev);
+    if( FAILED(hr) )
+    {
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        return;
+    }
+}
+
diff --git a/modules/video_output/msw/directx.c b/modules/video_output/msw/directx.c
new file mode 100644 (file)
index 0000000..e6500b7
--- /dev/null
@@ -0,0 +1,2157 @@
+/*****************************************************************************
+ * vout.c: Windows DirectX video output display method
+ *****************************************************************************
+ * Copyright (C) 2001-2004 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble:
+ *
+ * This plugin will use YUV overlay if supported, using overlay will result in
+ * the best video quality (hardware interpolation when rescaling the picture)
+ * and the fastest display as it requires less processing.
+ *
+ * If YUV overlay is not supported this plugin will use RGB offscreen video
+ * surfaces that will be blitted onto the primary surface (display) to
+ * effectively display the pictures. This fallback method also enables us to
+ * display video in window mode.
+ *
+ *****************************************************************************/
+#include <errno.h>                                                 /* ENOMEM */
+#include <stdlib.h>                                                /* free() */
+#include <string.h>                                            /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc_interface.h>
+#include <vlc_playlist.h>
+#include <vlc_vout.h>
+
+#include <windows.h>
+#include <ddraw.h>
+#include <commctrl.h>
+
+#ifndef UNDER_CE
+#   include <multimon.h>
+#endif
+#undef GetSystemMetrics
+
+#ifndef MONITOR_DEFAULTTONEAREST
+#   define MONITOR_DEFAULTTONEAREST 2
+#endif
+
+#include "vout.h"
+
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+struct picture_sys_t
+{
+    LPDIRECTDRAWSURFACE2 p_surface;
+    LPDIRECTDRAWSURFACE2 p_front_surface;
+    DDSURFACEDESC        ddsd;
+};
+
+/*****************************************************************************
+ * DirectDraw GUIDs.
+ * Defining them here allows us to get rid of the dxguid library during
+ * the linking stage.
+ *****************************************************************************/
+#include <initguid.h>
+#undef GUID_EXT
+#define GUID_EXT
+DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int  OpenVideo  ( vlc_object_t * );
+static void CloseVideo ( vlc_object_t * );
+
+static int  Init      ( vout_thread_t * );
+static void End       ( vout_thread_t * );
+static int  Manage    ( vout_thread_t * );
+static void Display   ( vout_thread_t *, picture_t * );
+static void FirstDisplay( vout_thread_t *, picture_t * );
+static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
+
+static int  NewPictureVec  ( vout_thread_t *, picture_t *, int );
+static void FreePictureVec ( vout_thread_t *, picture_t *, int );
+static int  UpdatePictureStruct( vout_thread_t *, picture_t *, int );
+
+static int  DirectXInitDDraw      ( vout_thread_t *p_vout );
+static void DirectXCloseDDraw     ( vout_thread_t *p_vout );
+static int  DirectXCreateDisplay  ( vout_thread_t *p_vout );
+static void DirectXCloseDisplay   ( vout_thread_t *p_vout );
+static int  DirectXCreateSurface  ( vout_thread_t *p_vout,
+                                    LPDIRECTDRAWSURFACE2 *, int, int, int );
+static void DirectXCloseSurface   ( vout_thread_t *p_vout,
+                                    LPDIRECTDRAWSURFACE2 );
+static int  DirectXCreateClipper  ( vout_thread_t *p_vout );
+static void DirectXGetDDrawCaps   ( vout_thread_t *p_vout );
+static int  DirectXLockSurface    ( vout_thread_t *p_vout, picture_t *p_pic );
+static int  DirectXUnlockSurface  ( vout_thread_t *p_vout, picture_t *p_pic );
+
+static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *i_color );
+
+void SwitchWallpaperMode( vout_thread_t *, vlc_bool_t );
+
+/* Object variables callbacks */
+static int FindDevicesCallback( vlc_object_t *, char const *,
+                                vlc_value_t, vlc_value_t, void * );
+static int WallpaperCallback( vlc_object_t *, char const *,
+                              vlc_value_t, vlc_value_t, void * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define HW_YUV_TEXT N_("Use hardware YUV->RGB conversions")
+#define HW_YUV_LONGTEXT N_( \
+    "Try to use hardware acceleration for YUV->RGB conversions. " \
+    "This option doesn't have any effect when using overlays." )
+
+#define SYSMEM_TEXT N_("Use video buffers in system memory")
+#define SYSMEM_LONGTEXT N_( \
+    "Create video buffers in system memory instead of video memory. This " \
+    "isn't recommended as usually using video memory allows to benefit from " \
+    "more hardware acceleration (like rescaling or YUV->RGB conversions). " \
+    "This option doesn't have any effect when using overlays." )
+
+#define TRIPLEBUF_TEXT N_("Use triple buffering for overlays")
+#define TRIPLEBUF_LONGTEXT N_( \
+    "Try to use triple buffering when using YUV overlays. That results in " \
+    "much better video quality (no flickering)." )
+
+#define DEVICE_TEXT N_("Name of desired display device")
+#define DEVICE_LONGTEXT N_("In a multiple monitor configuration, you can " \
+    "specify the Windows device name of the display that you want the video " \
+    "window to open on. For example, \"\\\\.\\DISPLAY1\" or " \
+    "\"\\\\.\\DISPLAY2\"." )
+
+#define WALLPAPER_TEXT N_("Enable wallpaper mode ")
+#define WALLPAPER_LONGTEXT N_( \
+    "The wallpaper mode allows you to display the video as the desktop " \
+    "background. Note that this feature only works in overlay mode and " \
+    "the desktop must not already have a wallpaper." )
+
+static char *ppsz_dev[] = { "" };
+static char *ppsz_dev_text[] = { N_("Default") };
+
+vlc_module_begin();
+    set_shortname( "DirectX" );
+    set_category( CAT_VIDEO );
+    set_subcategory( SUBCAT_VIDEO_VOUT );
+    add_bool( "directx-hw-yuv", 1, NULL, HW_YUV_TEXT, HW_YUV_LONGTEXT,
+              VLC_TRUE );
+    add_bool( "directx-use-sysmem", 0, NULL, SYSMEM_TEXT, SYSMEM_LONGTEXT,
+              VLC_TRUE );
+    add_bool( "directx-3buffering", 1, NULL, TRIPLEBUF_TEXT,
+              TRIPLEBUF_LONGTEXT, VLC_TRUE );
+
+    add_string( "directx-device", "", NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
+                VLC_TRUE );
+        change_string_list( ppsz_dev, ppsz_dev_text, FindDevicesCallback );
+        change_action_add( FindDevicesCallback, N_("Refresh list") );
+
+    add_bool( "directx-wallpaper", 0, NULL, WALLPAPER_TEXT, WALLPAPER_LONGTEXT,
+              VLC_TRUE );
+
+    set_description( _("DirectX video output") );
+    set_capability( "video output", 100 );
+    add_shortcut( "directx" );
+    set_callbacks( OpenVideo, CloseVideo );
+
+    /* FIXME: Hack to avoid unregistering our window class */
+    linked_with_a_crap_library_which_uses_atexit( );
+vlc_module_end();
+
+#if 0 /* FIXME */
+    /* check if we registered a window class because we need to
+     * unregister it */
+    WNDCLASS wndclass;
+    if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )
+        UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );
+#endif
+
+/*****************************************************************************
+ * OpenVideo: allocate DirectX video thread output method
+ *****************************************************************************
+ * This function allocates and initialize the DirectX vout method.
+ *****************************************************************************/
+static int OpenVideo( vlc_object_t *p_this )
+{
+    vout_thread_t * p_vout = (vout_thread_t *)p_this;
+    vlc_value_t val;
+    HMODULE huser32;
+
+    /* Allocate structure */
+    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+    if( p_vout->p_sys == NULL )
+    {
+        msg_Err( p_vout, "out of memory" );
+        return VLC_ENOMEM;
+    }
+    memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
+
+    /* Initialisations */
+    p_vout->pf_init = Init;
+    p_vout->pf_end = End;
+    p_vout->pf_manage = Manage;
+    p_vout->pf_render = NULL;
+    p_vout->pf_display = FirstDisplay;
+
+    p_vout->p_sys->p_ddobject = NULL;
+    p_vout->p_sys->p_display = NULL;
+    p_vout->p_sys->p_current_surface = NULL;
+    p_vout->p_sys->p_clipper = NULL;
+    p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
+    p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
+    p_vout->p_sys->i_changes = 0;
+    p_vout->p_sys->b_wallpaper = 0;
+    vlc_mutex_init( p_vout, &p_vout->p_sys->lock );
+    SetRectEmpty( &p_vout->p_sys->rect_display );
+    SetRectEmpty( &p_vout->p_sys->rect_parent );
+
+    /* Multimonitor stuff */
+    p_vout->p_sys->hmonitor = NULL;
+    p_vout->p_sys->p_display_driver = NULL;
+    p_vout->p_sys->MonitorFromWindow = NULL;
+    p_vout->p_sys->GetMonitorInfo = NULL;
+    if( (huser32 = GetModuleHandle( _T("USER32") ) ) )
+    {
+        p_vout->p_sys->MonitorFromWindow = (HMONITOR (WINAPI *)( HWND, DWORD ))
+            GetProcAddress( huser32, _T("MonitorFromWindow") );
+        p_vout->p_sys->GetMonitorInfo =
+#ifndef UNICODE
+            GetProcAddress( huser32, "GetMonitorInfoA" );
+#else
+            GetProcAddress( huser32, _T("GetMonitorInfoW") );
+#endif
+    }
+
+    var_Create( p_vout, "overlay", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+    var_Create( p_vout, "directx-use-sysmem", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
+    var_Create( p_vout, "directx-hw-yuv", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+    var_Create( p_vout, "directx-3buffering", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
+    var_Create( p_vout, "directx-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
+    var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
+    var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+
+    p_vout->p_sys->b_cursor_hidden = 0;
+    p_vout->p_sys->i_lastmoved = mdate();
+
+    /* Set main window's size */
+    p_vout->p_sys->i_window_width = p_vout->i_window_width;
+    p_vout->p_sys->i_window_height = p_vout->i_window_height;
+
+    /* Create the Vout EventThread, this thread is created by us to isolate
+     * the Win32 PeekMessage function calls. We want to do this because
+     * Windows can stay blocked inside this call for a long time, and when
+     * this happens it thus blocks vlc's video_output thread.
+     * DirectXEventThread will take care of the creation of the video
+     * window (because PeekMessage has to be called from the same thread which
+     * created the window). */
+    msg_Dbg( p_vout, "creating DirectXEventThread" );
+    p_vout->p_sys->p_event =
+        vlc_object_create( p_vout, sizeof(event_thread_t) );
+    p_vout->p_sys->p_event->p_vout = p_vout;
+    if( vlc_thread_create( p_vout->p_sys->p_event, "Vout Events Thread",
+                           E_(EventThread), 0, 1 ) )
+    {
+        msg_Err( p_vout, "cannot create Vout EventThread" );
+        vlc_object_destroy( p_vout->p_sys->p_event );
+        p_vout->p_sys->p_event = NULL;
+        goto error;
+    }
+
+    if( p_vout->p_sys->p_event->b_error )
+    {
+        msg_Err( p_vout, "Vout EventThread failed" );
+        goto error;
+    }
+
+    vlc_object_attach( p_vout->p_sys->p_event, p_vout );
+
+    msg_Dbg( p_vout, "Vout EventThread running" );
+
+    /* Initialise DirectDraw */
+    if( DirectXInitDDraw( p_vout ) )
+    {
+        msg_Err( p_vout, "cannot initialize DirectX DirectDraw" );
+        goto error;
+    }
+
+    /* Create the directx display */
+    if( DirectXCreateDisplay( p_vout ) )
+    {
+        msg_Err( p_vout, "cannot initialize DirectX DirectDraw" );
+        goto error;
+    }
+
+    /* Variable to indicate if the window should be on top of others */
+    /* Trigger a callback right now */
+    var_Get( p_vout, "video-on-top", &val );
+    var_Set( p_vout, "video-on-top", val );
+
+    /* Variable to indicate if the window should be on top of others */
+    /* Trigger a callback right now */
+    var_Create( p_vout, "directx-wallpaper", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
+    val.psz_string = _("Wallpaper");
+    var_Change( p_vout, "directx-wallpaper", VLC_VAR_SETTEXT, &val, NULL );
+    var_AddCallback( p_vout, "directx-wallpaper", WallpaperCallback, NULL );
+    var_Get( p_vout, "directx-wallpaper", &val );
+    var_Set( p_vout, "directx-wallpaper", val );
+
+    /* disable screensaver by temporarily changing system settings */
+    p_vout->p_sys->i_spi_lowpowertimeout = 0;
+    p_vout->p_sys->i_spi_powerofftimeout = 0;
+    p_vout->p_sys->i_spi_screensavetimeout = 0;
+    var_Get( p_vout, "disable-screensaver", &val);
+    if( val.b_bool ) {
+        msg_Dbg(p_vout, "disabling screen saver");
+        SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT,
+            0, &(p_vout->p_sys->i_spi_lowpowertimeout), 0);
+        if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {
+            SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0);
+        }
+        SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0,
+            &(p_vout->p_sys->i_spi_powerofftimeout), 0);
+        if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
+            SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, 0, NULL, 0);
+        }
+        SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0,
+            &(p_vout->p_sys->i_spi_screensavetimeout), 0);
+        if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {
+            SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 0, NULL, 0);
+        }
+    }
+
+    return VLC_SUCCESS;
+
+ error:
+    CloseVideo( VLC_OBJECT(p_vout) );
+    return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * 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 Init( vout_thread_t *p_vout )
+{
+    int i_chroma_backup;
+    vlc_value_t val;
+
+    /* Get a few default parameters */
+    var_Get( p_vout, "overlay", &val );
+    p_vout->p_sys->b_using_overlay = val.b_bool;
+    var_Get( p_vout, "directx-use-sysmem", &val );
+    p_vout->p_sys->b_use_sysmem = val.b_bool;
+    var_Get( p_vout, "directx-hw-yuv", &val );
+    p_vout->p_sys->b_hw_yuv = val.b_bool;
+    var_Get( p_vout, "directx-3buffering", &val );
+    p_vout->p_sys->b_3buf_overlay = val.b_bool;
+
+    /* Initialise DirectDraw if not already done.
+     * We do this here because on multi-monitor systems we may have to
+     * re-create the directdraw surfaces. */
+    if( !p_vout->p_sys->p_ddobject &&
+        DirectXInitDDraw( p_vout ) != VLC_SUCCESS )
+    {
+        msg_Err( p_vout, "cannot initialize DirectDraw" );
+        return VLC_EGENERIC;
+    }
+
+    /* Create the directx display */
+    if( !p_vout->p_sys->p_display &&
+        DirectXCreateDisplay( p_vout ) != VLC_SUCCESS )
+    {
+        msg_Err( p_vout, "cannot initialize DirectDraw" );
+        return VLC_EGENERIC;
+    }
+
+    /* 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;
+    p_vout->fmt_out = p_vout->fmt_in;
+    E_(UpdateRects)( p_vout, VLC_TRUE );
+
+#define MAX_DIRECTBUFFERS 1
+    /* Right now we use only 1 directbuffer because we don't want the
+     * video decoder to decode directly into direct buffers as they are
+     * created into video memory and video memory is _really_ slow */
+
+    /* Choose the chroma we will try first. */
+    switch( p_vout->render.i_chroma )
+    {
+        case VLC_FOURCC('Y','U','Y','2'):
+        case VLC_FOURCC('Y','U','N','V'):
+            p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
+            break;
+        case VLC_FOURCC('U','Y','V','Y'):
+        case VLC_FOURCC('U','Y','N','V'):
+        case VLC_FOURCC('Y','4','2','2'):
+            p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
+            break;
+        case VLC_FOURCC('Y','V','Y','U'):
+            p_vout->output.i_chroma = VLC_FOURCC('Y','V','Y','U');
+            break;
+        default:
+            p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
+            break;
+    }
+
+    NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
+
+    i_chroma_backup = p_vout->output.i_chroma;
+
+    if( !I_OUTPUTPICTURES )
+    {
+        /* hmmm, it didn't work! Let's try commonly supported chromas */
+        if( p_vout->output.i_chroma != VLC_FOURCC('I','4','2','0') )
+        {
+            p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
+            NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
+        }
+        if( !I_OUTPUTPICTURES )
+        {
+            /* hmmm, it still didn't work! Let's try another one */
+            p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
+            NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
+        }
+    }
+
+    if( !I_OUTPUTPICTURES )
+    {
+        /* If it still didn't work then don't try to use an overlay */
+        p_vout->output.i_chroma = i_chroma_backup;
+        p_vout->p_sys->b_using_overlay = 0;
+        NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
+    }
+
+    /* Change the window title bar text */
+    PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
+
+    p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * End: terminate Sys video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create.
+ * It is called at the end of the thread.
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+    FreePictureVec( p_vout, p_vout->p_picture, I_OUTPUTPICTURES );
+
+    DirectXCloseDisplay( p_vout );
+    DirectXCloseDDraw( p_vout );
+
+    return;
+}
+
+/*****************************************************************************
+ * CloseVideo: destroy Sys video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create
+ *****************************************************************************/
+static void CloseVideo( vlc_object_t *p_this )
+{
+    vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+    msg_Dbg( p_vout, "CloseVideo" );
+
+    if( p_vout->p_sys->p_event )
+    {
+        vlc_object_detach( p_vout->p_sys->p_event );
+
+        /* Kill Vout EventThread */
+        p_vout->p_sys->p_event->b_die = VLC_TRUE;
+
+        /* we need to be sure Vout EventThread won't stay stuck in
+         * GetMessage, so we send a fake message */
+        if( p_vout->p_sys->hwnd )
+        {
+            PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);
+        }
+
+        vlc_thread_join( p_vout->p_sys->p_event );
+        vlc_object_destroy( p_vout->p_sys->p_event );
+    }
+
+    vlc_mutex_destroy( &p_vout->p_sys->lock );
+
+    /* Make sure the wallpaper is restored */
+    SwitchWallpaperMode( p_vout, VLC_FALSE );
+
+    /* restore screensaver system settings */
+    if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {
+        SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT,
+            p_vout->p_sys->i_spi_lowpowertimeout, NULL, 0);
+    }
+    if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
+        SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT,
+            p_vout->p_sys->i_spi_powerofftimeout, NULL, 0);
+    }
+    if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {
+        SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT,
+            p_vout->p_sys->i_spi_screensavetimeout, NULL, 0);
+    }
+
+    if( p_vout->p_sys )
+    {
+        free( p_vout->p_sys );
+        p_vout->p_sys = NULL;
+    }
+}
+
+/*****************************************************************************
+ * Manage: handle Sys events
+ *****************************************************************************
+ * This function should be called regularly by the video output thread.
+ * It returns a non null value if an error occurred.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+    /* If we do not control our window, we check for geometry changes
+     * ourselves because the parent might not send us its events. */
+    vlc_mutex_lock( &p_vout->p_sys->lock );
+    if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
+    {
+        RECT rect_parent;
+        POINT point;
+
+        vlc_mutex_unlock( &p_vout->p_sys->lock );
+
+        GetClientRect( p_vout->p_sys->hparent, &rect_parent );
+        point.x = point.y = 0;
+        ClientToScreen( p_vout->p_sys->hparent, &point );
+        OffsetRect( &rect_parent, point.x, point.y );
+
+        if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
+        {
+            p_vout->p_sys->rect_parent = rect_parent;
+
+            /* This one is to force the update even if only
+             * the position has changed */
+            SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1,
+                          rect_parent.right - rect_parent.left,
+                          rect_parent.bottom - rect_parent.top, 0 );
+
+            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
+                          rect_parent.right - rect_parent.left,
+                          rect_parent.bottom - rect_parent.top, 0 );
+        }
+    }
+    else
+    {
+        vlc_mutex_unlock( &p_vout->p_sys->lock );
+    }
+
+    /*
+     * Position Change
+     */
+    if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE )
+    {
+        p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
+
+        /* Check if we are still on the same monitor */
+        if( p_vout->p_sys->MonitorFromWindow &&
+            p_vout->p_sys->hmonitor !=
+                p_vout->p_sys->MonitorFromWindow( p_vout->p_sys->hwnd,
+                                                  MONITOR_DEFAULTTONEAREST ) )
+        {
+            /* This will force the vout core to recreate the picture buffers */
+            p_vout->i_changes |= VOUT_PICTURE_BUFFERS_CHANGE;
+        }
+    }
+
+    /* Check for cropping / aspect changes */
+    if( p_vout->i_changes & VOUT_CROP_CHANGE ||
+        p_vout->i_changes & VOUT_ASPECT_CHANGE )
+    {
+        p_vout->i_changes &= ~VOUT_CROP_CHANGE;
+        p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
+
+        p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset;
+        p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset;
+        p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width;
+        p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height;
+        p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect;
+        p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;
+        p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;
+        p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
+        E_(UpdateRects)( p_vout, VLC_TRUE );
+    }
+
+    /* We used to call the Win32 PeekMessage function here to read the window
+     * messages. But since window can stay blocked into this function for a
+     * long time (for example when you move your window on the screen), I
+     * decided to isolate PeekMessage in another thread. */
+
+    if( p_vout->p_sys->i_changes & DX_WALLPAPER_CHANGE )
+    {
+        SwitchWallpaperMode( p_vout, !p_vout->p_sys->b_wallpaper );
+        p_vout->p_sys->i_changes &= ~DX_WALLPAPER_CHANGE;
+        DirectDrawUpdateOverlay( p_vout );
+    }
+
+    /*
+     * Fullscreen change
+     */
+    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
+        || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
+    {
+        Win32ToggleFullscreen( p_vout );
+
+        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+        p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+    }
+
+    /*
+     * Pointer change
+     */
+    if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&
+        (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 )
+    {
+        POINT point;
+        HWND hwnd;
+
+        /* Hide the cursor only if it is inside our window */
+        GetCursorPos( &point );
+        hwnd = WindowFromPoint(point);
+        if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )
+        {
+            PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
+        }
+        else
+        {
+            p_vout->p_sys->i_lastmoved = mdate();
+        }
+    }
+
+    /*
+     * "Always on top" status change
+     */
+    if( p_vout->p_sys->b_on_top_change )
+    {
+        vlc_value_t val;
+        HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
+
+        var_Get( p_vout, "video-on-top", &val );
+
+        /* Set the window on top if necessary */
+        if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
+                           & WS_EX_TOPMOST ) )
+        {
+            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
+                           MF_BYCOMMAND | MFS_CHECKED );
+            SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,
+                          SWP_NOSIZE | SWP_NOMOVE );
+        }
+        else
+        /* The window shouldn't be on top */
+        if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
+                           & WS_EX_TOPMOST ) )
+        {
+            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
+                           MF_BYCOMMAND | MFS_UNCHECKED );
+            SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
+                          SWP_NOSIZE | SWP_NOMOVE );
+        }
+
+        p_vout->p_sys->b_on_top_change = VLC_FALSE;
+    }
+
+    /* Check if the event thread is still running */
+    if( p_vout->p_sys->p_event->b_die )
+    {
+        return VLC_EGENERIC; /* exit */
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Display: displays previously rendered output
+ *****************************************************************************
+ * 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 Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    HRESULT dxresult;
+
+    if( (p_vout->p_sys->p_display == NULL) )
+    {
+        msg_Warn( p_vout, "no display!" );
+        return;
+    }
+
+    /* Our surface can be lost so be sure to check this
+     * and restore it if need be */
+    if( IDirectDrawSurface2_IsLost( p_vout->p_sys->p_display )
+        == DDERR_SURFACELOST )
+    {
+        if( IDirectDrawSurface2_Restore( p_vout->p_sys->p_display ) == DD_OK &&
+            p_vout->p_sys->b_using_overlay )
+            DirectDrawUpdateOverlay( p_vout );
+    }
+
+    if( !p_vout->p_sys->b_using_overlay )
+    {
+        DDBLTFX  ddbltfx;
+
+        /* We ask for the "NOTEARING" option */
+        memset( &ddbltfx, 0, sizeof(DDBLTFX) );
+        ddbltfx.dwSize = sizeof(DDBLTFX);
+        ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
+
+        /* Blit video surface to display */
+        dxresult = IDirectDrawSurface2_Blt( p_vout->p_sys->p_display,
+                                            &p_vout->p_sys->rect_dest_clipped,
+                                            p_pic->p_sys->p_surface,
+                                            &p_vout->p_sys->rect_src_clipped,
+                                            DDBLT_ASYNC, &ddbltfx );
+        if( dxresult != DD_OK )
+        {
+            msg_Warn( p_vout, "could not blit surface (error %li)", dxresult );
+            return;
+        }
+    }
+    else /* using overlay */
+    {
+        /* Flip the overlay buffers if we are using back buffers */
+        if( p_pic->p_sys->p_front_surface == p_pic->p_sys->p_surface )
+        {
+            return;
+        }
+
+        dxresult = IDirectDrawSurface2_Flip( p_pic->p_sys->p_front_surface,
+                                             NULL, DDFLIP_WAIT );
+        if( dxresult != DD_OK )
+        {
+            msg_Warn( p_vout, "could not flip overlay (error %li)", dxresult );
+        }
+
+        /* set currently displayed pic */
+        p_vout->p_sys->p_current_surface = p_pic->p_sys->p_front_surface;
+
+        /* Lock surface to get all the required info */
+        if( DirectXLockSurface( p_vout, p_pic ) )
+        {
+            /* AAARRGG */
+            msg_Warn( p_vout, "cannot lock surface" );
+            return;
+        }
+        DirectXUnlockSurface( p_vout, p_pic );
+    }
+}
+
+/*
+** this function is only used once when the first picture is received
+** this function will show the video window once video is ready for
+** display.
+*/
+
+static void FirstDisplay( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    /* get initial picture rendered on overlay surface */
+    Display(p_vout, p_pic);
+
+    IDirectDraw_WaitForVerticalBlank(p_vout->p_sys->p_ddobject,
+            DDWAITVB_BLOCKBEGIN, NULL);
+
+    if( p_vout->p_sys->b_using_overlay )
+    {
+        /* set the colorkey as the backgound brush for the video window */
+        SetClassLong( p_vout->p_sys->hvideownd, GCL_HBRBACKGROUND,
+                      (LONG)CreateSolidBrush( p_vout->p_sys->i_rgb_colorkey ) );
+    }
+    /*
+    ** Video window is initially hidden, show it now since we got a 
+    ** picture to show.
+    */
+    SetWindowPos( p_vout->p_sys->hvideownd, NULL, 0, 0, 0, 0, 
+        SWP_ASYNCWINDOWPOS|
+        SWP_FRAMECHANGED|
+        SWP_SHOWWINDOW|
+        SWP_NOMOVE|
+        SWP_NOSIZE|
+        SWP_NOZORDER );
+
+    /* use and restores proper display function for further pictures */
+    p_vout->pf_display = Display;
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * DirectXEnumCallback: Device enumeration
+ *****************************************************************************
+ * This callback function is called by DirectDraw once for each
+ * available DirectDraw device.
+ *****************************************************************************/
+BOOL WINAPI DirectXEnumCallback( GUID* p_guid, LPTSTR psz_desc,
+                                 LPTSTR psz_drivername, VOID* p_context,
+                                 HMONITOR hmon )
+{
+    vout_thread_t *p_vout = (vout_thread_t *)p_context;
+    vlc_value_t device;
+
+    msg_Dbg( p_vout, "DirectXEnumCallback: %s, %s", psz_desc, psz_drivername );
+
+    if( hmon )
+    {
+        var_Get( p_vout, "directx-device", &device );
+
+        if( ( !device.psz_string || !*device.psz_string ) &&
+            hmon == p_vout->p_sys->hmonitor )
+        {
+            if( device.psz_string ) free( device.psz_string );
+        }
+        else if( strcmp( psz_drivername, device.psz_string ) == 0 )
+        {
+            MONITORINFO monitor_info;
+            monitor_info.cbSize = sizeof( MONITORINFO );
+
+            if( p_vout->p_sys->GetMonitorInfo( hmon, &monitor_info ) )
+            {
+                RECT rect;
+
+                /* Move window to the right screen */
+                GetWindowRect( p_vout->p_sys->hwnd, &rect );
+                if( !IntersectRect( &rect, &rect, &monitor_info.rcWork ) )
+                {
+                    rect.left = monitor_info.rcWork.left;
+                    rect.top = monitor_info.rcWork.top;
+                    msg_Dbg( p_vout, "DirectXEnumCallback: setting window "
+                             "position to %ld,%ld", rect.left, rect.top );
+                    SetWindowPos( p_vout->p_sys->hwnd, NULL,
+                                  rect.left, rect.top, 0, 0,
+                                  SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
+                }
+            }
+
+            p_vout->p_sys->hmonitor = hmon;
+            if( device.psz_string ) free( device.psz_string );
+        }
+        else
+        {
+            if( device.psz_string ) free( device.psz_string );
+            return TRUE; /* Keep enumerating */
+        }
+
+        msg_Dbg( p_vout, "selecting %s, %s", psz_desc, psz_drivername );
+        p_vout->p_sys->p_display_driver = malloc( sizeof(GUID) );
+        if( p_vout->p_sys->p_display_driver )
+            memcpy( p_vout->p_sys->p_display_driver, p_guid, sizeof(GUID) );
+    }
+
+    return TRUE; /* Keep enumerating */
+}
+
+/*****************************************************************************
+ * DirectXInitDDraw: Takes care of all the DirectDraw initialisations
+ *****************************************************************************
+ * This function initialise and allocate resources for DirectDraw.
+ *****************************************************************************/
+static int DirectXInitDDraw( vout_thread_t *p_vout )
+{
+    HRESULT dxresult;
+    HRESULT (WINAPI *OurDirectDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
+    HRESULT (WINAPI *OurDirectDrawEnumerateEx)( LPDDENUMCALLBACKEXA, LPVOID,
+                                                DWORD );
+    LPDIRECTDRAW p_ddobject;
+
+    msg_Dbg( p_vout, "DirectXInitDDraw" );
+
+    /* Load direct draw DLL */
+    p_vout->p_sys->hddraw_dll = LoadLibrary(_T("DDRAW.DLL"));
+    if( p_vout->p_sys->hddraw_dll == NULL )
+    {
+        msg_Warn( p_vout, "DirectXInitDDraw failed loading ddraw.dll" );
+        goto error;
+    }
+
+    OurDirectDrawCreate =
+      (void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
+                              _T("DirectDrawCreate") );
+    if( OurDirectDrawCreate == NULL )
+    {
+        msg_Err( p_vout, "DirectXInitDDraw failed GetProcAddress" );
+        goto error;
+    }
+
+    OurDirectDrawEnumerateEx =
+      (void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
+#ifndef UNICODE
+                              "DirectDrawEnumerateExA" );
+#else
+                              _T("DirectDrawEnumerateExW") );
+#endif
+
+    if( OurDirectDrawEnumerateEx && p_vout->p_sys->MonitorFromWindow )
+    {
+        vlc_value_t device;
+
+        var_Get( p_vout, "directx-device", &device );
+        if( device.psz_string )
+        {
+            msg_Dbg( p_vout, "directx-device: %s", device.psz_string );
+            free( device.psz_string );
+        }
+
+        p_vout->p_sys->hmonitor =
+            p_vout->p_sys->MonitorFromWindow( p_vout->p_sys->hwnd,
+                                              MONITOR_DEFAULTTONEAREST );
+
+        /* Enumerate displays */
+        OurDirectDrawEnumerateEx( DirectXEnumCallback, p_vout,
+                                  DDENUM_ATTACHEDSECONDARYDEVICES );
+    }
+
+    /* Initialize DirectDraw now */
+    dxresult = OurDirectDrawCreate( p_vout->p_sys->p_display_driver,
+                                    &p_ddobject, NULL );
+    if( dxresult != DD_OK )
+    {
+        msg_Err( p_vout, "DirectXInitDDraw cannot initialize DDraw" );
+        goto error;
+    }
+
+    /* Get the IDirectDraw2 interface */
+    dxresult = IDirectDraw_QueryInterface( p_ddobject, &IID_IDirectDraw2,
+                                        (LPVOID *)&p_vout->p_sys->p_ddobject );
+    /* Release the unused interface */
+    IDirectDraw_Release( p_ddobject );
+    if( dxresult != DD_OK )
+    {
+        msg_Err( p_vout, "cannot get IDirectDraw2 interface" );
+        goto error;
+    }
+
+    /* Set DirectDraw Cooperative level, ie what control we want over Windows
+     * display */
+    dxresult = IDirectDraw2_SetCooperativeLevel( p_vout->p_sys->p_ddobject,
+                                                 NULL, DDSCL_NORMAL );
+    if( dxresult != DD_OK )
+    {
+        msg_Err( p_vout, "cannot set direct draw cooperative level" );
+        goto error;
+    }
+
+    /* Get the size of the current display device */
+    if( p_vout->p_sys->hmonitor && p_vout->p_sys->GetMonitorInfo )
+    {
+        MONITORINFO monitor_info;
+        monitor_info.cbSize = sizeof( MONITORINFO );
+        p_vout->p_sys->GetMonitorInfo( p_vout->p_sys->hmonitor,
+                                       &monitor_info );
+        p_vout->p_sys->rect_display = monitor_info.rcMonitor;
+    }
+    else
+    {
+        p_vout->p_sys->rect_display.left = 0;
+        p_vout->p_sys->rect_display.top = 0;
+        p_vout->p_sys->rect_display.right  = GetSystemMetrics(SM_CXSCREEN);
+        p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
+    }
+
+    msg_Dbg( p_vout, "screen dimensions (%lix%li,%lix%li)",
+             p_vout->p_sys->rect_display.left,
+             p_vout->p_sys->rect_display.top,
+             p_vout->p_sys->rect_display.right,
+             p_vout->p_sys->rect_display.bottom );
+
+    /* Probe the capabilities of the hardware */
+    DirectXGetDDrawCaps( p_vout );
+
+    msg_Dbg( p_vout, "End DirectXInitDDraw" );
+    return VLC_SUCCESS;
+
+ error:
+    if( p_vout->p_sys->p_ddobject )
+        IDirectDraw2_Release( p_vout->p_sys->p_ddobject );
+    if( p_vout->p_sys->hddraw_dll )
+        FreeLibrary( p_vout->p_sys->hddraw_dll );
+    p_vout->p_sys->hddraw_dll = NULL;
+    p_vout->p_sys->p_ddobject = NULL;
+    return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * DirectXCreateDisplay: create the DirectDraw display.
+ *****************************************************************************
+ * Create and initialize display according to preferences specified in the vout
+ * thread fields.
+ *****************************************************************************/
+static int DirectXCreateDisplay( vout_thread_t *p_vout )
+{
+    HRESULT              dxresult;
+    DDSURFACEDESC        ddsd;
+    LPDIRECTDRAWSURFACE  p_display;
+
+    msg_Dbg( p_vout, "DirectXCreateDisplay" );
+
+    /* Now get the primary surface. This surface is what you actually see
+     * on your screen */
+    memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
+    ddsd.dwSize = sizeof(DDSURFACEDESC);
+    ddsd.dwFlags = DDSD_CAPS;
+    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+    dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
+                                           &ddsd, &p_display, NULL );
+    if( dxresult != DD_OK )
+    {
+        msg_Err( p_vout, "cannot get primary surface (error %li)", dxresult );
+        return VLC_EGENERIC;
+    }
+
+    dxresult = IDirectDrawSurface_QueryInterface( p_display,
+                                         &IID_IDirectDrawSurface2,
+                                         (LPVOID *)&p_vout->p_sys->p_display );
+    /* Release the old interface */
+    IDirectDrawSurface_Release( p_display );
+    if ( dxresult != DD_OK )
+    {
+        msg_Err( p_vout, "cannot query IDirectDrawSurface2 interface "
+                         "(error %li)", dxresult );
+        return VLC_EGENERIC;
+    }
+
+    /* The clipper will be used only in non-overlay mode */
+    DirectXCreateClipper( p_vout );
+
+    /* Make sure the colorkey will be painted */
+    p_vout->p_sys->i_colorkey = 1;
+    p_vout->p_sys->i_rgb_colorkey =
+        DirectXFindColorkey( p_vout, &p_vout->p_sys->i_colorkey );
+
+    E_(UpdateRects)( p_vout, VLC_TRUE );
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * 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;
+
+    msg_Dbg( p_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 )
+    {
+        msg_Warn( p_vout, "cannot create clipper (error %li)", dxresult );
+        goto error;
+    }
+
+    /* Associate the clipper to the window */
+    dxresult = IDirectDrawClipper_SetHWnd( p_vout->p_sys->p_clipper, 0,
+                                           p_vout->p_sys->hvideownd );
+    if( dxresult != DD_OK )
+    {
+        msg_Warn( p_vout, "cannot attach clipper to window (error %li)",
+                          dxresult );
+        goto error;
+    }
+
+    /* 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 )
+    {
+        msg_Warn( p_vout, "cannot attach clipper to surface (error %li)",
+                          dxresult );
+        goto error;
+    }
+
+    return VLC_SUCCESS;
+
+ error:
+    if( p_vout->p_sys->p_clipper )
+    {
+        IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
+    }
+    p_vout->p_sys->p_clipper = NULL;
+    return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * DirectXCreateSurface: create an YUV overlay or RGB surface for the video.
+ *****************************************************************************
+ * The best method of display is with an YUV overlay because the YUV->RGB
+ * conversion is done in hardware.
+ * You can also create a plain RGB surface.
+ * ( Maybe we could also try an RGB overlay surface, which could have hardware
+ * scaling and which would also be faster in window mode because you don't
+ * need to do any blitting to the main display...)
+ *****************************************************************************/
+static int DirectXCreateSurface( vout_thread_t *p_vout,
+                                 LPDIRECTDRAWSURFACE2 *pp_surface_final,
+                                 int i_chroma, int b_overlay,
+                                 int i_backbuffers )
+{
+    HRESULT dxresult;
+    LPDIRECTDRAWSURFACE p_surface;
+    DDSURFACEDESC ddsd;
+
+    /* Create the video surface */
+    if( b_overlay )
+    {
+        /* Now try to create the YUV overlay surface.
+         * This overlay will be displayed on top of the primary surface.
+         * A color key is used to determine whether or not the overlay will be
+         * displayed, ie the overlay will be displayed in place of the primary
+         * surface wherever the primary surface will have this color.
+         * The video window has been created with a background of this color so
+         * the overlay will be only displayed on top of this window */
+
+        memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
+        ddsd.dwSize = sizeof(DDSURFACEDESC);
+        ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+        ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
+        ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
+        ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
+        ddsd.dwFlags |= (i_backbuffers ? DDSD_BACKBUFFERCOUNT : 0);
+        ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
+        ddsd.ddsCaps.dwCaps |= (i_backbuffers ? DDSCAPS_COMPLEX | DDSCAPS_FLIP
+                                : 0 );
+        ddsd.dwHeight = p_vout->render.i_height;
+        ddsd.dwWidth = p_vout->render.i_width;
+        ddsd.dwBackBufferCount = i_backbuffers;
+
+        dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
+                                               &ddsd, &p_surface, NULL );
+        if( dxresult != DD_OK )
+        {
+            *pp_surface_final = NULL;
+            return VLC_EGENERIC;
+        }
+    }
+
+    if( !b_overlay )
+    {
+        vlc_bool_t b_rgb_surface =
+            ( i_chroma == VLC_FOURCC('R','G','B','2') )
+          || ( i_chroma == VLC_FOURCC('R','V','1','5') )
+           || ( i_chroma == VLC_FOURCC('R','V','1','6') )
+            || ( i_chroma == VLC_FOURCC('R','V','2','4') )
+             || ( i_chroma == VLC_FOURCC('R','V','3','2') );
+
+        memset( &ddsd, 0, sizeof( DDSURFACEDESC ) );
+        ddsd.dwSize = sizeof(DDSURFACEDESC);
+        ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+        ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS;
+        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+        ddsd.dwHeight = p_vout->render.i_height;
+        ddsd.dwWidth = p_vout->render.i_width;
+
+        if( p_vout->p_sys->b_use_sysmem )
+            ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
+        else
+            ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
+
+        if( !b_rgb_surface )
+        {
+            ddsd.dwFlags |= DDSD_PIXELFORMAT;
+            ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
+            ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
+        }
+
+        dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
+                                               &ddsd, &p_surface, NULL );
+        if( dxresult != DD_OK )
+        {
+            *pp_surface_final = NULL;
+            return VLC_EGENERIC;
+        }
+    }
+
+    /* Now that the surface is created, try to get a newer DirectX interface */
+    dxresult = IDirectDrawSurface_QueryInterface( p_surface,
+                                     &IID_IDirectDrawSurface2,
+                                     (LPVOID *)pp_surface_final );
+    IDirectDrawSurface_Release( p_surface );    /* Release the old interface */
+    if ( dxresult != DD_OK )
+    {
+        msg_Err( p_vout, "cannot query IDirectDrawSurface2 interface "
+                         "(error %li)", dxresult );
+        *pp_surface_final = NULL;
+        return VLC_EGENERIC;
+    }
+
+    if( b_overlay )
+    {
+        /* Check the overlay is useable as some graphics cards allow creating
+         * several overlays but only one can be used at one time. */
+        p_vout->p_sys->p_current_surface = *pp_surface_final;
+        if( DirectDrawUpdateOverlay( p_vout ) != VLC_SUCCESS )
+        {
+            IDirectDrawSurface2_Release( *pp_surface_final );
+            *pp_surface_final = NULL;
+            msg_Err( p_vout, "overlay unuseable (might already be in use)" );
+            return VLC_EGENERIC;
+        }
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * DirectDrawUpdateOverlay: Move or resize overlay surface on video display.
+ *****************************************************************************
+ * This function is used to move or resize an overlay surface on the screen.
+ * Ususally the overlay is moved by the user and thus, by a move or resize
+ * event (in Manage).
+ *****************************************************************************/
+int DirectDrawUpdateOverlay( vout_thread_t *p_vout )
+{
+    DDOVERLAYFX     ddofx;
+    DWORD           dwFlags;
+    HRESULT         dxresult;
+    RECT            rect_src = p_vout->p_sys->rect_src_clipped;
+    RECT            rect_dest = p_vout->p_sys->rect_dest_clipped;
+
+    if( !p_vout->p_sys->b_using_overlay ) return VLC_EGENERIC;
+
+    if( p_vout->p_sys->b_wallpaper )
+    {
+        int i_x, i_y, i_width, i_height;
+
+        rect_src.left = p_vout->fmt_out.i_x_offset;
+        rect_src.top = p_vout->fmt_out.i_y_offset;
+        rect_src.right = rect_src.left + p_vout->fmt_out.i_visible_width;
+        rect_src.bottom = rect_src.top + p_vout->fmt_out.i_visible_height;
+
+        rect_dest = p_vout->p_sys->rect_display;
+        vout_PlacePicture( p_vout, rect_dest.right, rect_dest.bottom,
+                           &i_x, &i_y, &i_width, &i_height );
+
+        rect_dest.left += i_x;
+        rect_dest.right = rect_dest.left + i_width;
+        rect_dest.top += i_y;
+        rect_dest.bottom = rect_dest.top + i_height;
+    }
+
+    vlc_mutex_lock( &p_vout->p_sys->lock );
+    if( p_vout->p_sys->p_current_surface == NULL )
+    {
+        vlc_mutex_unlock( &p_vout->p_sys->lock );
+        return VLC_EGENERIC;
+    }
+
+    /* The new window dimensions should already have been computed by the
+     * caller of this function */
+
+    /* Position and show the overlay */
+    memset(&ddofx, 0, sizeof(DDOVERLAYFX));
+    ddofx.dwSize = sizeof(DDOVERLAYFX);
+    ddofx.dckDestColorkey.dwColorSpaceLowValue = p_vout->p_sys->i_colorkey;
+    ddofx.dckDestColorkey.dwColorSpaceHighValue = p_vout->p_sys->i_colorkey;
+
+    dwFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
+
+    dxresult = IDirectDrawSurface2_UpdateOverlay(
+                   p_vout->p_sys->p_current_surface,
+                   &rect_src, p_vout->p_sys->p_display, &rect_dest,
+                   dwFlags, &ddofx );
+
+    vlc_mutex_unlock( &p_vout->p_sys->lock );
+
+    if(dxresult != DD_OK)
+    {
+        msg_Warn( p_vout, "DirectDrawUpdateOverlay cannot move/resize overlay" );
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * DirectXCloseDDraw: Release the DDraw object allocated by DirectXInitDDraw
+ *****************************************************************************
+ * This function returns all resources allocated by DirectXInitDDraw.
+ *****************************************************************************/
+static void DirectXCloseDDraw( vout_thread_t *p_vout )
+{
+    msg_Dbg( p_vout, "DirectXCloseDDraw" );
+    if( p_vout->p_sys->p_ddobject != NULL )
+    {
+        IDirectDraw2_Release(p_vout->p_sys->p_ddobject);
+        p_vout->p_sys->p_ddobject = NULL;
+    }
+
+    if( p_vout->p_sys->hddraw_dll != NULL )
+    {
+        FreeLibrary( p_vout->p_sys->hddraw_dll );
+        p_vout->p_sys->hddraw_dll = NULL;
+    }
+
+    if( p_vout->p_sys->p_display_driver != NULL )
+    {
+        free( p_vout->p_sys->p_display_driver );
+        p_vout->p_sys->p_display_driver = NULL;
+    }
+
+    p_vout->p_sys->hmonitor = NULL;
+}
+
+/*****************************************************************************
+ * DirectXCloseDisplay: close and reset the DirectX display device
+ *****************************************************************************
+ * This function returns all resources allocated by DirectXCreateDisplay.
+ *****************************************************************************/
+static void DirectXCloseDisplay( vout_thread_t *p_vout )
+{
+    msg_Dbg( p_vout, "DirectXCloseDisplay" );
+
+    if( p_vout->p_sys->p_clipper != NULL )
+    {
+        msg_Dbg( p_vout, "DirectXCloseDisplay clipper" );
+        IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
+        p_vout->p_sys->p_clipper = NULL;
+    }
+
+    if( p_vout->p_sys->p_display != NULL )
+    {
+        msg_Dbg( p_vout, "DirectXCloseDisplay display" );
+        IDirectDrawSurface2_Release( p_vout->p_sys->p_display );
+        p_vout->p_sys->p_display = NULL;
+    }
+}
+
+/*****************************************************************************
+ * DirectXCloseSurface: close the YUV overlay or RGB surface.
+ *****************************************************************************
+ * This function returns all resources allocated for the surface.
+ *****************************************************************************/
+static void DirectXCloseSurface( vout_thread_t *p_vout,
+                                 LPDIRECTDRAWSURFACE2 p_surface )
+{
+    msg_Dbg( p_vout, "DirectXCloseSurface" );
+    if( p_surface != NULL )
+    {
+        IDirectDrawSurface2_Release( p_surface );
+    }
+}
+
+/*****************************************************************************
+ * 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;
+    int i_ret = VLC_SUCCESS;
+    LPDIRECTDRAWSURFACE2 p_surface;
+
+    msg_Dbg( p_vout, "NewPictureVec overlay:%s chroma:%.4s",
+             p_vout->p_sys->b_using_overlay ? "yes" : "no",
+             (char *)&p_vout->output.i_chroma );
+
+    I_OUTPUTPICTURES = 0;
+
+    /* First we try to use an YUV overlay surface.
+     * The overlay surface that we create won't be used to decode directly
+     * into it because accessing video memory directly is way to slow (remember
+     * that pictures are decoded macroblock per macroblock). Instead the video
+     * will be decoded in picture buffers in system memory which will then be
+     * memcpy() to the overlay surface. */
+    if( p_vout->p_sys->b_using_overlay )
+    {
+        /* Triple buffering rocks! it doesn't have any processing overhead
+         * (you don't have to wait for the vsync) and provides for a very nice
+         * video quality (no tearing). */
+        if( p_vout->p_sys->b_3buf_overlay )
+            i_ret = DirectXCreateSurface( p_vout, &p_surface,
+                                          p_vout->output.i_chroma,
+                                          p_vout->p_sys->b_using_overlay,
+                                          2 /* number of backbuffers */ );
+
+        if( !p_vout->p_sys->b_3buf_overlay || i_ret != VLC_SUCCESS )
+        {
+            /* Try to reduce the number of backbuffers */
+            i_ret = DirectXCreateSurface( p_vout, &p_surface,
+                                          p_vout->output.i_chroma,
+                                          p_vout->p_sys->b_using_overlay,
+                                          0 /* number of backbuffers */ );
+        }
+
+        if( i_ret == VLC_SUCCESS )
+        {
+            DDSCAPS dds_caps;
+            picture_t front_pic;
+            picture_sys_t front_pic_sys;
+            front_pic.p_sys = &front_pic_sys;
+
+            /* Allocate internal structure */
+            p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
+            if( p_pic[0].p_sys == NULL )
+            {
+                DirectXCloseSurface( p_vout, p_surface );
+                return VLC_ENOMEM;
+            }
+
+            /* set front buffer */
+            p_pic[0].p_sys->p_front_surface = p_surface;
+
+            /* Get the back buffer */
+            memset( &dds_caps, 0, sizeof( DDSCAPS ) );
+            dds_caps.dwCaps = DDSCAPS_BACKBUFFER;
+            if( DD_OK != IDirectDrawSurface2_GetAttachedSurface(
+                                                p_surface, &dds_caps,
+                                                &p_pic[0].p_sys->p_surface ) )
+            {
+                msg_Warn( p_vout, "NewPictureVec could not get back buffer" );
+                /* front buffer is the same as back buffer */
+                p_pic[0].p_sys->p_surface = p_surface;
+            }
+
+
+            p_vout->p_sys->p_current_surface = front_pic.p_sys->p_surface =
+                p_pic[0].p_sys->p_front_surface;
+
+            /* Reset the front buffer memory */
+            if( DirectXLockSurface( p_vout, &front_pic ) == VLC_SUCCESS )
+            {
+                int i,j;
+                for( i = 0; i < front_pic.i_planes; i++ )
+                    for( j = 0; j < front_pic.p[i].i_visible_lines; j++)
+                        memset( front_pic.p[i].p_pixels + j *
+                                front_pic.p[i].i_pitch, 127,
+                                front_pic.p[i].i_visible_pitch );
+
+                DirectXUnlockSurface( p_vout, &front_pic );
+            }
+
+            DirectDrawUpdateOverlay( p_vout );
+            I_OUTPUTPICTURES = 1;
+            msg_Dbg( p_vout, "YUV overlay created successfully" );
+        }
+    }
+
+    /* As we can't have an overlay, we'll try to create a plain offscreen
+     * surface. This surface will reside in video memory because there's a
+     * better chance then that we'll be able to use some kind of hardware
+     * acceleration like rescaling, blitting or YUV->RGB conversions.
+     * We then only need to blit this surface onto the main display when we
+     * want to display it */
+    if( !p_vout->p_sys->b_using_overlay )
+    {
+        if( p_vout->p_sys->b_hw_yuv )
+        {
+            DWORD i_codes;
+            DWORD *pi_codes;
+            vlc_bool_t b_result = VLC_FALSE;
+
+            /* Check if the chroma is supported first. This is required
+             * because a few buggy drivers don't mind creating the surface
+             * even if they don't know about the chroma. */
+            if( IDirectDraw2_GetFourCCCodes( p_vout->p_sys->p_ddobject,
+                                             &i_codes, NULL ) == DD_OK )
+            {
+                pi_codes = malloc( i_codes * sizeof(DWORD) );
+                if( pi_codes && IDirectDraw2_GetFourCCCodes(
+                    p_vout->p_sys->p_ddobject, &i_codes, pi_codes ) == DD_OK )
+                {
+                    for( i = 0; i < (int)i_codes; i++ )
+                    {
+                        if( p_vout->output.i_chroma == pi_codes[i] )
+                        {
+                            b_result = VLC_TRUE;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if( b_result )
+                i_ret = DirectXCreateSurface( p_vout, &p_surface,
+                                              p_vout->output.i_chroma,
+                                              0 /* no overlay */,
+                                              0 /* no back buffers */ );
+            else
+                p_vout->p_sys->b_hw_yuv = VLC_FALSE;
+        }
+
+        if( i_ret || !p_vout->p_sys->b_hw_yuv )
+        {
+            /* Our last choice is to use a plain RGB surface */
+            DDPIXELFORMAT ddpfPixelFormat;
+
+            ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+            IDirectDrawSurface2_GetPixelFormat( p_vout->p_sys->p_display,
+                                                &ddpfPixelFormat );
+
+            if( ddpfPixelFormat.dwFlags & DDPF_RGB )
+            {
+                switch( ddpfPixelFormat.dwRGBBitCount )
+                {
+                case 8:
+                    p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
+                    p_vout->output.pf_setpalette = SetPalette;
+                    break;
+                case 15:
+                    p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
+                    break;
+                case 16:
+                    p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
+                    break;
+                case 24:
+                    p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
+                    break;
+                case 32:
+                    p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
+                    break;
+                default:
+                    msg_Err( p_vout, "unknown screen depth" );
+                    return VLC_EGENERIC;
+                }
+                p_vout->output.i_rmask = ddpfPixelFormat.dwRBitMask;
+                p_vout->output.i_gmask = ddpfPixelFormat.dwGBitMask;
+                p_vout->output.i_bmask = ddpfPixelFormat.dwBBitMask;
+            }
+
+            p_vout->p_sys->b_hw_yuv = 0;
+
+            i_ret = DirectXCreateSurface( p_vout, &p_surface,
+                                          p_vout->output.i_chroma,
+                                          0 /* no overlay */,
+                                          0 /* no back buffers */ );
+
+            if( i_ret && !p_vout->p_sys->b_use_sysmem )
+            {
+                /* Give it a last try with b_use_sysmem enabled */
+                p_vout->p_sys->b_use_sysmem = 1;
+
+                i_ret = DirectXCreateSurface( p_vout, &p_surface,
+                                              p_vout->output.i_chroma,
+                                              0 /* no overlay */,
+                                              0 /* no back buffers */ );
+            }
+        }
+
+        if( i_ret == VLC_SUCCESS )
+        {
+            /* 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 VLC_ENOMEM;
+            }
+
+            p_pic[0].p_sys->p_surface = p_pic[0].p_sys->p_front_surface
+                = p_surface;
+
+            I_OUTPUTPICTURES = 1;
+
+            msg_Dbg( p_vout, "created plain surface of chroma:%.4s",
+                     (char *)&p_vout->output.i_chroma );
+        }
+    }
+
+
+    /* 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;
+        p_pic[i].b_slow   = VLC_TRUE;
+        p_pic[i].pf_lock  = DirectXLockSurface;
+        p_pic[i].pf_unlock = DirectXUnlockSurface;
+        PP_OUTPUTPICTURE[i] = &p_pic[i];
+
+        if( DirectXLockSurface( p_vout, &p_pic[i] ) != VLC_SUCCESS )
+        {
+            /* AAARRGG */
+            FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
+            I_OUTPUTPICTURES = 0;
+            msg_Err( p_vout, "cannot lock surface" );
+            return VLC_EGENERIC;
+        }
+        DirectXUnlockSurface( p_vout, &p_pic[i] );
+    }
+
+    msg_Dbg( p_vout, "End NewPictureVec (%s)",
+             I_OUTPUTPICTURES ? "succeeded" : "failed" );
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * FreePicture: destroy a picture vector allocated with NewPictureVec
+ *****************************************************************************
+ *
+ *****************************************************************************/
+static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic,
+                            int i_num_pics )
+{
+    int i;
+
+    vlc_mutex_lock( &p_vout->p_sys->lock );
+    p_vout->p_sys->p_current_surface = 0;
+    vlc_mutex_unlock( &p_vout->p_sys->lock );
+
+    for( i = 0; i < i_num_pics; i++ )
+    {
+        DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_front_surface );
+
+        for( i = 0; i < i_num_pics; i++ )
+        {
+            free( p_pic[i].p_sys );
+        }
+    }
+}
+
+/*****************************************************************************
+ * 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 VLC_FOURCC('R','G','B','2'):
+        case VLC_FOURCC('R','V','1','5'):
+        case VLC_FOURCC('R','V','1','6'):
+        case VLC_FOURCC('R','V','2','4'):
+        case VLC_FOURCC('R','V','3','2'):
+            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_visible_lines = p_vout->output.i_height;
+            p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
+            switch( p_vout->output.i_chroma )
+            {
+                case VLC_FOURCC('R','G','B','2'):
+                    p_pic->p->i_pixel_pitch = 1;
+                    break;
+                case VLC_FOURCC('R','V','1','5'):
+                case VLC_FOURCC('R','V','1','6'):
+                    p_pic->p->i_pixel_pitch = 2;
+                    break;
+                case VLC_FOURCC('R','V','2','4'):
+                    p_pic->p->i_pixel_pitch = 3;
+                    break;
+                case VLC_FOURCC('R','V','3','2'):
+                    p_pic->p->i_pixel_pitch = 4;
+                    break;
+                default:
+                    return VLC_EGENERIC;
+            }
+            p_pic->p->i_visible_pitch = p_vout->output.i_width *
+              p_pic->p->i_pixel_pitch;
+            p_pic->i_planes = 1;
+            break;
+
+        case VLC_FOURCC('Y','V','1','2'):
+        case VLC_FOURCC('I','4','2','0'):
+
+            /* U and V inverted compared to I420
+             * Fixme: this should be handled by the vout core */
+            p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0');
+
+            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_visible_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_pitch = 1;
+            p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
+              p_pic->p[Y_PLANE].i_pixel_pitch;
+
+            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_visible_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_pitch = 1;
+            p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
+              p_pic->p[V_PLANE].i_pixel_pitch;
+
+            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_visible_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_pitch = 1;
+            p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
+              p_pic->p[U_PLANE].i_pixel_pitch;
+
+            p_pic->i_planes = 3;
+            break;
+
+        case VLC_FOURCC('I','Y','U','V'):
+
+            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_visible_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_pitch = 1;
+            p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
+              p_pic->p[Y_PLANE].i_pixel_pitch;
+
+            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_visible_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_pitch = 1;
+            p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
+              p_pic->p[U_PLANE].i_pixel_pitch;
+
+            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_visible_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_pitch = 1;
+            p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
+              p_pic->p[V_PLANE].i_pixel_pitch;
+
+            p_pic->i_planes = 3;
+            break;
+
+        case VLC_FOURCC('U','Y','V','Y'):
+        case VLC_FOURCC('Y','U','Y','2'):
+
+            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_visible_lines = p_vout->output.i_height;
+            p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
+            p_pic->p->i_pixel_pitch = 2;
+            p_pic->p->i_visible_pitch = p_vout->output.i_width *
+              p_pic->p->i_pixel_pitch;
+
+            p_pic->i_planes = 1;
+            break;
+
+        default:
+            /* Unknown chroma, tell the guy to get lost */
+            msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",
+                     p_vout->output.i_chroma,
+                     (char*)&p_vout->output.i_chroma );
+            return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * 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 )
+    {
+        msg_Warn( p_vout, "cannot get caps" );
+    }
+    else
+    {
+        vlc_bool_t bHasOverlay, bHasOverlayFourCC, bCanDeinterlace,
+             bHasColorKey, bCanStretch, bCanBltFourcc,
+             bAlignBoundarySrc, bAlignBoundaryDest,
+             bAlignSizeSrc, bAlignSizeDest;
+
+        /* Determine if the hardware supports overlay surfaces */
+        bHasOverlay = (ddcaps.dwCaps & DDCAPS_OVERLAY) ? 1 : 0;
+        /* Determine if the hardware supports overlay surfaces */
+        bHasOverlayFourCC = (ddcaps.dwCaps & DDCAPS_OVERLAYFOURCC) ? 1 : 0;
+        /* Determine if the hardware supports overlay deinterlacing */
+        bCanDeinterlace = (ddcaps.dwCaps & DDCAPS2_CANFLIPODDEVEN) ? 1 : 0;
+        /* Determine if the hardware supports colorkeying */
+        bHasColorKey = (ddcaps.dwCaps & DDCAPS_COLORKEY) ? 1 : 0;
+        /* Determine if the hardware s