- direct3d: new video output module using Direct3D 9 APIs
authorDamien Fouilleul <damienf@videolan.org>
Thu, 20 Jul 2006 13:21:16 +0000 (13:21 +0000)
committerDamien Fouilleul <damienf@videolan.org>
Thu, 20 Jul 2006 13:21:16 +0000 (13:21 +0000)
configure.ac
modules/video_output/directx/Modules.am
modules/video_output/directx/direct3d.c [new file with mode: 0755]
modules/video_output/directx/directx.c
modules/video_output/directx/events.c
modules/video_output/directx/glwin32.c
modules/video_output/directx/vout.h

index fc1a562..8b8c75c 100644 (file)
@@ -3908,11 +3908,15 @@ then
       AC_CHECK_HEADERS(ddraw.h,
       [ VLC_ADD_PLUGINS([vout_directx aout_directx])
         VLC_ADD_LDFLAGS([vout_directx],[-lgdi32])
-        dnl to be moved when dependance is removed
-        AC_CHECK_HEADERS(GL/gl.h, [
-            VLC_ADD_PLUGINS([glwin32])
-            VLC_ADD_LDFLAGS([glwin32],[-lopengl32 -lgdi32])
-        ]) ])
+      ])
+      AC_CHECK_HEADERS(GL/gl.h,
+      [ VLC_ADD_PLUGINS([glwin32])
+        VLC_ADD_LDFLAGS([glwin32],[-lopengl32 -lgdi32])
+      ])
+      AC_CHECK_HEADERS(d3d9.h,
+      [ VLC_ADD_PLUGINS([direct3d])
+        VLC_ADD_LDFLAGS([direct3d],[-ld3d9 -lgdi32])
+      ])
     else
       AC_MSG_CHECKING(for directX headers in ${with_directx})
       if test -f ${with_directx}/ddraw.h
index 1bc35e6..2db1b1e 100644 (file)
@@ -4,6 +4,12 @@ SOURCES_vout_directx = \
        events.c \
        $(NULL)
 
+SOURCES_direct3d = \
+       direct3d.c \
+       vout.h \
+       events.c \
+       $(NULL)
+
 SOURCES_glwin32 = \
        glwin32.c \
        vout.h \
diff --git a/modules/video_output/directx/direct3d.c b/modules/video_output/directx/direct3d.c
new file mode 100755 (executable)
index 0000000..a8f79da
--- /dev/null
@@ -0,0 +1,1499 @@
+/*****************************************************************************\r
+ * vout.c: Windows DirectX video output display method\r
+ *****************************************************************************\r
+ * Copyright (C) 2001-2006 the VideoLAN team\r
+ *\r
+ * Authors: Damien Fouilleul <damienf@videolan.org>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.\r
+ *****************************************************************************/\r
+\r
+/*****************************************************************************\r
+ * Preamble:\r
+ *\r
+ * This plugin will use YUV overlay if supported, using overlay will result in\r
+ * the best video quality (hardware filering when rescaling the picture)\r
+ * and the fastest display as it requires less processing.\r
+ *\r
+ * If YUV overlay is not supported this plugin will use RGB offscreen video\r
+ * surfaces that will be blitted onto the primary surface (display) to\r
+ * effectively display the pictures. This fallback method also enables us to\r
+ * display video in window mode.\r
+ *\r
+ *****************************************************************************/\r
+#include <errno.h>                                                 /* ENOMEM */\r
+#include <stdlib.h>                                                /* free() */\r
+#include <string.h>                                            /* strerror() */\r
+\r
+#include <vlc/vlc.h>\r
+#include <vlc/intf.h>\r
+#include <vlc/vout.h>\r
+\r
+#include <windows.h>\r
+#include <d3d9.h>\r
+\r
+#include "vout.h"\r
+\r
+/*****************************************************************************\r
+ * Local prototypes.\r
+ *****************************************************************************/\r
+static int  OpenVideo  ( vlc_object_t * );\r
+static void CloseVideo ( vlc_object_t * );\r
+\r
+static int  Init      ( vout_thread_t * );\r
+static void End       ( vout_thread_t * );\r
+static int  Manage    ( vout_thread_t * );\r
+static void Display   ( vout_thread_t *, picture_t * );\r
+\r
+static int Direct3DVoutCreate     ( vout_thread_t * );\r
+static void Direct3DVoutRelease   ( vout_thread_t * );\r
+\r
+static int  Direct3DVoutOpen      ( vout_thread_t * );\r
+static void Direct3DVoutClose     ( vout_thread_t * );\r
+\r
+static int Direct3DVoutResetDevice( vout_thread_t *, UINT , UINT );\r
+\r
+static int Direct3DVoutCreatePictures   ( vout_thread_t *, size_t );\r
+static void Direct3DVoutReleasePictures ( vout_thread_t * );\r
+\r
+static int Direct3DVoutLockSurface  ( vout_thread_t *, picture_t * );\r
+static int Direct3DVoutUnlockSurface( vout_thread_t *, picture_t * );\r
+\r
+static void Direct3DVoutRenderDefault   ( vout_thread_t *, picture_t * );\r
+\r
+static int Direct3DVoutCreateScene      ( vout_thread_t * );\r
+static void Direct3DVoutReleaseScene    ( vout_thread_t * );\r
+static void Direct3DVoutRenderScene     ( vout_thread_t *, picture_t * );\r
+\r
+/*****************************************************************************\r
+ * Module descriptor\r
+ *****************************************************************************/\r
+vlc_module_begin();\r
+    set_shortname( "Direct3D" );\r
+    set_category( CAT_VIDEO );\r
+    set_subcategory( SUBCAT_VIDEO_VOUT );\r
+    set_description( _("DirectX 3D video output") );\r
+    set_capability( "video output", 150 );\r
+    add_shortcut( "direct3d" );\r
+    set_callbacks( OpenVideo, CloseVideo );\r
+\r
+    /* FIXME: Hack to avoid unregistering our window class */\r
+    linked_with_a_crap_library_which_uses_atexit( );\r
+vlc_module_end();\r
+\r
+#if 0 /* FIXME */\r
+    /* check if we registered a window class because we need to\r
+     * unregister it */\r
+    WNDCLASS wndclass;\r
+    if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )\r
+        UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );\r
+#endif\r
+\r
+/*****************************************************************************\r
+ * CUSTOMVERTEX: \r
+ *****************************************************************************\r
+ *****************************************************************************/\r
+typedef struct \r
+{\r
+    FLOAT       x,y,z;      // vertex untransformed position \r
+    FLOAT       rhw;        // eye distance\r
+    D3DCOLOR    diffuse;    // diffuse color\r
+    FLOAT       tu, tv;     // texture relative coordinates\r
+} CUSTOMVERTEX;\r
+\r
+#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)\r
+\r
+/*****************************************************************************\r
+ * OpenVideo: allocate DirectX video thread output method\r
+ *****************************************************************************\r
+ * This function allocates and initialize the DirectX vout method.\r
+ *****************************************************************************/\r
+static int OpenVideo( vlc_object_t *p_this )\r
+{\r
+    vout_thread_t * p_vout = (vout_thread_t *)p_this;\r
+    vlc_value_t val;\r
+\r
+    /* Allocate structure */\r
+    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );\r
+    if( p_vout->p_sys == NULL )\r
+    {\r
+        msg_Err( p_vout, "out of memory" );\r
+        return VLC_ENOMEM;\r
+    }\r
+    memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );\r
+\r
+    if( VLC_SUCCESS != Direct3DVoutCreate( p_vout ) )\r
+    {\r
+        msg_Err( p_vout, "Direct3D could not be initialized !");\r
+        goto error;\r
+    }\r
+\r
+    /* Initialisations */\r
+    p_vout->pf_init = Init;\r
+    p_vout->pf_end = End;\r
+    p_vout->pf_manage = Manage;\r
+    p_vout->pf_render = Direct3DVoutRenderScene;\r
+    p_vout->pf_display = Display;\r
+\r
+    p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;\r
+    p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;\r
+    p_vout->p_sys->i_changes = 0;\r
+    p_vout->p_sys->b_wallpaper = 0;\r
+    vlc_mutex_init( p_vout, &p_vout->p_sys->lock );\r
+    SetRectEmpty( &p_vout->p_sys->rect_display );\r
+    SetRectEmpty( &p_vout->p_sys->rect_parent );\r
+\r
+    p_vout->p_sys->b_cursor_hidden = 0;\r
+    p_vout->p_sys->i_lastmoved = mdate();\r
+\r
+    /* Set main window's size */\r
+    p_vout->p_sys->i_window_width = p_vout->i_window_width;\r
+    p_vout->p_sys->i_window_height = p_vout->i_window_height;\r
+\r
+    /* Create the DirectXEventThread, this thread is created by us to isolate\r
+     * the Win32 PeekMessage function calls. We want to do this because\r
+     * Windows can stay blocked inside this call for a long time, and when\r
+     * this happens it thus blocks vlc's video_output thread.\r
+     * DirectXEventThread will take care of the creation of the video\r
+     * window (because PeekMessage has to be called from the same thread which\r
+     * created the window). */\r
+    msg_Dbg( p_vout, "creating DirectXEventThread" );\r
+    p_vout->p_sys->p_event =\r
+        vlc_object_create( p_vout, sizeof(event_thread_t) );\r
+    p_vout->p_sys->p_event->p_vout = p_vout;\r
+    if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread",\r
+                           E_(DirectXEventThread), 0, 1 ) )\r
+    {\r
+        msg_Err( p_vout, "cannot create DirectXEventThread" );\r
+        vlc_object_destroy( p_vout->p_sys->p_event );\r
+        p_vout->p_sys->p_event = NULL;\r
+        goto error;\r
+    }\r
+\r
+    if( p_vout->p_sys->p_event->b_error )\r
+    {\r
+        msg_Err( p_vout, "DirectXEventThread failed" );\r
+        goto error;\r
+    }\r
+\r
+    vlc_object_attach( p_vout->p_sys->p_event, p_vout );\r
+\r
+    msg_Dbg( p_vout, "DirectXEventThread running" );\r
+\r
+    /* Variable to indicate if the window should be on top of others */\r
+    /* Trigger a callback right now */\r
+    var_Get( p_vout, "video-on-top", &val );\r
+    var_Set( p_vout, "video-on-top", val );\r
+\r
+    /* disable screensaver by temporarily changing system settings */\r
+    p_vout->p_sys->i_spi_lowpowertimeout = 0;\r
+    p_vout->p_sys->i_spi_powerofftimeout = 0;\r
+    p_vout->p_sys->i_spi_screensavetimeout = 0;\r
+    var_Get( p_vout, "disable-screensaver", &val);\r
+    if( val.b_bool ) {\r
+        msg_Dbg(p_vout, "disabling screen saver");\r
+        SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT,\r
+            0, &(p_vout->p_sys->i_spi_lowpowertimeout), 0);\r
+        if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {\r
+            SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0);\r
+        }\r
+        SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0,\r
+            &(p_vout->p_sys->i_spi_powerofftimeout), 0);\r
+        if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {\r
+            SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, 0, NULL, 0);\r
+        }\r
+        SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0,\r
+            &(p_vout->p_sys->i_spi_screensavetimeout), 0);\r
+        if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {\r
+            SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 0, NULL, 0);\r
+        }\r
+    }\r
+    return VLC_SUCCESS;\r
+\r
+ error:\r
+    CloseVideo( VLC_OBJECT(p_vout) );\r
+    return VLC_EGENERIC;\r
+}\r
+\r
+/*****************************************************************************\r
+ * CloseVideo: destroy Sys video thread output method\r
+ *****************************************************************************\r
+ * Terminate an output method created by Create\r
+ *****************************************************************************/\r
+static void CloseVideo( vlc_object_t *p_this )\r
+{\r
+    vout_thread_t * p_vout = (vout_thread_t *)p_this;\r
+\r
+    Direct3DVoutRelease( p_vout );\r
+\r
+    if( p_vout->p_sys->p_event )\r
+    {\r
+        vlc_object_detach( p_vout->p_sys->p_event );\r
+\r
+        /* Kill DirectXEventThread */\r
+        p_vout->p_sys->p_event->b_die = VLC_TRUE;\r
+\r
+        /* we need to be sure DirectXEventThread won't stay stuck in\r
+         * GetMessage, so we send a fake message */\r
+        if( p_vout->p_sys->hwnd )\r
+        {\r
+            PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);\r
+        }\r
+\r
+        vlc_thread_join( p_vout->p_sys->p_event );\r
+        vlc_object_destroy( p_vout->p_sys->p_event );\r
+    }\r
+\r
+    vlc_mutex_destroy( &p_vout->p_sys->lock );\r
+\r
+    /* restore screensaver system settings */\r
+    if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {\r
+        SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT,\r
+            p_vout->p_sys->i_spi_lowpowertimeout, NULL, 0);\r
+    }\r
+    if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {\r
+        SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT,\r
+            p_vout->p_sys->i_spi_powerofftimeout, NULL, 0);\r
+    }\r
+    if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {\r
+        SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT,\r
+            p_vout->p_sys->i_spi_screensavetimeout, NULL, 0);\r
+    }\r
+\r
+    if( p_vout->p_sys )\r
+    {\r
+        free( p_vout->p_sys );\r
+        p_vout->p_sys = NULL;\r
+    }\r
+}\r
+\r
+/*****************************************************************************\r
+ * Init: initialize Direct3D video thread output method\r
+ *****************************************************************************/\r
+static int Init( vout_thread_t *p_vout )\r
+{\r
+    int i_ret;\r
+\r
+    /* Initialise Direct3D */\r
+    if( VLC_SUCCESS != Direct3DVoutOpen( p_vout ) )\r
+    {\r
+        msg_Err( p_vout, "cannot initialize Direct3D" );\r
+        return VLC_EGENERIC;\r
+    }\r
+\r
+    /* Initialize the output structure.\r
+     * Since Direct3D can do rescaling for us, stick to the default\r
+     * coordinates and aspect. */\r
+    p_vout->output.i_width  = p_vout->render.i_width;\r
+    p_vout->output.i_height = p_vout->render.i_height;\r
+    p_vout->output.i_aspect = p_vout->render.i_aspect;\r
+    p_vout->fmt_out = p_vout->fmt_in;\r
+    E_(DirectXUpdateRects)( p_vout, VLC_TRUE );\r
+\r
+    /*  create picture pool */\r
+    i_ret = Direct3DVoutCreatePictures(p_vout, 1);\r
+    if( VLC_SUCCESS != i_ret )\r
+    {\r
+        msg_Err(p_vout, "Direct3D picture pool initialization failed !");\r
+        return i_ret;\r
+    }\r
+\r
+    /* create scene */\r
+    i_ret = Direct3DVoutCreateScene(p_vout);\r
+    if( VLC_SUCCESS != i_ret )\r
+    {\r
+        msg_Err(p_vout, "Direct3D scene initialization failed !");\r
+        Direct3DVoutReleasePictures(p_vout);\r
+        return i_ret;\r
+    }\r
+\r
+    p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;\r
+    return VLC_SUCCESS;\r
+}\r
+\r
+/*****************************************************************************\r
+ * End: terminate Sys video thread output method\r
+ *****************************************************************************\r
+ * Terminate an output method created by Create.\r
+ * It is called at the end of the thread.\r
+ *****************************************************************************/\r
+static void End( vout_thread_t *p_vout )\r
+{\r
+    Direct3DVoutReleaseScene(p_vout);\r
+    Direct3DVoutReleasePictures(p_vout);\r
+    Direct3DVoutClose( p_vout );\r
+}\r
+\r
+/*****************************************************************************\r
+ * Manage: handle Sys events\r
+ *****************************************************************************\r
+ * This function should be called regularly by the video output thread.\r
+ * It returns a non null value if an error occurred.\r
+ *****************************************************************************/\r
+static int Manage( vout_thread_t *p_vout )\r
+{\r
+    WINDOWPLACEMENT window_placement;\r
+\r
+    /* If we do not control our window, we check for geometry changes\r
+     * ourselves because the parent might not send us its events. */\r
+    vlc_mutex_lock( &p_vout->p_sys->lock );\r
+    if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )\r
+    {\r
+        RECT rect_parent;\r
+        POINT point;\r
+\r
+        vlc_mutex_unlock( &p_vout->p_sys->lock );\r
+\r
+        GetClientRect( p_vout->p_sys->hparent, &rect_parent );\r
+        point.x = point.y = 0;\r
+        ClientToScreen( p_vout->p_sys->hparent, &point );\r
+        OffsetRect( &rect_parent, point.x, point.y );\r
+\r
+        if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )\r
+        {\r
+            p_vout->p_sys->rect_parent = rect_parent;\r
+\r
+            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,\r
+                          rect_parent.right - rect_parent.left,\r
+                          rect_parent.bottom - rect_parent.top, 0 );\r
+        }\r
+    }\r
+    else\r
+    {\r
+        vlc_mutex_unlock( &p_vout->p_sys->lock );\r
+    }\r
+\r
+    /*\r
+     * Position Change\r
+     */\r
+    if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE )\r
+    {\r
+#if 0 /* need that when bicubic filter is available */\r
+        RECT rect;\r
+        UINT width, height;\r
+\r
+        GetClientRect(p_vout->p_sys->hvideownd, &rect);\r
+        width  = rect.right-rect.left;\r
+        height = rect.bottom-rect.top;\r
+\r
+        if( (width != p_vout->p_sys->d3dpp.BackBufferWidth)\r
+         || (height != p_vout->p_sys->d3dpp.BackBufferHeight) )\r
+        {\r
+            msg_Dbg(p_vout, "resizing device back buffers to (%lux%lu)", width, height);\r
+            // need to reset D3D device to resize back buffer\r
+            if( VLC_SUCCESS != Direct3DVoutResetDevice(p_vout, width, height) )\r
+                return VLC_EGENERIC;\r
+        }\r
+#endif\r
+        p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;\r
+    }\r
+\r
+    /* Check for cropping / aspect changes */\r
+    if( p_vout->i_changes & VOUT_CROP_CHANGE ||\r
+        p_vout->i_changes & VOUT_ASPECT_CHANGE )\r
+    {\r
+        p_vout->i_changes &= ~VOUT_CROP_CHANGE;\r
+        p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;\r
+\r
+        p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset;\r
+        p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset;\r
+        p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width;\r
+        p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height;\r
+        p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect;\r
+        p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;\r
+        p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;\r
+        p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;\r
+        E_(DirectXUpdateRects)( p_vout, VLC_TRUE );\r
+    }\r
+\r
+    /* We used to call the Win32 PeekMessage function here to read the window\r
+     * messages. But since window can stay blocked into this function for a\r
+     * long time (for example when you move your window on the screen), I\r
+     * decided to isolate PeekMessage in another thread. */\r
+\r
+    /*\r
+     * Fullscreen change\r
+     */\r
+    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE\r
+        || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )\r
+    {\r
+        vlc_value_t val;\r
+        HWND hwnd = (p_vout->p_sys->hparent && p_vout->p_sys->hfswnd) ?\r
+            p_vout->p_sys->hfswnd : p_vout->p_sys->hwnd;\r
+\r
+        p_vout->b_fullscreen = ! p_vout->b_fullscreen;\r
+\r
+        /* We need to switch between Maximized and Normal sized window */\r
+        window_placement.length = sizeof(WINDOWPLACEMENT);\r
+        GetWindowPlacement( hwnd, &window_placement );\r
+        if( p_vout->b_fullscreen )\r
+        {\r
+            /* Change window style, no borders and no title bar */\r
+            int i_style = WS_CLIPCHILDREN | WS_VISIBLE;\r
+            SetWindowLong( hwnd, GWL_STYLE, i_style );\r
+\r
+            if( p_vout->p_sys->hparent )\r
+            {\r
+                /* Retrieve current window position so fullscreen will happen\r
+                 * on the right screen */\r
+                POINT point = {0,0};\r
+                RECT rect;\r
+                ClientToScreen( p_vout->p_sys->hwnd, &point );\r
+                GetClientRect( p_vout->p_sys->hwnd, &rect );\r
+                SetWindowPos( hwnd, 0, point.x, point.y,\r
+                              rect.right, rect.bottom,\r
+                              SWP_NOZORDER|SWP_FRAMECHANGED );\r
+                GetWindowPlacement( hwnd, &window_placement );\r
+            }\r
+\r
+            /* Maximize window */\r
+            window_placement.showCmd = SW_SHOWMAXIMIZED;\r
+            SetWindowPlacement( hwnd, &window_placement );\r
+            SetWindowPos( hwnd, 0, 0, 0, 0, 0,\r
+                          SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);\r
+\r
+            if( p_vout->p_sys->hparent )\r
+            {\r
+                RECT rect;\r
+                GetClientRect( hwnd, &rect );\r
+                SetParent( p_vout->p_sys->hwnd, hwnd );\r
+                SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,\r
+                              rect.right, rect.bottom,\r
+                              SWP_NOZORDER|SWP_FRAMECHANGED );\r
+            }\r
+\r
+            SetForegroundWindow( hwnd );\r
+        }\r
+        else\r
+        {\r
+            /* Change window style, no borders and no title bar */\r
+            SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style );\r
+\r
+            /* Normal window */\r
+            window_placement.showCmd = SW_SHOWNORMAL;\r
+            SetWindowPlacement( hwnd, &window_placement );\r
+            SetWindowPos( hwnd, 0, 0, 0, 0, 0,\r
+                          SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);\r
+\r
+            if( p_vout->p_sys->hparent )\r
+            {\r
+                RECT rect;\r
+                GetClientRect( p_vout->p_sys->hparent, &rect );\r
+                SetParent( p_vout->p_sys->hwnd, p_vout->p_sys->hparent );\r
+                SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,\r
+                              rect.right, rect.bottom,\r
+                              SWP_NOZORDER|SWP_FRAMECHANGED );\r
+\r
+                ShowWindow( hwnd, SW_HIDE );\r
+                SetForegroundWindow( p_vout->p_sys->hparent );\r
+            }\r
+\r
+            /* Make sure the mouse cursor is displayed */\r
+            PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 );\r
+        }\r
+\r
+        /* Update the object variable and trigger callback */\r
+        val.b_bool = p_vout->b_fullscreen;\r
+        var_Set( p_vout, "fullscreen", val );\r
+\r
+        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;\r
+        p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;\r
+    }\r
+\r
+    /*\r
+     * Pointer change\r
+     */\r
+    if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&\r
+        (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 )\r
+    {\r
+        POINT point;\r
+        HWND hwnd;\r
+\r
+        /* Hide the cursor only if it is inside our window */\r
+        GetCursorPos( &point );\r
+        hwnd = WindowFromPoint(point);\r
+        if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )\r
+        {\r
+            PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );\r
+        }\r
+        else\r
+        {\r
+            p_vout->p_sys->i_lastmoved = mdate();\r
+        }\r
+    }\r
+\r
+    /*\r
+     * "Always on top" status change\r
+     */\r
+    if( p_vout->p_sys->b_on_top_change )\r
+    {\r
+        vlc_value_t val;\r
+        HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );\r
+\r
+        var_Get( p_vout, "video-on-top", &val );\r
+\r
+        /* Set the window on top if necessary */\r
+        if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )\r
+                           & WS_EX_TOPMOST ) )\r
+        {\r
+            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,\r
+                           MF_BYCOMMAND | MFS_CHECKED );\r
+            SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,\r
+                          SWP_NOSIZE | SWP_NOMOVE );\r
+        }\r
+        else\r
+        /* The window shouldn't be on top */\r
+        if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )\r
+                           & WS_EX_TOPMOST ) )\r
+        {\r
+            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,\r
+                           MF_BYCOMMAND | MFS_UNCHECKED );\r
+            SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,\r
+                          SWP_NOSIZE | SWP_NOMOVE );\r
+        }\r
+\r
+        p_vout->p_sys->b_on_top_change = VLC_FALSE;\r
+    }\r
+\r
+    /* Check if the event thread is still running */\r
+    if( p_vout->p_sys->p_event->b_die )\r
+    {\r
+        return VLC_EGENERIC; /* exit */\r
+    }\r
+\r
+    return VLC_SUCCESS;\r
+}\r
+\r
+/*****************************************************************************\r
+ * Display: displays previously rendered output\r
+ *****************************************************************************\r
+ * This function sends the currently rendered image to the display, wait until\r
+ * it is displayed and switch the two rendering buffers, preparing next frame.\r
+ *****************************************************************************/\r
+static void Display( vout_thread_t *p_vout, picture_t *p_pic )\r
+{\r
+    LPDIRECT3DDEVICE9       p_d3ddev = p_vout->p_sys->p_d3ddev;\r
+    // Present the backbuffer contents to the display\r
+    HRESULT hr = IDirect3DDevice9_Present(p_d3ddev, NULL, NULL, NULL, NULL);\r
+    if( FAILED(hr) )\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+}\r
+\r
+/*****************************************************************************\r
+ * DirectD3DVoutCreate: Initialize and instance of Direct3D9 \r
+ *****************************************************************************\r
+ * This function initialize Direct3D and analyze available resources from\r
+ * default adapter.\r
+ *****************************************************************************/\r
+static int Direct3DVoutCreate( vout_thread_t *p_vout )\r
+{\r
+    HRESULT hr;\r
+    LPDIRECT3D9 p_d3dobj;\r
+    D3DCAPS9 d3dCaps;\r
+\r
+    /* Create the D3D object. */\r
+    p_d3dobj = Direct3DCreate9( D3D_SDK_VERSION );\r
+    if( NULL == p_d3dobj )\r
+    {\r
+       msg_Err( p_vout, "Could not create Direct3D9 instance.");\r
+       return VLC_EGENERIC;\r
+    }\r
+    p_vout->p_sys->p_d3dobj = p_d3dobj;\r
+\r
+    /*\r
+    ** Get device capabilities\r
+    */\r
+    ZeroMemory(&d3dCaps, sizeof(d3dCaps));\r
+    hr = IDirect3D9_GetDeviceCaps(p_d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps);\r
+    if( FAILED(hr) )\r
+    {\r
+       msg_Err( p_vout, "Could not read adapter capabilities. (hr=0x%lX)", hr);\r
+       return VLC_EGENERIC;\r
+    }\r
+    /* TODO: need to test device capabilities and select the right render function */\r
+\r
+    return VLC_SUCCESS;\r
+}\r
+\r
+/*****************************************************************************\r
+ * DirectD3DVoutRelease: release an instance of Direct3D9\r
+ *****************************************************************************/\r
+\r
+static void Direct3DVoutRelease( vout_thread_t *p_vout )\r
+{\r
+    if( p_vout->p_sys->p_d3dobj )\r
+    {\r
+       IDirect3D9_Release(p_vout->p_sys->p_d3dobj);\r
+       p_vout->p_sys->p_d3dobj = NULL;\r
+    }\r
+}\r
+       \r
+/*****************************************************************************\r
+ * DirectD3DVoutOpen: Takes care of all the Direct3D9 initialisations\r
+ *****************************************************************************\r
+ * This function creates Direct3D device\r
+ * this must be called from the vout thread for performance reason, as\r
+ * all Direct3D Device APIs are used in a non multithread safe environment\r
+ *****************************************************************************/\r
+static int Direct3DVoutOpen( vout_thread_t *p_vout )\r
+{\r
+    HRESULT hr = S_OK;\r
+    LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj;;\r
+    D3DDISPLAYMODE d3ddm;\r
+    LPDIRECT3DDEVICE9 p_d3ddev;\r
+\r
+    /*\r
+    ** Get the current desktop display mode, so we can set up a back\r
+    ** buffer of the same format\r
+    */\r
+    hr = IDirect3D9_GetAdapterDisplayMode(p_d3dobj, D3DADAPTER_DEFAULT, &d3ddm );\r
+    if( FAILED(hr))\r
+    {\r
+       msg_Err( p_vout, "Could not read adapter display mode. (hr=0x%lX)", hr);\r
+       return VLC_EGENERIC;\r
+    }\r
+\r
+    /* Set up the structure used to create the D3DDevice. */\r
+    ZeroMemory( &p_vout->p_sys->d3dpp, sizeof(D3DPRESENT_PARAMETERS) );\r
+    p_vout->p_sys->d3dpp.Windowed               = TRUE;\r
+    p_vout->p_sys->d3dpp.hDeviceWindow          = p_vout->p_sys->hvideownd;\r
+    p_vout->p_sys->d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;\r
+    p_vout->p_sys->d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT;\r
+    p_vout->p_sys->d3dpp.BackBufferFormat       = d3ddm.Format;\r
+    p_vout->p_sys->d3dpp.BackBufferCount        = 1;\r
+    p_vout->p_sys->d3dpp.EnableAutoDepthStencil = TRUE;\r
+    p_vout->p_sys->d3dpp.AutoDepthStencilFormat = D3DFMT_D16;\r
+\r
+    // Create the D3DDevice\r
+    hr = IDirect3D9_CreateDevice(p_d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL,\r
+                D3DCREATE_SOFTWARE_VERTEXPROCESSING, &(p_vout->p_sys->d3dpp), &p_d3ddev );\r
+    if( FAILED(hr) )                                      \r
+    {\r
+       msg_Err(p_vout, "Could not create the D3D device! (hr=0x%lX)", hr);\r
+       return VLC_EGENERIC;\r
+    }\r
+    p_vout->p_sys->p_d3ddev = p_d3ddev;\r
+\r
+    msg_Dbg( p_vout, "Direct3D device adapter successfully initialized" );\r
+    return VLC_SUCCESS;\r
+}\r
+\r
+/*****************************************************************************\r
+ * DirectD3DClose: release the Direct3D9 device \r
+ *****************************************************************************/\r
+static void Direct3DVoutClose( vout_thread_t *p_vout )\r
+{\r
+    if( p_vout->p_sys->p_d3ddev )\r
+    {\r
+       IDirect3DDevice9_Release(p_vout->p_sys->p_d3ddev);\r
+       p_vout->p_sys->p_d3ddev = NULL;\r
+    }\r
+       \r
+    p_vout->p_sys->hmonitor = NULL;\r
+}\r
+\r
+/*****************************************************************************\r
+ * DirectD3DClose: reset the Direct3D9 device \r
+ *****************************************************************************\r
+ * All resources must be deallocated before the reset occur, they will be\r
+ * realllocated once the reset has been performed successfully\r
+ *****************************************************************************/\r
+static int Direct3DVoutResetDevice( vout_thread_t *p_vout, UINT i_width, UINT i_height )\r
+{\r
+    LPDIRECT3DDEVICE9       p_d3ddev = p_vout->p_sys->p_d3ddev;\r
+    D3DPRESENT_PARAMETERS   d3dpp;\r
+    HRESULT hr;\r
+\r
+    memcpy(&d3dpp, &(p_vout->p_sys->d3dpp), sizeof(d3dpp));\r
+    if( i_width )\r
+        d3dpp.BackBufferWidth  = i_width;\r
+    if( i_height )\r
+        d3dpp.BackBufferHeight = i_height;\r
+\r
+    // release all D3D objects\r
+    Direct3DVoutReleaseScene( p_vout );\r
+    Direct3DVoutReleasePictures( p_vout );\r
+\r
+    hr = IDirect3DDevice9_Reset(p_d3ddev, &d3dpp);\r
+    if( SUCCEEDED(hr) )\r
+    {\r
+        // re-create them\r
+        if( (VLC_SUCCESS == Direct3DVoutCreatePictures(p_vout, 1))\r
+         && (VLC_SUCCESS == Direct3DVoutCreateScene(p_vout)) )\r
+        {\r
+            p_vout->p_sys->d3dpp.BackBufferWidth  = i_width;\r
+            p_vout->p_sys->d3dpp.BackBufferHeight = i_height;\r
+            return VLC_SUCCESS;\r
+        }\r
+        return VLC_EGENERIC;\r
+    }\r
+    else {\r
+        msg_Err(p_vout, "%s failed ! (hr=%08lX)", __FUNCTION__, hr);\r
+        return VLC_EGENERIC;\r
+    }\r
+    return VLC_SUCCESS;\r
+}\r
+\r
+static D3DFORMAT Direct3DVoutSelectFormat( vout_thread_t *p_vout, D3DFORMAT target,\r
+    const D3DFORMAT *formats, size_t count)\r
+{\r
+    LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj;\r
+    size_t c;\r
+\r
+    for( c=0; c<count; ++c )\r
+    {\r
+        HRESULT hr;\r
+        D3DFORMAT format = formats[c];\r
+        hr = IDirect3D9_CheckDeviceFormatConversion(p_d3dobj,\r
+                D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,\r
+                format, target);\r
+        if( SUCCEEDED(hr) )\r
+        {\r
+            // found a compatible format\r
+            switch( format )\r
+            {\r
+                case D3DFMT_UYVY:\r
+                    msg_Dbg( p_vout, "selected surface pixel format is UYVY");\r
+                    break;\r
+                case D3DFMT_YUY2:\r
+                    msg_Dbg( p_vout, "selected surface pixel format is YUY2");\r
+                    break;\r
+                case D3DFMT_X8R8G8B8:\r
+                    msg_Dbg( p_vout, "selected surface pixel format is X8R8G8B8");\r
+                    break;\r
+                case D3DFMT_A8R8G8B8:\r
+                    msg_Dbg( p_vout, "selected surface pixel format is A8R8G8B8");\r
+                    break;\r
+                case D3DFMT_R8G8B8:\r
+                    msg_Dbg( p_vout, "selected surface pixel format is R8G8B8");\r
+                    break;\r
+                case D3DFMT_R5G6B5:\r
+                    msg_Dbg( p_vout, "selected surface pixel format is R5G6B5");\r
+                    break;\r
+                case D3DFMT_X1R5G5B5:\r
+                    msg_Dbg( p_vout, "selected surface pixel format is X1R5G5B5");\r
+                    break;\r
+                default:\r
+                    msg_Dbg( p_vout, "selected surface pixel format is 0x%0X", format);\r
+                    break;\r
+            }\r
+            return format;\r
+        }\r
+        else if( D3DERR_NOTAVAILABLE != hr )\r
+        {\r
+            msg_Err( p_vout, "Could not query adapter supported formats. (hr=0x%lX)", hr);\r
+            break;\r
+        }\r
+    }\r
+    return D3DFMT_UNKNOWN;\r
+}\r
+\r
+D3DFORMAT Direct3DVoutFindFormat(vout_thread_t *p_vout, int i_chroma, D3DFORMAT target)\r
+{\r
+    switch( i_chroma )\r
+    {\r
+        case VLC_FOURCC('U','Y','V','Y'):\r
+        case VLC_FOURCC('U','Y','N','V'):\r
+        case VLC_FOURCC('Y','4','2','2'):\r
+        {\r
+            static const D3DFORMAT formats[] =\r
+                { D3DFMT_UYVY, D3DFMT_YUY2, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };\r
+            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));\r
+        }\r
+        case VLC_FOURCC('I','4','2','0'):\r
+        case VLC_FOURCC('Y','V','1','2'):\r
+        {\r
+            /* typically 3D textures don't support planar format\r
+            ** fallback to packed version and use pixel\r
+            ** shader or CPU for the conversion\r
+            */\r
+            static const D3DFORMAT formats[] = \r
+                { D3DFMT_YUY2, D3DFMT_UYVY, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };\r
+            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));\r
+        }\r
+        case VLC_FOURCC('Y','U','Y','2'):\r
+        case VLC_FOURCC('Y','U','N','V'):\r
+        {\r
+            static const D3DFORMAT formats[] = \r
+                { D3DFMT_YUY2, D3DFMT_UYVY, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };\r
+            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));\r
+        }\r
+        case VLC_FOURCC('R', 'V', '1', '5'):\r
+        {\r
+            static const D3DFORMAT formats[] = \r
+                { D3DFMT_X1R5G5B5 };\r
+            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));\r
+        }\r
+        case VLC_FOURCC('R', 'V', '1', '6'):\r
+        {\r
+            static const D3DFORMAT formats[] = \r
+                { D3DFMT_R5G6B5 };\r
+            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));\r
+        }\r
+        case VLC_FOURCC('R', 'V', '2', '4'):\r
+        {\r
+            static const D3DFORMAT formats[] = \r
+                { D3DFMT_R8G8B8, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8 };\r
+            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));\r
+        }\r
+        case VLC_FOURCC('R', 'V', '3', '2'):\r
+        {\r
+            static const D3DFORMAT formats[] = \r
+                { D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 };\r
+            return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));\r
+        }\r
+        default:\r
+            ;\r
+    }\r
+    return D3DFMT_UNKNOWN;\r
+}\r
+\r
+static int Direct3DVoutSetOuputFormat(vout_thread_t *p_vout, D3DFORMAT format)\r
+{\r
+    switch( format )\r
+    {\r
+        case D3DFMT_YUY2:\r
+            p_vout->output.i_chroma = VLC_FOURCC('Y', 'U', 'Y', '2');\r
+            break;\r
+        case D3DFMT_UYVY:\r
+            p_vout->output.i_chroma = VLC_FOURCC('U', 'Y', 'V', 'Y');\r
+            break;\r
+        case D3DFMT_X8R8G8B8:\r
+        case D3DFMT_A8R8G8B8:\r
+/*\r
+** FIXME: some custom masks are not handled properly in rgb_yuv converter,\r
+**        ARGB do NOT work !\r
+*/\r
+            p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '3', '2');\r
+            p_vout->output.i_rmask = 0x000000ff;\r
+            p_vout->output.i_gmask = 0x0000ff00;\r
+            p_vout->output.i_bmask = 0x00ff0000;\r
+            p_vout->output.i_lrshift = 8;\r
+            p_vout->output.i_lgshift = 16;\r
+            p_vout->output.i_lbshift = 24;\r
+            break;\r
+        case D3DFMT_R5G6B5:\r
+            p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '1', '6');\r
+#       if defined( WORDS_BIGENDIAN )\r
+            p_vout->output.i_rmask = (0x1fL)<<11;\r
+            p_vout->output.i_gmask = (0x3fL)<<5;\r
+            p_vout->output.i_bmask = (0x1fL)<<0;\r
+            //p_vout->output.i_rshift = 11;\r
+            //p_vout->output.i_gshift = 5;\r
+            //p_vout->output.i_bshift = 0;\r
+#       else\r
+/*\r
+** FIXME: in little endian mode, following masking is not byte aligned,\r
+**        therefore green bits will not be sequentially merged !\r
+*/\r
+            p_vout->output.i_rmask = (0x1fL)<<0;\r
+            p_vout->output.i_gmask = (0x3fL)<<5;\r
+            p_vout->output.i_bmask = (0x1fL)<<11;\r
+            //p_vout->output.i_rshift = 0;\r
+            //p_vout->output.i_gshift = 5;\r
+            //p_vout->output.i_bshift = 11;\r
+#       endif\r
+            break;\r
+        case D3DFMT_X1R5G5B5:\r
+            p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '1', '5');\r
+#       if defined( WORDS_BIGENDIAN )\r
+            p_vout->output.i_rmask = (0x1fL)<<10;\r
+            p_vout->output.i_gmask = (0x1fL)<<5;\r
+            p_vout->output.i_bmask = (0x1fL)<<0;\r
+            //p_vout->output.i_rshift = 10;\r
+            //p_vout->output.i_gshift = 5;\r
+            //p_vout->output.i_bshift = 0;\r
+#       else\r
+/*\r
+** FIXME: in little endian mode, following masking is not byte aligned,\r
+**        therefore green bits will not be sequentially merged !\r
+*/\r
+            p_vout->output.i_rmask = (0x1fL)<<1;\r
+            p_vout->output.i_gmask = (0x1fL)<<6;\r
+            p_vout->output.i_bmask = (0x1fL)<<11;\r
+            //p_vout->output.i_rshift = 1;\r
+            //p_vout->output.i_gshift = 5;\r
+            //p_vout->output.i_bshift = 11;\r
+#       endif\r
+            break;\r
+        default:\r
+            return VLC_EGENERIC;\r
+    }\r
+    return VLC_SUCCESS;\r
+}\r
+\r
+/*****************************************************************************\r
+ * Direct3DVoutCreatePictures: allocate a vector of identical pictures\r
+ *****************************************************************************\r
+ * Each picture has an associated offscreen surface in video memory\r
+ * depending on hardware capabilities the picture chroma will be as close\r
+ * as possible to the orginal render chroma to reduce CPU conversion overhead\r
+ * and delegate this work to video card GPU\r
+ *****************************************************************************/\r
+static int Direct3DVoutCreatePictures( vout_thread_t *p_vout, size_t i_num_pics )\r
+{\r
+    LPDIRECT3DDEVICE9       p_d3ddev  = p_vout->p_sys->p_d3ddev;\r
+    D3DFORMAT               format    = p_vout->p_sys->d3dpp.BackBufferFormat;\r
+    HRESULT hr;\r
+    size_t c;\r
+\r
+    I_OUTPUTPICTURES = 0;\r
+\r
+    /*\r
+    ** find the appropriate D3DFORMAT for the render chroma, the format will be the closest to\r
+    ** the requested chroma which is usable by the hardware in an offscreen surface, as they\r
+    ** typically support more formats than textures\r
+    */ \r
+    format = Direct3DVoutFindFormat(p_vout, p_vout->render.i_chroma, format);\r
+    if( VLC_SUCCESS != Direct3DVoutSetOuputFormat(p_vout, format) )\r
+    {\r
+        msg_Err(p_vout, "surface pixel format is not supported.");\r
+        return VLC_EGENERIC;\r
+    }\r
+\r
+    for( c=0; c<i_num_pics; )\r
+    {\r
+\r
+        LPDIRECT3DSURFACE9 p_d3dsurf;\r
+        picture_t *p_pic = p_vout->p_picture+c; \r
+\r
+        hr = IDirect3DDevice9_CreateOffscreenPlainSurface(p_d3ddev, \r
+                p_vout->render.i_width,\r
+                p_vout->render.i_height,\r
+                format,\r
+                D3DPOOL_DEFAULT,\r
+                &p_d3dsurf,\r
+                NULL);\r
+        if( FAILED(hr) )\r
+        {\r
+            msg_Err(p_vout, "Failed to create picture surface. (hr=0x%lx)", hr);\r
+            Direct3DVoutReleasePictures(p_vout);\r
+            return VLC_EGENERIC;\r
+        }\r
+\r
+        /* fill surface with default color */\r
+        IDirect3DDevice9_ColorFill(p_d3ddev, p_d3dsurf, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0) );\r
+        \r
+        /* assign surface to internal structure */\r
+        p_pic->p_sys = (void *)p_d3dsurf;\r
+\r
+        /* Now that we've got our direct-buffer, we can finish filling in the\r
+         * picture_t structures */\r
+        switch( p_vout->output.i_chroma )\r
+        {\r
+            case VLC_FOURCC('R','G','B','2'):\r
+                p_pic->p->i_lines = p_vout->output.i_height;\r
+                p_pic->p->i_visible_lines = p_vout->output.i_height;\r
+                p_pic->p->i_pixel_pitch = 1;\r
+                p_pic->p->i_visible_pitch = p_vout->output.i_width *\r
+                    p_pic->p->i_pixel_pitch;\r
+                p_pic->i_planes = 1;\r
+            break;\r
+            case VLC_FOURCC('R','V','1','5'):\r
+            case VLC_FOURCC('R','V','1','6'):\r
+                p_pic->p->i_lines = p_vout->output.i_height;\r
+                p_pic->p->i_visible_lines = p_vout->output.i_height;\r
+                p_pic->p->i_pixel_pitch = 2;\r
+                p_pic->p->i_visible_pitch = p_vout->output.i_width *\r
+                    p_pic->p->i_pixel_pitch;\r
+                p_pic->i_planes = 1;\r
+            break;\r
+            case VLC_FOURCC('R','V','2','4'):\r
+                p_pic->p->i_lines = p_vout->output.i_height;\r
+                p_pic->p->i_visible_lines = p_vout->output.i_height;\r
+                p_pic->p->i_pixel_pitch = 3;\r
+                p_pic->p->i_visible_pitch = p_vout->output.i_width *\r
+                    p_pic->p->i_pixel_pitch;\r
+                p_pic->i_planes = 1;\r
+            break;\r
+            case VLC_FOURCC('R','V','3','2'):\r
+                p_pic->p->i_lines = p_vout->output.i_height;\r
+                p_pic->p->i_visible_lines = p_vout->output.i_height;\r
+                p_pic->p->i_pixel_pitch = 4;\r
+                p_pic->p->i_visible_pitch = p_vout->output.i_width *\r
+                    p_pic->p->i_pixel_pitch;\r
+                p_pic->i_planes = 1;\r
+                break;\r
+            case VLC_FOURCC('U','Y','V','Y'):\r
+            case VLC_FOURCC('Y','U','Y','2'):\r
+                p_pic->p->i_lines = p_vout->output.i_height;\r
+                p_pic->p->i_visible_lines = p_vout->output.i_height;\r
+                p_pic->p->i_pixel_pitch = 2;\r
+                p_pic->p->i_visible_pitch = p_vout->output.i_width *\r
+                    p_pic->p->i_pixel_pitch;\r
+                p_pic->i_planes = 1;\r
+                break;\r
+            default:\r
+                Direct3DVoutReleasePictures(p_vout);\r
+                return VLC_EGENERIC;\r
+        }\r
+        p_pic->i_status = DESTROYED_PICTURE;\r
+        p_pic->i_type   = DIRECT_PICTURE;\r
+        p_pic->b_slow   = VLC_TRUE;\r
+        p_pic->pf_lock  = Direct3DVoutLockSurface;\r
+        p_pic->pf_unlock = Direct3DVoutUnlockSurface;\r
+        PP_OUTPUTPICTURE[c] = p_pic;\r
+\r
+        I_OUTPUTPICTURES = ++c;\r
+    }\r
+\r
+    msg_Dbg( p_vout, "%u Direct3D pictures created successfully", c );\r
+\r
+    return VLC_SUCCESS;\r
+}\r
+\r
+/*****************************************************************************\r
+ * Direct3DVoutReleasePictures: destroy a picture vector \r
+ *****************************************************************************\r
+ * release all video resources used for pictures\r
+ *****************************************************************************/\r
+static void Direct3DVoutReleasePictures( vout_thread_t *p_vout)\r
+{\r
+    size_t i_num_pics = I_OUTPUTPICTURES;\r
+    size_t c;\r
+    for( c=0; c<i_num_pics; ++c )\r
+    {\r
+        picture_t *p_pic = p_vout->p_picture+c; \r
+        if( p_pic->p_sys )\r
+        {\r
+            LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;\r
+\r
+            p_pic->p_sys = NULL;\r
+\r
+            if( p_d3dsurf )\r
+            {\r
+                IDirect3DSurface9_Release(p_d3dsurf);\r
+            }\r
+        }\r
+    }\r
+    msg_Dbg( p_vout, "%u Direct3D pictures released.", c);\r
+\r
+    I_OUTPUTPICTURES = 0;\r
+}\r
+\r
+/*****************************************************************************\r
+ * Direct3DVoutLockSurface: Lock surface and get picture data pointer\r
+ *****************************************************************************\r
+ * This function locks a surface and get the surface descriptor which amongst\r
+ * other things has the pointer to the picture data.\r
+ *****************************************************************************/\r
+static int Direct3DVoutLockSurface( vout_thread_t *p_vout, picture_t *p_pic )\r
+{\r
+    HRESULT hr;\r
+    D3DLOCKED_RECT d3drect;\r
+    LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;\r
+\r
+    if( NULL == p_d3dsurf )\r
+        return VLC_EGENERIC;\r
+\r
+    /* Lock the surface to get a valid pointer to the picture buffer */\r
+    hr = IDirect3DSurface9_LockRect(p_d3dsurf, &d3drect, NULL, D3DLOCK_DISCARD);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        return VLC_EGENERIC;\r
+    }\r
+\r
+    /* fill in buffer info in first plane */\r
+    p_pic->p->p_pixels = d3drect.pBits;\r
+    p_pic->p->i_pitch  = d3drect.Pitch;\r
+\r
+    return VLC_SUCCESS;\r
+}\r
+\r
+/*****************************************************************************\r
+ * Direct3DVoutUnlockSurface: Unlock a surface locked by Direct3DLockSurface().\r
+ *****************************************************************************/\r
+static int Direct3DVoutUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )\r
+{\r
+    HRESULT hr;\r
+    LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;\r
+\r
+    if( NULL == p_d3dsurf )\r
+        return VLC_EGENERIC;\r
+\r
+    /* Unlock the Surface */\r
+    hr = IDirect3DSurface9_UnlockRect(p_d3dsurf);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        return VLC_EGENERIC;\r
+    }\r
+    return VLC_SUCCESS;\r
+}\r
+\r
+/*****************************************************************************\r
+ * Direct3DVoutCreateScene: allocate and initialize a 3D scene\r
+ *****************************************************************************\r
+ * for advanced blending/filtering a texture needs be used in a 3D scene.\r
+ *****************************************************************************/\r
+\r
+static int Direct3DVoutCreateScene( vout_thread_t *p_vout )\r
+{\r
+    LPDIRECT3DDEVICE9       p_d3ddev  = p_vout->p_sys->p_d3ddev;\r
+    LPDIRECT3DTEXTURE9      p_d3dtex;\r
+    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc;\r
+\r
+    HRESULT hr;\r
+\r
+    /*\r
+    ** Create a texture for use when rendering a scene\r
+    ** for performance reason, texture format is identical to backbuffer\r
+    ** which would usually be a RGB format\r
+    */\r
+    hr = IDirect3DDevice9_CreateTexture(p_d3ddev, \r
+            p_vout->render.i_width,\r
+            p_vout->render.i_height,\r
+            1,\r
+            D3DUSAGE_RENDERTARGET, \r
+            p_vout->p_sys->d3dpp.BackBufferFormat,\r
+            D3DPOOL_DEFAULT,\r
+            &p_d3dtex, \r
+            NULL);\r
+    if( FAILED(hr))\r
+    {\r
+        msg_Err(p_vout, "Failed to create texture. (hr=0x%lx)", hr);\r
+        return VLC_EGENERIC;\r
+    }\r
+\r
+    /*\r
+    ** Create a vertex buffer for use when rendering scene\r
+    */\r
+    hr = IDirect3DDevice9_CreateVertexBuffer(p_d3ddev,\r
+            sizeof(CUSTOMVERTEX)*4,\r
+            D3DUSAGE_WRITEONLY,\r
+            D3DFVF_CUSTOMVERTEX,\r
+            D3DPOOL_DEFAULT,\r
+            &p_d3dvtc,\r
+            NULL);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Err(p_vout, "Failed to create vertex buffer. (hr=0x%lx)", hr);\r
+            IDirect3DTexture9_Release(p_d3dtex);\r
+        return VLC_EGENERIC;\r
+    }\r
+\r
+    p_vout->p_sys->p_d3dtex = p_d3dtex;\r
+    p_vout->p_sys->p_d3dvtc = p_d3dvtc;\r
+\r
+    // Texture coordinates outside the range [0.0, 1.0] are set \r
+    // to the texture color at 0.0 or 1.0, respectively.\r
+    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);\r
+    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);\r
+\r
+    // Set linear filtering quality\r
+    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);\r
+    IDirect3DDevice9_SetSamplerState(p_d3ddev, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);\r
+\r
+    // set maximum ambient light\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255));\r
+\r
+    // Turn off culling\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_CULLMODE, D3DCULL_NONE);\r
+\r
+    // Turn off the zbuffer\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ZENABLE, D3DZB_FALSE);\r
+\r
+    // Turn off lights\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_LIGHTING, FALSE);\r
+\r
+    // Enable dithering\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_DITHERENABLE, TRUE);\r
+\r
+    // disable stencil\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_STENCILENABLE, FALSE);\r
+\r
+    // manage blending\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHABLENDENABLE, TRUE);\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHATESTENABLE,TRUE);\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHAREF, 0x10);\r
+    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ALPHAFUNC,D3DCMP_GREATER);\r
+\r
+    // Set texture states\r
+    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_COLOROP,D3DTOP_MODULATE);\r
+    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_COLORARG1,D3DTA_TEXTURE);\r
+    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_COLORARG2,D3DTA_DIFFUSE);\r
+\r
+    // turn off alpha operation\r
+    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);\r
+\r
+    msg_Dbg( p_vout, "Direct3D scene created successfully");\r
+\r
+    return VLC_SUCCESS;\r
+}\r
+\r
+/*****************************************************************************\r
+ * Direct3DVoutReleaseScene\r
+ *****************************************************************************/\r
+static void Direct3DVoutReleaseScene( vout_thread_t *p_vout )\r
+{\r
+    LPDIRECT3DTEXTURE9      p_d3dtex = p_vout->p_sys->p_d3dtex;\r
+    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc = p_vout->p_sys->p_d3dvtc;\r
+\r
+    if( p_d3dvtc )\r
+    {\r
+        IDirect3DVertexBuffer9_Release(p_d3dvtc);\r
+        p_vout->p_sys->p_d3dvtc = NULL;\r
+    }\r
+\r
+    if( p_d3dtex )\r
+    {\r
+        IDirect3DTexture9_Release(p_d3dtex);\r
+        p_vout->p_sys->p_d3dtex = NULL;\r
+    }\r
+    msg_Dbg( p_vout, "Direct3D scene released successfully");\r
+}\r
+\r
+/*****************************************************************************\r
+ * Direct3DVoutRenderDefault: copy picture surface to display back buffer\r
+ *****************************************************************************\r
+ * This function is intented for lower end video cards, without pixel shader \r
+ * support or low video RAM\r
+ *****************************************************************************/\r
+static void Direct3DVoutRenderDefault( vout_thread_t *p_vout, picture_t *p_pic )\r
+{\r
+    LPDIRECT3DDEVICE9       p_d3ddev  = p_vout->p_sys->p_d3ddev;\r
+    LPDIRECT3DSURFACE9      p_d3dsrc, p_d3ddest;\r
+    UINT                    iSwapChain, iSwapChains;\r
+    HRESULT hr;\r
+\r
+    // check if device is still available    \r
+    hr = IDirect3DDevice9_TestCooperativeLevel(p_d3ddev);\r
+    if( FAILED(hr) )\r
+    {\r
+        if( (D3DERR_DEVICENOTRESET != hr)\r
+         || (VLC_SUCCESS != Direct3DVoutResetDevice(p_vout, 0, 0)) )\r
+        {\r
+            // device is not usable at present (lost device, out of video mem ?)\r
+            return;\r
+        }\r
+    }\r
+\r
+    /*  retrieve the number of swap chains */\r
+    iSwapChains = IDirect3DDevice9_GetNumberOfSwapChains(p_d3ddev);\r
+    if( 0 == iSwapChains )\r
+    {\r
+        msg_Dbg( p_vout, "no swap chain to render ?");\r
+        return;\r
+    }\r
+\r
+    /*  retrieve picture surface */\r
+    p_d3dsrc = (LPDIRECT3DSURFACE9)p_pic->p_sys;\r
+    if( NULL == p_d3dsrc )\r
+    {\r
+        msg_Dbg( p_vout, "no surface to render ?");\r
+        return;\r
+    }\r
+\r
+    for( iSwapChain=0; iSwapChain < iSwapChains; ++iSwapChain )\r
+    {\r
+        /* retrieve swap chain back buffer */\r
+        hr = IDirect3DDevice9_GetBackBuffer(p_d3ddev, iSwapChain, 0, D3DBACKBUFFER_TYPE_MONO, &p_d3ddest);\r
+        if( FAILED(hr) )\r
+        {\r
+            msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+            continue;\r
+        }\r
+\r
+        /* Copy picture surface into texture surface, color space conversion happens here */\r
+        hr = IDirect3DDevice9_StretchRect(p_d3ddev, p_d3dsrc, NULL, p_d3ddest, NULL, D3DTEXF_NONE);\r
+        IDirect3DSurface9_Release(p_d3ddest);\r
+        if( FAILED(hr) )\r
+        {\r
+            msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+            return;\r
+        }\r
+    }\r
+}\r
+\r
+/*****************************************************************************\r
+ * Render: copy picture surface into a texture and render into a scene\r
+ *****************************************************************************\r
+ * This function is intented for higher end 3D cards, with pixel shader support\r
+ * and at least 64 MB of video RAM.\r
+ *****************************************************************************/\r
+static void Direct3DVoutRenderScene( vout_thread_t *p_vout, picture_t *p_pic )\r
+{\r
+    LPDIRECT3DDEVICE9       p_d3ddev  = p_vout->p_sys->p_d3ddev;\r
+    LPDIRECT3DTEXTURE9      p_d3dtex  = p_vout->p_sys->p_d3dtex;\r
+    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc  = p_vout->p_sys->p_d3dvtc;\r
+    LPDIRECT3DSURFACE9      p_d3dsrc, p_d3ddest;\r
+    CUSTOMVERTEX            *p_vertices;\r
+    HRESULT hr;\r
+    float f_width, f_height;\r
+\r
+    // check if device is still available    \r
+    hr = IDirect3DDevice9_TestCooperativeLevel(p_d3ddev);\r
+    if( FAILED(hr) )\r
+    {\r
+        if( (D3DERR_DEVICENOTRESET != hr)\r
+         || (VLC_SUCCESS != Direct3DVoutResetDevice(p_vout, 0, 0)) )\r
+        {\r
+            // device is not usable at present (lost device, out of video mem ?)\r
+            return;\r
+        }\r
+    }\r
+\r
+    /* Clear the backbuffer and the zbuffer */\r
+    hr = IDirect3DDevice9_Clear( p_d3ddev, 0, NULL, D3DCLEAR_TARGET,\r
+                              D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0 );\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        return;\r
+    }\r
+\r
+    /*  retrieve picture surface */\r
+    p_d3dsrc = (LPDIRECT3DSURFACE9)p_pic->p_sys;\r
+    if( NULL == p_d3dsrc )\r
+    {\r
+        msg_Dbg( p_vout, "no surface to render ?");\r
+        return;\r
+    }\r
+\r
+    /* retrieve texture top-level surface */\r
+    hr = IDirect3DTexture9_GetSurfaceLevel(p_d3dtex, 0, &p_d3ddest);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        return;\r
+    }\r
+\r
+    /* Copy picture surface into texture surface, color space conversion happens here */\r
+    hr = IDirect3DDevice9_StretchRect(p_d3ddev, p_d3dsrc, NULL, p_d3ddest, NULL, D3DTEXF_NONE);\r
+    IDirect3DSurface9_Release(p_d3ddest);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        return;\r
+    }\r
+\r
+    /* Update the vertex buffer */\r
+    hr = IDirect3DVertexBuffer9_Lock(p_d3dvtc, 0, 0, (VOID **)(&p_vertices), D3DLOCK_DISCARD);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        return;\r
+    }\r
+\r
+    /* Setup vertices */\r
+    f_width  = (float)(p_vout->p_sys->d3dpp.BackBufferWidth);\r
+    f_height = (float)(p_vout->p_sys->d3dpp.BackBufferHeight);\r
+\r
+    p_vertices[0].x       = 0.0f;       // left\r
+    p_vertices[0].y       = 0.0f;       // top\r
+    p_vertices[0].z       = 0.0f;\r
+    p_vertices[0].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);\r
+    p_vertices[0].rhw     = 1.0f;\r
+    p_vertices[0].tu      = 0.0f;\r
+    p_vertices[0].tv      = 0.0f;\r
\r
+    p_vertices[1].x       = f_width;    // right\r
+    p_vertices[1].y       = 0.0f;       // top\r
+    p_vertices[1].z       = 0.0f;\r
+    p_vertices[1].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);\r
+    p_vertices[1].rhw     = 1.0f;\r
+    p_vertices[1].tu      = 1.0f;\r
+    p_vertices[1].tv      = 0.0f;\r
\r
+    p_vertices[2].x       = f_width;    // right\r
+    p_vertices[2].y       = f_height;   // bottom\r
+    p_vertices[2].z       = 0.0f;\r
+    p_vertices[2].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);\r
+    p_vertices[2].rhw     = 1.0f;\r
+    p_vertices[2].tu      = 1.0f;\r
+    p_vertices[2].tv      = 1.0f;\r
\r
+    p_vertices[3].x       = 0.0f;       // left\r
+    p_vertices[3].y       = f_height;   // bottom\r
+    p_vertices[3].z       = 0.0f;\r
+    p_vertices[3].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);\r
+    p_vertices[3].rhw     = 1.0f;\r
+    p_vertices[3].tu      = 0.0f;\r
+    p_vertices[3].tv      = 1.0f;\r
\r
+    hr= IDirect3DVertexBuffer9_Unlock(p_d3dvtc);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        return;\r
+    }\r
+\r
+    // Begin the scene\r
+    hr = IDirect3DDevice9_BeginScene(p_d3ddev);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        return;\r
+    }\r
+\r
+    // Setup our texture. Using textures introduces the texture stage states,\r
+    // which govern how textures get blended together (in the case of multiple\r
+    // textures) and lighting information. In this case, we are modulating\r
+    // (blending) our texture with the diffuse color of the vertices.\r
+    hr = IDirect3DDevice9_SetTexture(p_d3ddev, 0, (LPDIRECT3DBASETEXTURE9)p_d3dtex);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        IDirect3DDevice9_EndScene(p_d3ddev);\r
+        return;\r
+    }\r
+\r
+    // Render the vertex buffer contents\r
+    hr = IDirect3DDevice9_SetStreamSource(p_d3ddev, 0, p_d3dvtc, 0, sizeof(CUSTOMVERTEX));\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        IDirect3DDevice9_EndScene(p_d3ddev);\r
+        return;\r
+    }\r
\r
+    // we use FVF instead of vertex shader\r
+    hr = IDirect3DDevice9_SetVertexShader(p_d3ddev, NULL);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        IDirect3DDevice9_EndScene(p_d3ddev);\r
+        return;\r
+    }\r
+\r
+    hr = IDirect3DDevice9_SetFVF(p_d3ddev, D3DFVF_CUSTOMVERTEX);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        IDirect3DDevice9_EndScene(p_d3ddev);\r
+        return;\r
+    }\r
+\r
+    // draw rectangle\r
+    hr = IDirect3DDevice9_DrawPrimitive(p_d3ddev, D3DPT_TRIANGLEFAN, 0, 2);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        IDirect3DDevice9_EndScene(p_d3ddev);\r
+        return;\r
+    }\r
+\r
+    // End the scene\r
+    hr = IDirect3DDevice9_EndScene(p_d3ddev);\r
+    if( FAILED(hr) )\r
+    {\r
+        msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);\r
+        return;\r
+    }\r
+}\r
+\r
index 7de06ec..9845589 100644 (file)
 
 #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
@@ -908,7 +921,7 @@ BOOL WINAPI DirectXEnumCallback( GUID* p_guid, LPTSTR psz_desc,
                     rect.left = monitor_info.rcWork.left;
                     rect.top = monitor_info.rcWork.top;
                     msg_Dbg( p_vout, "DirectXEnumCallback: setting window "
-                             "position to %d,%d", rect.left, rect.top );
+                             "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 );
@@ -1040,7 +1053,7 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
         p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
     }
 
-    msg_Dbg( p_vout, "screen dimensions (%ix%i,%ix%i)",
+    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,
index 4cf9300..3149341 100644 (file)
 #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"
@@ -301,7 +309,11 @@ void E_(DirectXEventThread)( event_thread_t *p_event )
 
 #ifdef MODULE_NAME_IS_glwin32
                 val.psz_string = strdup( VOUT_TITLE " (OpenGL output)" );
-#else
+#endif
+#ifdef MODULE_NAME_IS_direct3d
+                val.psz_string = strdup( VOUT_TITLE " (Direct3D output)" );
+#endif
+#ifdef MODULE_NAME_IS_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 = 
@@ -481,9 +493,9 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
                     _T(VOUT_TITLE) _T(" (DirectX Output)"),  /* window title */
                     i_style,                                 /* window style */
                     (p_vout->p_sys->i_window_x < 0) ? CW_USEDEFAULT :
-                        p_vout->p_sys->i_window_x,   /* default X coordinate */
+                        (UINT)p_vout->p_sys->i_window_x,   /* default X coordinate */
                     (p_vout->p_sys->i_window_y < 0) ? CW_USEDEFAULT :
-                        p_vout->p_sys->i_window_y,   /* default Y coordinate */
+                        (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 */
@@ -519,20 +531,33 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
                             NULL, NULL, hInstance, NULL );
     }
 
-    /* Now display the window */
-    ShowWindow( p_vout->p_sys->hwnd, SW_SHOW );
-
-    /* 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. */
-    SendMessage( p_vout->p_sys->hwnd, WM_VLC_CREATE_VIDEO_WIN, 0, 0 );
-
     /* 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 | WS_VISIBLE,                   /* window style */
+               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;
 }
 
@@ -613,6 +638,7 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
     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 )
     {
@@ -626,6 +652,7 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
                 p_vout->p_sys->i_align_dest_size / 2 ) & 
                 ~p_vout->p_sys->i_align_dest_size) + rect_dest.left;
     }
+#endif
 
     /* UpdateOverlay directdraw function doesn't automatically clip to the
      * display size so we need to do it otherwise it will fail */
@@ -675,6 +702,7 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
       (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 )
     {
@@ -689,6 +717,7 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
                 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"
@@ -704,8 +733,10 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
     rect_dest_clipped.top -= p_vout->p_sys->rect_display.top;
     rect_dest_clipped.bottom -= p_vout->p_sys->rect_display.top;
 
+#ifdef MODULE_NAME_IS_vout_directx
     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;
@@ -808,23 +839,6 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
         }
         break;
 
-    case WM_VLC_CREATE_VIDEO_WIN:
-        /* Create video sub-window */
-        p_vout->p_sys->hvideownd =
-            CreateWindow( _T("VLC DirectX video"), _T(""),   /* window class */
-                    WS_CHILD | WS_VISIBLE,                   /* window style */
-                    CW_USEDEFAULT, CW_USEDEFAULT,     /* default coordinates */
-                    CW_USEDEFAULT, CW_USEDEFAULT,
-                    hwnd,                                   /* parent window */
-                    NULL, GetModuleHandle(NULL),
-                    (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" );
-        break;
-
     case WM_PAINT:
     case WM_NCPAINT:
     case WM_ERASEBKGND:
index 3a081c0..413950d 100644 (file)
@@ -104,10 +104,6 @@ static int OpenVideo( vlc_object_t *p_this )
     p_vout->pf_manage = Manage;
     p_vout->pf_swap = GLSwapBuffers;
 
-    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;
@@ -485,8 +481,3 @@ static void GLSwapBuffers( vout_thread_t *p_vout )
 {
     SwapBuffers( p_vout->p_sys->hGLDC );
 }
-
-int E_(DirectXUpdateOverlay)( vout_thread_t *p_vout )
-{
-    return 1;
-}
index b466eeb..2cd1ca5 100644 (file)
@@ -40,12 +40,6 @@ typedef struct event_thread_t
  *****************************************************************************/
 struct vout_sys_t
 {
-    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 */
-
     HWND                 hwnd;                  /* Handle of the main window */
     HWND                 hvideownd;        /* Handle of the video sub-window */
     HWND                 hparent;             /* Handle of the parent window */
@@ -58,15 +52,13 @@ struct vout_sys_t
     HMONITOR             (WINAPI* MonitorFromWindow)( HWND, DWORD );
     BOOL                 (WINAPI* GetMonitorInfo)( HMONITOR, LPMONITORINFO );
 
-    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_hw_yuv;    /* Should we use hardware YUV->RGB conversions */
-    vlc_bool_t   b_3buf_overlay;   /* Should we use triple buffered overlays */
-
     /* 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;
@@ -74,65 +66,74 @@ struct vout_sys_t
     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;
-    RECT         rect_parent;
 
+#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_hw_yuv;    /* Should we use hardware YUV->RGB conversions */
+    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 */
 
-    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;
     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
 
-    /* screensaver system settings to be restored when vout is closed */
-    UINT i_spi_lowpowertimeout;
-    UINT i_spi_powerofftimeout;
-    UINT i_spi_screensavetimeout;
-
+#ifdef MODULE_NAME_IS_direct3d
+    // core objects
+    LPDIRECT3D9                    p_d3dobj;
+    LPDIRECT3DDEVICE9      p_d3ddev;
+    D3DPRESENT_PARAMETERS   d3dpp;
+    // scene objects
+    LPDIRECT3DTEXTURE9      p_d3dtex;
+    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc;
+#endif
     event_thread_t *p_event;
     vlc_mutex_t    lock;
 };
 
-/*****************************************************************************
- * 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;
-    DDSURFACEDESC        ddsd;
-    LPDIRECTDRAWSURFACE2 p_front_surface;
-};
-
 /*****************************************************************************
  * Prototypes from vout.c
  *****************************************************************************/
@@ -149,8 +150,7 @@ void E_(DirectXUpdateRects) ( vout_thread_t *p_vout, vlc_bool_t b_force );
  *****************************************************************************/
 #define WM_VLC_HIDE_MOUSE WM_APP
 #define WM_VLC_SHOW_MOUSE WM_APP + 1
-#define WM_VLC_CREATE_VIDEO_WIN WM_APP + 2
-#define WM_VLC_CHANGE_TEXT WM_APP + 3
+#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