]> git.sesse.net Git - vlc/commitdiff
Converted direct3d to vout display.
authorLaurent Aimar <fenrir@videolan.org>
Fri, 23 Oct 2009 23:34:53 +0000 (01:34 +0200)
committerLaurent Aimar <fenrir@videolan.org>
Mon, 2 Nov 2009 18:50:27 +0000 (19:50 +0100)
It also fixes a few remaining race conditions.

modules/video_output/msw/Modules.am
modules/video_output/msw/common.c
modules/video_output/msw/common.h [new file with mode: 0644]
modules/video_output/msw/direct3d.c
modules/video_output/msw/events.c
modules/video_output/msw/events.h

index 6460ba7056ecdaeb9193d7c174c7817d17f87bec..cc958ecfcd2389c0f5c40ce7437c0c4acab0b47c 100644 (file)
@@ -8,10 +8,10 @@ SOURCES_directx = \
 
 SOURCES_direct3d = \
        direct3d.c \
-       vout.h \
-       events_vo.h \
-       events_vo.c \
-       common_vo.c \
+       common.h \
+       events.h \
+       events.c \
+       common.c \
        $(NULL)
 
 SOURCES_glwin32 = \
index f2bbc97cbb37801cee8be56d14a299569d88bcba..83dac0b48f521e86b6bdeceb8ef82edc7b9c3820 100644 (file)
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
+#include <assert.h>
 
 #include <vlc_common.h>
-#include <vlc_vout.h>
+#include <vlc_vout_display.h>
 #include <vlc_vout_window.h>
 
 #include <windows.h>
@@ -48,7 +49,7 @@
 #include <GL/gl.h>
 #endif
 
-#include "vout.h"
+#include "common.h"
 
 #ifndef UNDER_CE
 #include <vlc_windows_interfaces.h>
     //WINSHELLAPI BOOL WINAPI SHFullScreen(HWND hwndRequester, DWORD dwState);
 #endif
 
-static int vaControlParentWindow( vout_thread_t *, int, va_list );
+static int CommonControlSetFullscreen(vout_display_t *, bool is_fullscreen);
+
+static void DisableScreensaver(vout_display_t *);
+static void RestoreScreensaver(vout_display_t *);
 
 /* */
-int CommonInit( vout_thread_t *p_vout )
+int CommonInit(vout_display_t *vd)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
-
-    p_sys->hwnd      = NULL;
-    p_sys->hvideownd = NULL;
-    p_sys->hparent   = NULL;
-    p_sys->hfswnd    = NULL;
-    p_sys->i_changes = 0;
-    SetRectEmpty( &p_sys->rect_display );
-    SetRectEmpty( &p_sys->rect_parent );
-
-    var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
-
-    /* Set main window's size */
-    vout_window_cfg_t wnd_cfg;
-
-    memset( &wnd_cfg, 0, sizeof(wnd_cfg) );
-    wnd_cfg.type   = VOUT_WINDOW_TYPE_HWND;
-    wnd_cfg.x      = 0;
-    wnd_cfg.y      = 0;
-    wnd_cfg.width  = p_vout->i_window_width;
-    wnd_cfg.height = p_vout->i_window_height;
-
-    p_sys->p_event = EventThreadCreate( p_vout, &wnd_cfg );
-    if( !p_sys->p_event )
+    vout_display_sys_t *sys = vd->sys;
+
+    sys->hwnd      = NULL;
+    sys->hvideownd = NULL;
+    sys->hparent   = NULL;
+    sys->hfswnd    = NULL;
+    sys->changes   = 0;
+    SetRectEmpty(&sys->rect_display);
+    SetRectEmpty(&sys->rect_parent);
+    sys->is_first_display = true;
+    sys->is_on_top = false;
+
+    var_Create(vd, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
+    var_Create(vd, "video-deco", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
+
+    /* FIXME remove mouse hide from msw */
+    var_Create(vd, "mouse-hide-timeout", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
+
+    /* */
+    sys->event = EventThreadCreate(vd);
+    if (!sys->event)
         return VLC_EGENERIC;
 
     event_cfg_t cfg;
     memset(&cfg, 0, sizeof(cfg));
 #ifdef MODULE_NAME_IS_direct3d
-    cfg.use_desktop = p_vout->p_sys->b_desktop;
+    cfg.use_desktop = sys->use_desktop;
 #endif
 #ifdef MODULE_NAME_IS_directx
-    cfg.use_overlay = p_vout->p_sys->b_using_overlay;
+    cfg.use_overlay = sys->b_using_overlay;
 #endif
+    cfg.win.type   = VOUT_WINDOW_TYPE_HWND;
+    cfg.win.x      = 0;
+    cfg.win.y      = 0;
+    cfg.win.width  = vd->cfg->display.width;
+    cfg.win.height = vd->cfg->display.height;
+
     event_hwnd_t hwnd;
-    if( EventThreadStart( p_sys->p_event, &hwnd, &cfg ) )
+    if (EventThreadStart(sys->event, &hwnd, &cfg))
         return VLC_EGENERIC;
 
-    p_sys->parent_window = hwnd.parent_window;
-    p_sys->hparent       = hwnd.hparent;
-    p_sys->hwnd          = hwnd.hwnd;
-    p_sys->hvideownd     = hwnd.hvideownd;
-    p_sys->hfswnd        = hwnd.hfswnd;
+    sys->parent_window = hwnd.parent_window;
+    sys->hparent       = hwnd.hparent;
+    sys->hwnd          = hwnd.hwnd;
+    sys->hvideownd     = hwnd.hvideownd;
+    sys->hfswnd        = hwnd.hfswnd;
 
-    /* Variable to indicate if the window should be on top of others */
-    /* Trigger a callback right now */
-    var_TriggerCallback( p_vout, "video-on-top" );
+    if (vd->cfg->is_fullscreen) {
+        if (CommonControlSetFullscreen(vd, true))
+            vout_display_SendEventFullscreen(vd, false);
+    }
 
     /* Why not with glwin32 */
 #if !defined(UNDER_CE) && !defined(MODULE_NAME_IS_glwin32)
-    var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
-    DisableScreensaver ( p_vout );
+    var_Create(vd, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
+    DisableScreensaver (vd);
 #endif
 
     return VLC_SUCCESS;
 }
 
 /* */
-void CommonClean( vout_thread_t *p_vout )
+void CommonClean(vout_display_t *vd)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
+    vout_display_sys_t *sys = vd->sys;
 
-    ExitFullscreen( p_vout );
-    if( p_sys->p_event )
-    {
-        EventThreadStop( p_sys->p_event );
-        EventThreadDestroy( p_sys->p_event );
+    if (sys->event) {
+        EventThreadStop(sys->event);
+        EventThreadDestroy(sys->event);
     }
 
 #if !defined(UNDER_CE) && !defined(MODULE_NAME_IS_glwin32)
-    RestoreScreensaver( p_vout );
+    RestoreScreensaver(vd);
 #endif
 }
 
-void CommonManage( vout_thread_t *p_vout )
+void CommonManage(vout_display_t *vd)
 {
+    vout_display_sys_t *sys = vd->sys;
+
+    /* 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 we do not control our window, we check for geometry changes
      * ourselves because the parent might not send us its events. */
-    if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
-    {
+    if (sys->hparent && !vd->cfg->is_fullscreen) {
         RECT rect_parent;
         POINT point;
 
-        GetClientRect( p_vout->p_sys->hparent, &rect_parent );
+        GetClientRect(sys->hparent, &rect_parent);
         point.x = point.y = 0;
-        ClientToScreen( p_vout->p_sys->hparent, &point );
-        OffsetRect( &rect_parent, point.x, point.y );
+        ClientToScreen(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;
+        if (!EqualRect(&rect_parent, &sys->rect_parent)) {
+            sys->rect_parent = rect_parent;
 
             /* FIXME I find such #ifdef quite weirds. Are they really needed ? */
 
 #if defined(MODULE_NAME_IS_direct3d)
-            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
-                          rect_parent.right - rect_parent.left,
-                          rect_parent.bottom - rect_parent.top,
-                          SWP_NOZORDER );
-            UpdateRects( p_vout, true );
+            SetWindowPos(sys->hwnd, 0, 0, 0,
+                         rect_parent.right - rect_parent.left,
+                         rect_parent.bottom - rect_parent.top,
+                         SWP_NOZORDER);
+            UpdateRects(vd, NULL, NULL, true);
 #else
             /* 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(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 );
+            SetWindowPos(sys->hwnd, 0, 0, 0,
+                         rect_parent.right - rect_parent.left,
+                         rect_parent.bottom - rect_parent.top, 0);
 
 #if defined(MODULE_NAME_IS_wingdi) || defined(MODULE_NAME_IS_wingapi)
             unsigned int i_x, i_y, i_width, i_height;
-            vout_PlacePicture( p_vout, rect_parent.right - rect_parent.left,
-                               rect_parent.bottom - rect_parent.top,
-                               &i_x, &i_y, &i_width, &i_height );
+            vout_PlacePicture(vd, rect_parent.right - rect_parent.left,
+                              rect_parent.bottom - rect_parent.top,
+                              &i_x, &i_y, &i_width, &i_height);
 
-            SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP,
-                          i_x, i_y, i_width, i_height, 0 );
+            SetWindowPos(sys->hvideownd, HWND_TOP,
+                         i_x, i_y, i_width, i_height, 0);
 #endif
 #endif
         }
     }
 
     /* */
-    p_vout->p_sys->i_changes |= EventThreadRetreiveChanges( p_vout->p_sys->p_event );
-
-    /* autoscale toggle */
-    if( p_vout->i_changes & VOUT_SCALE_CHANGE )
-    {
-        p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
-
-        p_vout->b_autoscale = var_GetBool( p_vout, "autoscale" );
-        p_vout->i_zoom = (int) ZOOM_FP_FACTOR;
-
-        UpdateRects( p_vout, true );
-    }
-
-    /* scaling factor */
-    if( p_vout->i_changes & VOUT_ZOOM_CHANGE )
-    {
-        p_vout->i_changes &= ~VOUT_ZOOM_CHANGE;
-
-        p_vout->b_autoscale = false;
-        p_vout->i_zoom =
-            (int)( ZOOM_FP_FACTOR * var_GetFloat( p_vout, "scale" ) );
-        UpdateRects( p_vout, true );
-    }
-
-    /* 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;
-        UpdateRects( p_vout, 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 (EventThreadGetAndResetHasMoved(sys->event))
+        UpdateRects(vd, NULL, NULL, false);
 
-    /*
-     * 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
-     */
-    EventThreadMouseAutoHide( p_vout->p_sys->p_event );
-
-    /*
-     * "Always on top" status change
-     */
-    if( p_vout->p_sys->b_on_top_change )
-    {
-        HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
-        bool b = var_GetBool( p_vout, "video-on-top" );
-
-        /* Set the window on top if necessary */
-        if( b && !( 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( !b && ( 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 = false;
-    }
+    /* Pointer change */
+    EventThreadMouseAutoHide(sys->event);
 }
 
 /*****************************************************************************
@@ -292,67 +214,81 @@ void CommonManage( vout_thread_t *p_vout )
  * its job is to update the source and destination RECTs used to display the
  * picture.
  *****************************************************************************/
-void UpdateRects( vout_thread_t *p_vout, bool b_force )
+void UpdateRects(vout_display_t *vd,
+                  const vout_display_cfg_t *cfg,
+                  const video_format_t *source,
+                  bool is_forced)
 {
-#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
-
-    unsigned int i_width, i_height, i_x, i_y;
+    vout_display_sys_t *sys = vd->sys;
+#define rect_src sys->rect_src
+#define rect_src_clipped sys->rect_src_clipped
+#define rect_dest sys->rect_dest
+#define rect_dest_clipped sys->rect_dest_clipped
 
     RECT  rect;
     POINT point;
 
     /* Retrieve the window size */
-    GetClientRect( p_vout->p_sys->hwnd, &rect );
+    GetClientRect(sys->hwnd, &rect);
 
     /* Retrieve the window position */
     point.x = point.y = 0;
-    ClientToScreen( p_vout->p_sys->hwnd, &point );
+    ClientToScreen(sys->hwnd, &point);
 
     /* If nothing changed, we can return */
-    bool b_changed;
-    EventThreadUpdateWindowPosition( p_vout->p_sys->p_event, &b_changed,
-                                     point.x, point.y,
-                                     rect.right, rect.bottom );
-    if( !b_force && !b_changed )
+    bool has_changed;
+    EventThreadUpdateWindowPosition(sys->event, &has_changed,
+                                    point.x, point.y,
+                                    rect.right, rect.bottom);
+    if (!is_forced && !has_changed)
         return;
 
+    /* */
+    if (!cfg)
+        cfg = vd->cfg;
+    if (!source)
+        source = &vd->source;
+
     /* Update the window position and size */
-    vout_PlacePicture( p_vout, rect.right, rect.bottom,
-                       &i_x, &i_y, &i_width, &i_height );
+    vout_display_cfg_t place_cfg = *cfg;
+    place_cfg.display.width  = rect.right;
+    place_cfg.display.height = rect.bottom;
+
+    vout_display_place_t place;
+    vout_display_PlacePicture(&place, source, &place_cfg, true);
 
-    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 );
+    EventThreadUpdateSourceAndPlace(sys->event, source, &place);
+
+    if (sys->hvideownd)
+        SetWindowPos(sys->hvideownd, 0,
+                     place.x, place.y, place.width, place.height,
+                     SWP_NOCOPYBITS|SWP_NOZORDER|SWP_ASYNCWINDOWPOS);
 
     /* Destination image position and dimensions */
 #if defined(MODULE_NAME_IS_direct3d)
     rect_dest.left   = 0;
-    rect_dest.right  = i_width;
+    rect_dest.right  = place.width;
     rect_dest.top    = 0;
-    rect_dest.bottom = i_height;
+    rect_dest.bottom = place.height;
 #else
-    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;
+    rect_dest.left = point.x + place.x;
+    rect_dest.right = rect_dest.left + place.width;
+    rect_dest.top = point.y + place.y;
+    rect_dest.bottom = rect_dest.top + place.height;
 
 #ifdef MODULE_NAME_IS_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;
+    if (sys->b_using_overlay) {
+        if (sys->i_align_dest_boundary)
+            rect_dest.left = (rect_dest.left +
+                              sys->i_align_dest_boundary / 2) &
+                                        ~sys->i_align_dest_boundary;
+
+        if (sys->i_align_dest_size)
+            rect_dest.right = ((rect_dest.right -
+                                rect_dest.left +
+                                sys->i_align_dest_size / 2) &
+                                    ~sys->i_align_dest_size) + rect_dest.left;
     }
 #endif
 
@@ -364,18 +300,17 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
      * It is also needed for d3d to avoid exceding our surface size */
 
     /* Clip the destination window */
-    if( !IntersectRect( &rect_dest_clipped, &rect_dest,
-                        &p_vout->p_sys->rect_display ) )
-    {
-        SetRectEmpty( &rect_src_clipped );
+    if (!IntersectRect(&rect_dest_clipped, &rect_dest,
+                       &sys->rect_display)) {
+        SetRectEmpty(&rect_src_clipped);
         return;
     }
 
 #ifndef NDEBUG
-    msg_Dbg( p_vout, "DirectXUpdateRects image_dst_clipped coords:"
-                     " %li,%li,%li,%li",
-                     rect_dest_clipped.left, rect_dest_clipped.top,
-                     rect_dest_clipped.right, rect_dest_clipped.bottom );
+    msg_Dbg(vd, "DirectXUpdateRects image_dst_clipped coords:"
+                " %li,%li,%li,%li",
+                rect_dest_clipped.left, rect_dest_clipped.top,
+                rect_dest_clipped.right, rect_dest_clipped.bottom);
 #endif
 
 #else
@@ -386,49 +321,48 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
 #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 );
+    if ((rect_dest_clipped.right - rect_dest_clipped.left) == 0 ||
+        (rect_dest_clipped.bottom - rect_dest_clipped.top) == 0) {
+        SetRectEmpty(&rect_src_clipped);
         return;
     }
 
     /* src image dimensions */
-    rect_src.left = 0;
-    rect_src.top = 0;
-    rect_src.right = p_vout->render.i_width;
-    rect_src.bottom = p_vout->render.i_height;
+    rect_src.left   = 0;
+    rect_src.top    = 0;
+    rect_src.right  = source->i_width;
+    rect_src.bottom = source->i_height;
 
     /* Clip the source image */
-    rect_src_clipped.left = p_vout->fmt_out.i_x_offset +
+    rect_src_clipped.left = source->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 -
+      source->i_visible_width / (rect_dest.right - rect_dest.left);
+    rect_src_clipped.right = source->i_x_offset +
+      source->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 +
+      source->i_visible_width / (rect_dest.right - rect_dest.left);
+    rect_src_clipped.top = source->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 -
+      source->i_visible_height / (rect_dest.bottom - rect_dest.top);
+    rect_src_clipped.bottom = source->i_y_offset +
+      source->i_visible_height -
       (rect_dest.bottom - rect_dest_clipped.bottom) *
-      p_vout->fmt_out.i_visible_height / (rect_dest.bottom - rect_dest.top);
+      source->i_visible_height / (rect_dest.bottom - rect_dest.top);
 
 #ifdef MODULE_NAME_IS_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;
+    if (sys->b_using_overlay) {
+        if (sys->i_align_src_boundary)
+            rect_src_clipped.left =
+                (rect_src_clipped.left +
+                 sys->i_align_src_boundary / 2) &
+                            ~sys->i_align_src_boundary;
+
+        if (sys->i_align_src_size)
+            rect_src_clipped.right =
+                ((rect_src_clipped.right - rect_src_clipped.left +
+                  sys->i_align_src_size / 2) &
+                            ~sys->i_align_src_size) + rect_src_clipped.left;
     }
 #elif defined(MODULE_NAME_IS_direct3d)
     /* Needed at least with YUV content */
@@ -439,59 +373,57 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
 #endif
 
 #ifndef NDEBUG
-    msg_Dbg( p_vout, "DirectXUpdateRects image_src_clipped"
-                     " coords: %li,%li,%li,%li",
-                     rect_src_clipped.left, rect_src_clipped.top,
-                     rect_src_clipped.right, rect_src_clipped.bottom );
+    msg_Dbg(vd, "DirectXUpdateRects image_src_clipped"
+                " coords: %li,%li,%li,%li",
+                rect_src_clipped.left, rect_src_clipped.top,
+                rect_src_clipped.right, rect_src_clipped.bottom);
 #endif
 
 #ifdef MODULE_NAME_IS_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;
+    rect_dest_clipped.left -= sys->rect_display.left;
+    rect_dest_clipped.right -= sys->rect_display.left;
+    rect_dest_clipped.top -= sys->rect_display.top;
+    rect_dest_clipped.bottom -= sys->rect_display.top;
 
-    if( p_vout->p_sys->b_using_overlay )
-        DirectDrawUpdateOverlay( p_vout );
+    if (sys->b_using_overlay)
+        DirectDrawUpdateOverlay(vd);
 #endif
 
 #ifndef UNDER_CE
     /* Windows 7 taskbar thumbnail code */
-    LPTASKBARLIST3 p_taskbl;
+    LPTASKBARLIST3 taskbl;
     OSVERSIONINFO winVer;
     winVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-    if( GetVersionEx(&winVer) && winVer.dwMajorVersion > 5 )
-    {
-        CoInitialize( 0 );
-
-        if( S_OK == CoCreateInstance( &clsid_ITaskbarList,
-                    NULL, CLSCTX_INPROC_SERVER,
-                    &IID_ITaskbarList3,
-                    &p_taskbl) )
-        {
+    if (GetVersionEx(&winVer) && winVer.dwMajorVersion > 5) {
+        CoInitialize(0);
+
+        if (S_OK == CoCreateInstance(&clsid_ITaskbarList,
+                                     NULL, CLSCTX_INPROC_SERVER,
+                                     &IID_ITaskbarList3,
+                                     &taskbl)) {
             RECT rect_video, rect_parent, rect_relative;
-            HWND hroot = GetAncestor(p_vout->p_sys->hwnd,GA_ROOT);
+            HWND hroot = GetAncestor(sys->hwnd,GA_ROOT);
 
-            p_taskbl->vt->HrInit(p_taskbl);
-            GetWindowRect(p_vout->p_sys->hvideownd, &rect_video);
+            taskbl->vt->HrInit(taskbl);
+            GetWindowRect(sys->hvideownd, &rect_video);
             GetWindowRect(hroot, &rect_parent);
             rect_relative.left = rect_video.left - rect_parent.left - 8;
             rect_relative.right = rect_video.right - rect_video.left + rect_relative.left;
             rect_relative.top = rect_video.top - rect_parent.top - 10;
             rect_relative.bottom = rect_video.bottom - rect_video.top + rect_relative.top - 25;
 
-            if (S_OK != p_taskbl->vt->SetThumbnailClip(p_taskbl, hroot, &rect_relative))
-                msg_Err( p_vout, "SetThumbNailClip failed");
+            if (S_OK != taskbl->vt->SetThumbnailClip(taskbl, hroot, &rect_relative))
+                msg_Err(vd, "SetThumbNailClip failed");
 
-            p_taskbl->vt->Release(p_taskbl);
+            taskbl->vt->Release(taskbl);
         }
         CoUninitialize();
     }
 #endif
     /* Signal the change in size/position */
-    p_vout->p_sys->i_changes |= DX_POSITION_CHANGE;
+    sys->changes |= DX_POSITION_CHANGE;
 
 #undef rect_src
 #undef rect_src_clipped
@@ -499,254 +431,238 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
 #undef rect_dest_clipped
 }
 
-/*****************************************************************************
- * Control: control facility for the vout
- *****************************************************************************/
-int Control( vout_thread_t *p_vout, int i_query, va_list args )
+static int CommonControlSetFullscreen(vout_display_t *vd, bool is_fullscreen)
 {
-    RECT rect_window;
-
-    switch( i_query )
-    {
-    case VOUT_SET_SIZE:
-        if( p_vout->p_sys->parent_window )
-            return vaControlParentWindow( p_vout, 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, EventThreadGetWindowStyle( p_vout->p_sys->p_event ), 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_SET_STAY_ON_TOP:
-        if( p_vout->p_sys->hparent && !var_GetBool( p_vout, "fullscreen" ) )
-            return vaControlParentWindow( p_vout, i_query, args );
+    vout_display_sys_t *sys = vd->sys;
 
-        p_vout->p_sys->b_on_top_change = true;
-        return VLC_SUCCESS;
-
-    default:
-        return VLC_EGENERIC;
-    }
-}
-
-
-/* Internal wrapper over GetWindowPlacement */
-static WINDOWPLACEMENT getWindowState(HWND hwnd)
-{
-    WINDOWPLACEMENT window_placement;
-    window_placement.length = sizeof(WINDOWPLACEMENT);
-    GetWindowPlacement( hwnd, &window_placement );
-    return window_placement;
-}
-
-/* Internal wrapper to call vout_ControlWindow for hparent */
-static int vaControlParentWindow( vout_thread_t *p_vout, int i_query,
-                                   va_list args )
-{
-    switch( i_query )
-    {
-    case VOUT_SET_SIZE:
-    {
-        const unsigned i_width  = va_arg(args, unsigned);
-        const unsigned i_height = va_arg(args, unsigned);
-        return vout_window_SetSize( p_vout->p_sys->parent_window, i_width, i_height );
-    }
-    case VOUT_SET_STAY_ON_TOP:
-    {
-        const bool is_on_top = va_arg(args, int);
-        return vout_window_SetOnTop( p_vout->p_sys->parent_window, is_on_top );
-    }
-    default:
+#ifdef MODULE_NAME_IS_direct3d
+    if (sys->use_desktop && is_fullscreen)
         return VLC_EGENERIC;
-    }
-}
-
-#if 0
-static int ControlParentWindow( vout_thread_t *p_vout, int i_query, ... )
-{
-    va_list args;
-    int ret;
-
-    va_start( args, i_query );
-    ret = vaControlParentWindow( p_vout, i_query, args );
-    va_end( args );
-    return ret;
-}
 #endif
 
-void ExitFullscreen( vout_thread_t *p_vout )
-{
-    if( p_vout->b_fullscreen )
-    {
-        msg_Dbg( p_vout, "Quitting fullscreen" );
-        Win32ToggleFullscreen( p_vout );
-        /* Force fullscreen in the core for the next video */
-        var_SetBool( p_vout, "fullscreen", true );
-    }
-}
+    /* */
+    if (sys->parent_window)
+        return vout_window_SetFullScreen(sys->parent_window, is_fullscreen);
 
-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;
+    /* */
+    HWND hwnd = sys->hparent && sys->hfswnd ? sys->hfswnd : sys->hwnd;
 
     /* Save the current windows placement/placement to restore
        when fullscreen is over */
-    WINDOWPLACEMENT window_placement = getWindowState( hwnd );
-
-    p_vout->b_fullscreen = ! p_vout->b_fullscreen;
+    WINDOWPLACEMENT window_placement;
+    window_placement.length = sizeof(WINDOWPLACEMENT);
+    GetWindowPlacement(hwnd, &window_placement);
 
-    /* We want to go to Fullscreen */
-    if( p_vout->b_fullscreen )
-    {
-        msg_Dbg( p_vout, "entering fullscreen mode" );
+    if (is_fullscreen) {
+        msg_Dbg(vd, "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 );
+        SetWindowLong(hwnd, GWL_STYLE, WS_CLIPCHILDREN | WS_VISIBLE);
 
-        if( p_vout->p_sys->hparent )
-        {
+        if (sys->hparent) {
 #ifdef UNDER_CE
             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 );
+            ClientToScreen(sys->hwnd, &point);
+            GetClientRect(sys->hwnd, &rect);
+            SetWindowPos(hwnd, 0, point.x, point.y,
+                         rect.right, rect.bottom,
+                         SWP_NOZORDER|SWP_FRAMECHANGED);
 #else
             /* Retrieve current window position so fullscreen will happen
             *on the right screen */
-            HMONITOR hmon = MonitorFromWindow(p_vout->p_sys->hparent,
-                                            MONITOR_DEFAULTTONEAREST);
+            HMONITOR hmon = MonitorFromWindow(sys->hparent,
+                                              MONITOR_DEFAULTTONEAREST);
             MONITORINFO mi;
             mi.cbSize = sizeof(MONITORINFO);
             if (GetMonitorInfo(hmon, &mi))
-            SetWindowPos( hwnd, 0,
-                            mi.rcMonitor.left,
-                            mi.rcMonitor.top,
-                            mi.rcMonitor.right - mi.rcMonitor.left,
-                            mi.rcMonitor.bottom - mi.rcMonitor.top,
-                            SWP_NOZORDER|SWP_FRAMECHANGED );
+                SetWindowPos(hwnd, 0,
+                             mi.rcMonitor.left,
+                             mi.rcMonitor.top,
+                             mi.rcMonitor.right - mi.rcMonitor.left,
+                             mi.rcMonitor.bottom - mi.rcMonitor.top,
+                             SWP_NOZORDER|SWP_FRAMECHANGED);
 #endif
-        }
-        else
-        {
+        } else {
             /* Maximize non embedded window */
-            ShowWindow( hwnd, SW_SHOWMAXIMIZED );
+            ShowWindow(hwnd, SW_SHOWMAXIMIZED);
         }
 
-        if( p_vout->p_sys->hparent )
-        {
+        if (sys->hparent) {
             /* Hide the previous window */
             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 );
+            GetClientRect(hwnd, &rect);
+            SetParent(sys->hwnd, hwnd);
+            SetWindowPos(sys->hwnd, 0, 0, 0,
+                         rect.right, rect.bottom,
+                         SWP_NOZORDER|SWP_FRAMECHANGED);
 
 #ifdef UNDER_CE
-            HWND topLevelParent = GetParent( p_vout->p_sys->hparent );
+            HWND topLevelParent = GetParent(sys->hparent);
 #else
-            HWND topLevelParent = GetAncestor( p_vout->p_sys->hparent, GA_ROOT );
+            HWND topLevelParent = GetAncestor(sys->hparent, GA_ROOT);
 #endif
-            ShowWindow( topLevelParent, SW_HIDE );
+            ShowWindow(topLevelParent, SW_HIDE);
         }
+        SetForegroundWindow(hwnd);
+    } else {
+        msg_Dbg(vd, "leaving fullscreen mode");
 
-        SetForegroundWindow( hwnd );
-    }
-    else
-    {
-        msg_Dbg( p_vout, "leaving fullscreen mode" );
         /* Change window style, no borders and no title bar */
-        SetWindowLong( hwnd, GWL_STYLE, EventThreadGetWindowStyle( p_vout->p_sys->p_event ) );
+        SetWindowLong(hwnd, GWL_STYLE, EventThreadGetWindowStyle(sys->event));
 
-        if( p_vout->p_sys->hparent )
-        {
+        if (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 );
+            GetClientRect(sys->hparent, &rect);
+            SetParent(sys->hwnd, sys->hparent);
+            SetWindowPos(sys->hwnd, 0, 0, 0,
+                         rect.right, rect.bottom,
+                         SWP_NOZORDER|SWP_FRAMECHANGED);
 
 #ifdef UNDER_CE
-            HWND topLevelParent = GetParent( p_vout->p_sys->hparent );
+            HWND topLevelParent = GetParent(sys->hparent);
 #else
-            HWND topLevelParent = GetAncestor( p_vout->p_sys->hparent, GA_ROOT );
+            HWND topLevelParent = GetAncestor(sys->hparent, GA_ROOT);
 #endif
-            ShowWindow( topLevelParent, SW_SHOW );
-            SetForegroundWindow( p_vout->p_sys->hparent );
-            ShowWindow( hwnd, SW_HIDE );
-        }
-        else
-        {
+            ShowWindow(topLevelParent, SW_SHOW);
+            SetForegroundWindow(sys->hparent);
+            ShowWindow(hwnd, SW_HIDE);
+        } else {
             /* return to normal window for non embedded vout */
-            SetWindowPlacement( hwnd, &window_placement );
-            ShowWindow( hwnd, SW_SHOWNORMAL );
+            SetWindowPlacement(hwnd, &window_placement);
+            ShowWindow(hwnd, SW_SHOWNORMAL);
         }
 
         /* Make sure the mouse cursor is displayed */
-        EventThreadMouseShow( p_vout->p_sys->p_event );
+        EventThreadMouseShow(sys->event);
     }
+    return VLC_SUCCESS;
+}
 
-    /* Update the object variable and trigger callback */
-    var_SetBool( p_vout, "fullscreen", p_vout->b_fullscreen );
+int CommonControl(vout_display_t *vd, int query, va_list args)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    switch (query) {
+    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:   /* const vout_display_cfg_t *p_cfg, int is_forced */
+    case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: /* const vout_display_cfg_t *p_cfg */
+    case VOUT_DISPLAY_CHANGE_ZOOM:           /* const vout_display_cfg_t *p_cfg */
+    case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:  /* const video_format_t *p_source */
+    case VOUT_DISPLAY_CHANGE_SOURCE_CROP: {  /* const video_format_t *p_source */
+        const vout_display_cfg_t *cfg;
+        const video_format_t *source;
+        bool  is_forced = true;
+        if (query == VOUT_DISPLAY_CHANGE_SOURCE_CROP ||
+            query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT) {
+            cfg    = vd->cfg;
+            source = va_arg(args, const video_format_t *);
+        } else {
+            cfg    = va_arg(args, const vout_display_cfg_t *);
+            source = &vd->source;
+            if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE)
+                is_forced = va_arg(args, int);
+        }
+        if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE && is_forced) {
+            /* Update dimensions */
+            if (sys->parent_window) {
+                vout_window_SetSize(sys->parent_window, cfg->display.width, cfg->display.height);
+            } else {
+                RECT rect_window;
+                rect_window.top    = 0;
+                rect_window.left   = 0;
+                rect_window.right  = cfg->display.width;
+                rect_window.bottom = cfg->display.height;
+                AdjustWindowRect(&rect_window, EventThreadGetWindowStyle(sys->event), 0);
+
+                SetWindowPos(sys->hwnd, 0, 0, 0,
+                             rect_window.right - rect_window.left,
+                             rect_window.bottom - rect_window.top, SWP_NOMOVE);
+            }
+        }
+        UpdateRects(vd, cfg, source, is_forced);
+        return VLC_SUCCESS;
+    }
+    case VOUT_DISPLAY_CHANGE_ON_TOP: {       /* int b_on_top */
+        const bool is_on_top = va_arg(args, int);
+#ifdef MODULE_NAME_IS_direct3d
+        if (sys->use_desktop && is_on_top)
+            return VLC_EGENERIC;
+#endif
+        if (sys->parent_window) {
+            if (vout_window_SetOnTop(sys->parent_window, is_on_top))
+                return VLC_EGENERIC;
+        } else {
+            HMENU hMenu = GetSystemMenu(sys->hwnd, FALSE);
+
+            if (is_on_top && !(GetWindowLong(sys->hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)) {
+                CheckMenuItem(hMenu, IDM_TOGGLE_ON_TOP, MF_BYCOMMAND | MFS_CHECKED);
+                SetWindowPos(sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+            } else if (!is_on_top && (GetWindowLong(sys->hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)) {
+                CheckMenuItem(hMenu, IDM_TOGGLE_ON_TOP, MF_BYCOMMAND | MFS_UNCHECKED);
+                SetWindowPos(sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+            }
+        }
+        sys->is_on_top = is_on_top;
+        return VLC_SUCCESS;
+    }
+    case VOUT_DISPLAY_CHANGE_FULLSCREEN: {   /* const vout_display_cfg_t *p_cfg */
+        const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);
+        return CommonControlSetFullscreen(vd, cfg->is_fullscreen);
+    }
+
+    case VOUT_DISPLAY_RESET_PICTURES:
+    case VOUT_DISPLAY_HIDE_MOUSE:
+        assert(0);
+    default:
+        return VLC_EGENERIC;
+    }
 }
 
 #ifndef UNDER_CE
-void DisableScreensaver( vout_thread_t *p_vout )
+static void DisableScreensaver(vout_display_t *vd)
 {
+    vout_display_sys_t *sys = vd->sys;
+
     /* 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;
-    if( var_GetBool( p_vout, "disable-screensaver" ) )
-    {
-        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 ) {
+    sys->i_spi_lowpowertimeout = 0;
+    sys->i_spi_powerofftimeout = 0;
+    sys->i_spi_screensavetimeout = 0;
+    if (var_GetBool(vd, "disable-screensaver")) {
+        msg_Dbg(vd, "disabling screen saver");
+        SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT, 0,
+                             &sys->i_spi_lowpowertimeout, 0);
+        if (0 != 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 ) {
+                             &sys->i_spi_powerofftimeout, 0);
+        if (0 != 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 ) {
+                             &sys->i_spi_screensavetimeout, 0);
+        if (0 != sys->i_spi_screensavetimeout) {
             SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 0, NULL, 0);
         }
     }
 }
 
-void RestoreScreensaver( vout_thread_t *p_vout )
+static void RestoreScreensaver(vout_display_t *vd)
 {
+    vout_display_sys_t *sys = vd->sys;
+
     /* restore screensaver system settings */
-    if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {
+    if (0 != sys->i_spi_lowpowertimeout) {
         SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT,
-            p_vout->p_sys->i_spi_lowpowertimeout, NULL, 0);
+                             sys->i_spi_lowpowertimeout, NULL, 0);
     }
-    if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
+    if (0 != sys->i_spi_powerofftimeout) {
         SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT,
-            p_vout->p_sys->i_spi_powerofftimeout, NULL, 0);
+                             sys->i_spi_powerofftimeout, NULL, 0);
     }
-    if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {
+    if (0 != sys->i_spi_screensavetimeout) {
         SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT,
-            p_vout->p_sys->i_spi_screensavetimeout, NULL, 0);
+                             sys->i_spi_screensavetimeout, NULL, 0);
     }
 }
 #endif
diff --git a/modules/video_output/msw/common.h b/modules/video_output/msw/common.h
new file mode 100644 (file)
index 0000000..dc48711
--- /dev/null
@@ -0,0 +1,322 @@
+/*****************************************************************************
+ * common.h: Windows video output header file
+ *****************************************************************************
+ * Copyright (C) 2001-2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *          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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * event_thread_t: event thread
+ *****************************************************************************/
+#include <vlc_picture_pool.h>
+#include "events.h"
+
+#ifdef MODULE_NAME_IS_wingapi
+    typedef struct GXDisplayProperties {
+        DWORD cxWidth;
+        DWORD cyHeight;
+        long cbxPitch;
+        long cbyPitch;
+        long cBPP;
+        DWORD ffFormat;
+    } GXDisplayProperties;
+
+    typedef struct GXScreenRect {
+        DWORD dwTop;
+        DWORD dwLeft;
+        DWORD dwWidth;
+        DWORD dwHeight;
+    } GXScreenRect;
+
+#   define GX_FULLSCREEN    0x01
+#   define GX_NORMALKEYS    0x02
+#   define GX_LANDSCAPEKEYS 0x03
+
+#   ifndef kfLandscape
+#       define kfLandscape      0x8
+#       define kfPalette        0x10
+#       define kfDirect         0x20
+#       define kfDirect555      0x40
+#       define kfDirect565      0x80
+#       define kfDirect888      0x100
+#       define kfDirect444      0x200
+#       define kfDirectInverted 0x400
+#   endif
+
+#endif
+
+/*****************************************************************************
+ * vout_sys_t: video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the module specific properties of an output thread.
+ *****************************************************************************/
+struct vout_display_sys_t
+{
+    /* */
+    event_thread_t *event;
+
+    /* */
+    HWND                 hwnd;                  /* Handle of the main window */
+    HWND                 hvideownd;        /* Handle of the video sub-window */
+    struct vout_window_t *parent_window;         /* Parent window VLC object */
+    HWND                 hparent;             /* Handle of the parent window */
+    HWND                 hfswnd;          /* Handle of the fullscreen window */
+
+    /* 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          display_depth;
+
+    /* size of the overall window (including black bands) */
+    RECT         rect_parent;
+
+    unsigned changes;        /* changes made to the video display */
+
+    /* Misc */
+    bool is_first_display;
+    bool is_on_top;
+
+#ifndef UNDER_CE
+
+    /* screensaver system settings to be restored when vout is closed */
+    UINT i_spi_lowpowertimeout;
+    UINT i_spi_powerofftimeout;
+    UINT i_spi_screensavetimeout;
+
+#endif
+
+    /* 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;
+
+    bool   allow_hw_yuv;    /* Should we use hardware YUV->RGB conversions */
+
+
+#ifdef MODULE_NAME_IS_directx
+    /* Overlay alignment restrictions */
+    int          i_align_src_boundary;
+    int          i_align_src_size;
+    int          i_align_dest_boundary;
+    int          i_align_dest_size;
+
+    bool      b_wallpaper;    /* show as desktop wallpaper ? */
+
+    bool   b_using_overlay;         /* Are we using an overlay surface */
+    bool   b_use_sysmem;   /* Should we use system memory for surfaces */
+    bool   b_3buf_overlay;   /* Should we use triple buffered overlays */
+
+    /* DDraw capabilities */
+    int          b_caps_overlay_clipping;
+
+    unsigned int    i_rgb_colorkey;      /* colorkey in RGB used by the overlay */
+    unsigned 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 */
+    vlc_mutex_t    lock;
+#endif
+
+#ifdef MODULE_NAME_IS_glwin32
+    HDC hGLDC;
+    HGLRC hGLRC;
+#endif
+
+#ifdef MODULE_NAME_IS_direct3d
+    /* show video on desktop window ? */
+    bool use_desktop;
+    struct {
+        bool is_fullscreen;
+        bool is_on_top;
+        RECT win;
+    } desktop_save;
+    vout_display_cfg_t cfg_saved; /* configuration used before going into desktop mode */
+
+    // core objects
+    HINSTANCE               hd3d9_dll;       /* handle of the opened d3d9 dll */
+    LPDIRECT3D9             d3dobj;
+    LPDIRECT3DDEVICE9       d3ddev;
+    D3DPRESENT_PARAMETERS   d3dpp;
+    // scene objects
+    LPDIRECT3DTEXTURE9      d3dtex;
+    LPDIRECT3DVERTEXBUFFER9 d3dvtc;
+
+    picture_resource_t      resource;
+    picture_pool_t          *pool;
+
+    /* */
+    bool                    reset_device;
+    bool                    reopen_device;
+
+    /* It protects the following variables */
+    vlc_mutex_t    lock;
+    bool           ch_desktop;
+    bool           desktop_requested;
+#endif
+
+#ifdef MODULE_NAME_IS_wingdi
+
+    int  i_depth;
+
+    /* Our offscreen bitmap and its framebuffer */
+    HDC        off_dc;
+    HBITMAP    off_bitmap;
+    uint8_t *  p_pic_buffer;
+    int        i_pic_pitch;
+    int        i_pic_pixel_pitch;
+
+    BITMAPINFO bitmapinfo;
+    RGBQUAD    red;
+    RGBQUAD    green;
+    RGBQUAD    blue;
+#endif
+
+#ifdef MODULE_NAME_IS_wingapi
+    int        i_depth;
+    int        render_width;
+    int        render_height;
+           /* Our offscreen bitmap and its framebuffer */
+    HDC        off_dc;
+    HBITMAP    off_bitmap;
+    uint8_t *  p_pic_buffer;
+    int        i_pic_pitch;
+    int        i_pic_pixel_pitch;
+
+    BITMAPINFO bitmapinfo;
+    RGBQUAD    red;
+    RGBQUAD    green;
+    RGBQUAD    blue;
+
+    HINSTANCE  gapi_dll;                   /* handle of the opened gapi dll */
+
+    /* GAPI functions */
+    int (*GXOpenDisplay)(HWND hWnd, DWORD dwFlags);
+    int (*GXCloseDisplay)();
+    void *(*GXBeginDraw)();
+    int (*GXEndDraw)();
+    GXDisplayProperties (*GXGetDisplayProperties)();
+    int (*GXSuspend)();
+    int (*GXResume)();
+#endif
+};
+
+#ifdef MODULE_NAME_IS_wingapi
+#   define GXOpenDisplay p_vout->p_sys->GXOpenDisplay
+#   define GXCloseDisplay p_vout->p_sys->GXCloseDisplay
+#   define GXBeginDraw p_vout->p_sys->GXBeginDraw
+#   define GXEndDraw p_vout->p_sys->GXEndDraw
+#   define GXGetDisplayProperties p_vout->p_sys->GXGetDisplayProperties
+#   define GXSuspend p_vout->p_sys->GXSuspend
+#   define GXResume p_vout->p_sys->GXResume
+#endif
+
+/*****************************************************************************
+ * Prototypes from directx.c
+ *****************************************************************************/
+int DirectDrawUpdateOverlay(vout_display_t *);
+
+/*****************************************************************************
+ * Prototypes from common.c
+ *****************************************************************************/
+int  CommonInit(vout_display_t *);
+void CommonClean(vout_display_t *);
+void CommonManage(vout_display_t *);
+int  CommonControl(vout_display_t *, int , va_list );
+
+void UpdateRects (vout_display_t *,
+                  const vout_display_cfg_t *,
+                  const video_format_t *,
+                  bool is_forced);
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+#define IDM_TOGGLE_ON_TOP WM_USER + 1
+#define DX_POSITION_CHANGE 0x1000
+#define DX_WALLPAPER_CHANGE 0x2000
+#define DX_DESKTOP_CHANGE 0x4000
+
+/*****************************************************************************
+ * 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
index 85249a0b5e2af5e437f67737fced5c0d3d516b2d..ef62ed54cdf28e28906fde3bc69e29f797b71422 100644 (file)
@@ -40,7 +40,7 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_playlist.h>
-#include <vlc_vout.h>
+#include <vlc_vout_display.h>
 
 #include <windows.h>
 #include <d3d9.h>
@@ -63,20 +63,19 @@ vlc_module_begin ()
     set_category(CAT_VIDEO)
     set_subcategory(SUBCAT_VIDEO_VOUT)
 
-    add_bool("direct3d-desktop", false, NULL, DESKTOP_TEXT, DESKTOP_LONGTEXT,
-              true)
+    add_bool("direct3d-desktop", false, NULL, DESKTOP_TEXT, DESKTOP_LONGTEXT, true)
 
     set_description(N_("DirectX 3D video output"))
-    set_capability("video output", 50)
-    add_shortcut("direct3d")
+    set_capability("vout display", 50)
+    add_shortcut("direct3d_xp")
     set_callbacks(OpenVideoXP, Close)
 
     /* FIXME: Hack to avoid unregistering our window class */
-    linked_with_a_crap_library_which_uses_atexit ()
+    linked_with_a_crap_library_which_uses_atexit()
 
     add_submodule()
         set_capability("video output", 150)
-        add_shortcut("direct3d")
+        add_shortcut("direct3d_vista")
         set_callbacks(OpenVideoVista, Close)
 vlc_module_end ()
 
@@ -91,92 +90,106 @@ vlc_module_end ()
 /*****************************************************************************
  * Local prototypes.
  *****************************************************************************/
-static int  Open(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 Direct3DCreate     (vout_thread_t *);
-static void Direct3DRelease   (vout_thread_t *);
+struct picture_sys_t
+{
+    LPDIRECT3DSURFACE9 surface;
+};
 
-static int  Direct3DOpen      (vout_thread_t *);
-static void Direct3DClose     (vout_thread_t *);
+static int  Open(vlc_object_t *);
 
-static int Direct3DResetDevice(vout_thread_t *);
+static picture_t *Get    (vout_display_t *);
+static void       Prepare(vout_display_t *, picture_t *);
+static void       Display(vout_display_t *, picture_t *);
+static int        Control(vout_display_t *, int, va_list);
+static void       Manage (vout_display_t *);
 
-static int Direct3DCreatePictures   (vout_thread_t *, size_t);
-static void Direct3DReleasePictures (vout_thread_t *);
+static int  Direct3DCreate (vout_display_t *);
+static int  Direct3DReset  (vout_display_t *);
+static void Direct3DDestroy(vout_display_t *);
 
-static int Direct3DLockSurface  (vout_thread_t *, picture_t *);
-static int Direct3DUnlockSurface(vout_thread_t *, picture_t *);
+static int  Direct3DOpen (vout_display_t *, video_format_t *);
+static void Direct3DClose(vout_display_t *);
 
-static int Direct3DCreateScene      (vout_thread_t *);
-static void Direct3DReleaseScene    (vout_thread_t *);
-static void Direct3DRenderScene     (vout_thread_t *, picture_t *);
+static void Direct3DRenderScene(vout_display_t *vd, LPDIRECT3DSURFACE9 surface);
 
+/* */
 static int DesktopCallback(vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void *);
 
-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)
-
 /**
  * It creates a Direct3D vout display.
  */
 static int Open(vlc_object_t *object)
 {
-    vout_thread_t *p_vout = (vout_thread_t *)object;
-    vout_sys_t *p_sys;
+    vout_display_t *vd = (vout_display_t *)object;
+    vout_display_sys_t *sys;
 
     /* Allocate structure */
-    p_vout->p_sys = p_sys = calloc(1, sizeof(vout_sys_t));
-    if (!p_sys)
+    vd->sys = sys = calloc(1, sizeof(vout_display_sys_t));
+    if (!sys)
         return VLC_ENOMEM;
 
-    if (VLC_SUCCESS != Direct3DCreate(p_vout)) {
-        msg_Err(p_vout, "Direct3D could not be initialized !");
-        Direct3DRelease(p_vout);
-        free(p_sys);
+    if (Direct3DCreate(vd)) {
+        msg_Err(vd, "Direct3D could not be initialized");
+        Direct3DDestroy(vd);
+        free(sys);
         return VLC_EGENERIC;
     }
 
-    p_sys->b_desktop = false;
-
-    /* Initialisations */
-    p_vout->pf_init = Init;
-    p_vout->pf_end = End;
-    p_vout->pf_manage = Manage;
-    p_vout->pf_render = Direct3DRenderScene;
-    p_vout->pf_display = FirstDisplay;
-    p_vout->pf_control = Control;
+    sys->use_desktop = var_CreateGetBool(vd, "direct3d-desktop");
+    sys->reset_device = false;
+    sys->reset_device = false;
+    sys->allow_hw_yuv = var_CreateGetBool(vd, "directx-hw-yuv");
+    sys->desktop_save.is_fullscreen = vd->cfg->is_fullscreen;
+    sys->desktop_save.is_on_top     = false;
+    sys->desktop_save.win.left      = 0;
+    sys->desktop_save.win.right     = vd->cfg->display.width;
+    sys->desktop_save.win.top       = 0;
+    sys->desktop_save.win.bottom    = vd->cfg->display.height;
+
+    if (CommonInit(vd))
+        goto error;
 
-    if (CommonInit(p_vout))
+    /* */
+    video_format_t fmt;
+    if (Direct3DOpen(vd, &fmt)) {
+        msg_Err(vd, "Direct3D could not be opened");
         goto error;
+    }
 
-    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);
+    /* */
+    vout_display_info_t info = vd->info;
+    info.is_slow = true;
+    info.has_double_click = true;
+    info.has_hide_mouse = true;
+    info.has_pictures_invalid = true;
+
+    /* Interaction */
+    vlc_mutex_init(&sys->lock);
+    sys->ch_desktop = false;
+    sys->desktop_requested = sys->use_desktop;
 
-    /* Trigger a callback right now */
-    var_Create(p_vout, "direct3d-desktop", VLC_VAR_BOOL|VLC_VAR_DOINHERIT);
     vlc_value_t val;
     val.psz_string = _("Desktop");
-    var_Change(p_vout, "direct3d-desktop", VLC_VAR_SETTEXT, &val, NULL);
-    var_AddCallback(p_vout, "direct3d-desktop", DesktopCallback, NULL);
-    var_TriggerCallback(p_vout, "direct3d-desktop");
+    var_Change(vd, "direct3d-desktop", VLC_VAR_SETTEXT, &val, NULL);
+    var_AddCallback(vd, "direct3d-desktop", DesktopCallback, NULL);
 
-    return VLC_SUCCESS;
+    /* Setup vout_display now that everything is fine */
+    vd->fmt  = fmt;
+    vd->info = info;
 
+    vd->get     = Get;
+    vd->prepare = Prepare;
+    vd->display = Display;
+    vd->control = Control;
+    vd->manage  = Manage;
+
+    /* Fix state in case of desktop mode */
+    if (sys->use_desktop && vd->cfg->is_fullscreen)
+        vout_display_SendEventFullscreen(vd, false);
+
+    return VLC_SUCCESS;
 error:
-    Close(VLC_OBJECT(p_vout));
+    Close(VLC_OBJECT(vd));
     return VLC_EGENERIC;
 }
 
@@ -204,92 +217,212 @@ static int OpenVideoVista(vlc_object_t *obj)
  */
 static void Close(vlc_object_t *object)
 {
-    vout_thread_t * p_vout = (vout_thread_t *)object;
+    vout_display_t * vd = (vout_display_t *)object;
+
+    var_DelCallback(vd, "direct3d-desktop", DesktopCallback, NULL);
 
-    CommonClean(p_vout);
+    Direct3DClose(vd);
 
-    Direct3DRelease(p_vout);
+    CommonClean(vd);
 
-    free(p_vout->p_sys);
+    Direct3DDestroy(vd);
+
+    free(vd->sys);
 }
 
-/*****************************************************************************
- * Init: initialize Direct3D video thread output method
- *****************************************************************************/
-static int Init(vout_thread_t *p_vout)
+/* */
+static picture_t *Get(vout_display_t *vd)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
-    int i_ret;
+    vout_display_sys_t *sys = vd->sys;
 
-    p_sys->b_hw_yuv = var_GetBool(p_vout, "directx-hw-yuv");
+    if (!sys->pool)
+        return NULL;
+    return picture_pool_Get(sys->pool);
+}
 
-    /* Initialise Direct3D */
-    if (Direct3DOpen(p_vout)) {
-        msg_Err(p_vout, "cannot initialize Direct3D");
-        return VLC_EGENERIC;
+static int  Direct3DLockSurface(picture_t *);
+static void Direct3DUnlockSurface(picture_t *);
+
+static void Prepare(vout_display_t *vd, picture_t *picture)
+{
+    LPDIRECT3DSURFACE9 surface = picture->p_sys->surface;
+#if 0
+    picture_Release(picture);
+    Direct3DRenderScene(vd, surface);
+#else
+    /* FIXME it is a bit ugly, we need the surface to be unlocked for
+     * rendering.
+     *  The clean way would be to release the picture (and ensure that
+     * the vout doesn't keep a reference). But because of the vout
+     * wrapper, we can't */
+
+    Direct3DUnlockSurface(picture);
+
+    Direct3DRenderScene(vd, surface);
+
+    Direct3DLockSurface(picture);
+#endif
+}
+
+static void Display(vout_display_t *vd, picture_t *picture)
+{
+    vout_display_sys_t *sys = vd->sys;
+    LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev;
+
+    // Present the back buffer contents to the display
+    // No stretching should happen here !
+    const RECT src = sys->rect_dest_clipped;
+    const RECT dst = sys->rect_dest_clipped;
+    HRESULT hr = IDirect3DDevice9_Present(d3ddev, &src, &dst, NULL, NULL);
+    if (FAILED(hr)) {
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
     }
 
-    /* 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;
-    UpdateRects(p_vout, true);
-
-    /*  create picture pool */
-    p_vout->output.i_chroma = 0;
-    i_ret = Direct3DCreatePictures(p_vout, 1);
-    if (i_ret) {
-        msg_Err(p_vout, "Direct3D picture pool initialization failed !");
-        return i_ret;
+    if (sys->is_first_display) {
+        /* Video window is initially hidden, show it now since we got a
+         * picture to show.
+         */
+        SetWindowPos(vd->sys->hvideownd, 0, 0, 0, 0, 0,
+                     SWP_ASYNCWINDOWPOS|
+                     SWP_FRAMECHANGED|
+                     SWP_SHOWWINDOW|
+                     SWP_NOMOVE|
+                     SWP_NOSIZE|
+                     SWP_NOZORDER);
+        sys->is_first_display = false;
     }
 
-    /* create scene */
-    i_ret = Direct3DCreateScene(p_vout);
-    if (i_ret) {
-        msg_Err(p_vout, "Direct3D scene initialization failed !");
-        Direct3DReleasePictures(p_vout);
-        return i_ret;
+#if 0
+    VLC_UNUSED(picture);
+#else
+    /* XXX See Prepare() */
+    picture_Release(picture);
+#endif
+}
+static int ControlResetDevice(vout_display_t *vd)
+{
+    return Direct3DReset(vd);
+}
+static int ControlReopenDevice(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    if (!sys->use_desktop) {
+        /* Save non-desktop state */
+        sys->desktop_save.is_fullscreen = vd->cfg->is_fullscreen;
+        sys->desktop_save.is_on_top     = sys->is_on_top;
+
+        WINDOWPLACEMENT wp = { .length = sizeof(wp), };
+        GetWindowPlacement(sys->hparent ? sys->hparent : sys->hwnd, &wp);
+        sys->desktop_save.win = wp.rcNormalPosition;
     }
 
-    /* Change the window title bar text */
-    EventThreadUpdateTitle(p_sys->p_event, VOUT_TITLE " (Direct3D output)");
+    /* */
+    Direct3DClose(vd);
+    EventThreadStop(sys->event);
+
+    /* */
+    vlc_mutex_lock(&sys->lock);
+    sys->use_desktop = sys->desktop_requested;
+    sys->ch_desktop = false;
+    vlc_mutex_unlock(&sys->lock);
 
-    p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
+    /* */
+    event_cfg_t cfg;
+    memset(&cfg, 0, sizeof(cfg));
+    cfg.use_desktop = sys->use_desktop;
+    if (!sys->use_desktop) {
+        cfg.win.type   = VOUT_WINDOW_TYPE_HWND;
+        cfg.win.x      = sys->desktop_save.win.left;
+        cfg.win.y      = sys->desktop_save.win.top;
+        cfg.win.width  = sys->desktop_save.win.right  - sys->desktop_save.win.left;
+        cfg.win.height = sys->desktop_save.win.bottom - sys->desktop_save.win.top;
+    }
+
+    event_hwnd_t hwnd;
+    if (EventThreadStart(sys->event, &hwnd, &cfg)) {
+        msg_Err(vd, "Failed to restart event thread");
+        return VLC_EGENERIC;
+    }
+    sys->parent_window = hwnd.parent_window;
+    sys->hparent       = hwnd.hparent;
+    sys->hwnd          = hwnd.hwnd;
+    sys->hvideownd     = hwnd.hvideownd;
+    sys->hfswnd        = hwnd.hfswnd;
+    SetRectEmpty(&sys->rect_parent);
+
+    /* */
+    video_format_t fmt;
+    if (Direct3DOpen(vd, &fmt)) {
+        CommonClean(vd);
+        msg_Err(vd, "Failed to reopen device");
+        return VLC_EGENERIC;
+    }
+    vd->fmt = fmt;
+    sys->is_first_display = true;
+
+    if (sys->use_desktop) {
+        /* Disable fullscreen/on_top while using desktop */
+        if (sys->desktop_save.is_fullscreen)
+            vout_display_SendEventFullscreen(vd, false);
+        if (sys->desktop_save.is_on_top)
+            vout_display_SendEventOnTop(vd, false);
+    } else {
+        /* Restore fullscreen/on_top */
+        if (sys->desktop_save.is_fullscreen)
+            vout_display_SendEventFullscreen(vd, true);
+        if (sys->desktop_save.is_on_top)
+            vout_display_SendEventOnTop(vd, true);
+    }
     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)
+static int Control(vout_display_t *vd, int query, va_list args)
 {
-    Direct3DReleaseScene(p_vout);
-    Direct3DReleasePictures(p_vout);
-    Direct3DClose(p_vout);
+    vout_display_sys_t *sys = vd->sys;
+
+    switch (query) {
+    case VOUT_DISPLAY_RESET_PICTURES:
+        /* FIXME what to do here in case of failure */
+        if (sys->reset_device) {
+            if (ControlResetDevice(vd)) {
+                msg_Err(vd, "Failed to reset device");
+                return VLC_EGENERIC;
+            }
+            sys->reset_device = false;
+        } else if(sys->reopen_device) {
+            if (ControlReopenDevice(vd)) {
+                msg_Err(vd, "Failed to reopen device");
+                return VLC_EGENERIC;
+            }
+            sys->reopen_device = false;
+        }
+        return VLC_SUCCESS;
+    default:
+        return CommonControl(vd, query, args);
+    }
 }
-
-/*****************************************************************************
- * 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)
+static void Manage (vout_display_t *vd)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
+    vout_display_sys_t *sys = vd->sys;
+
+    CommonManage(vd);
 
-    CommonManage(p_vout);
+    /* Desktop mode change */
+    vlc_mutex_lock(&sys->lock);
+    const bool ch_desktop = sys->ch_desktop;
+    sys->ch_desktop = false;
+    vlc_mutex_unlock(&sys->lock);
+
+    if (ch_desktop) {
+        sys->reopen_device = true;
+        vout_display_SendEventPicturesInvalid(vd);
+    }
 
+#if 0
     /*
      * Position Change
      */
-    if (p_sys->i_changes & DX_POSITION_CHANGE) {
+    if (sys->changes & DX_POSITION_CHANGE) {
 #if 0 /* need that when bicubic filter is available */
         RECT rect;
         UINT width, height;
@@ -300,139 +433,54 @@ static int Manage(vout_thread_t *p_vout)
 
         if (width != p_sys->d3dpp.BackBufferWidth || height != p_sys->d3dpp.BackBufferHeight)
         {
-            msg_Dbg(p_vout, "resizing device back buffers to (%lux%lu)", width, height);
+            msg_Dbg(vd, "resizing device back buffers to (%lux%lu)", width, height);
             // need to reset D3D device to resize back buffer
-            if (VLC_SUCCESS != Direct3DResetDevice(p_vout, width, height))
+            if (VLC_SUCCESS != Direct3DResetDevice(vd, width, height))
                 return VLC_EGENERIC;
         }
 #endif
-        p_sys->i_changes &= ~DX_POSITION_CHANGE;
-    }
-
-    /*
-     * Desktop mode change
-     */
-    if (p_sys->i_changes & DX_DESKTOP_CHANGE) {
-        /* Close the direct3d instance attached to the current output window. */
-        End(p_vout);
-
-        ExitFullscreen(p_vout);
-
-        EventThreadStop(p_sys->p_event);
-
-        /* Open the direct3d output and attaches it to the new window */
-        p_sys->b_desktop = !p_sys->b_desktop;
-        p_vout->pf_display = FirstDisplay;
-
-        event_cfg_t cfg;
-        memset(&cfg, 0, sizeof(cfg));
-        cfg.use_desktop = p_sys->b_desktop;
-
-        event_hwnd_t hwnd;
-        EventThreadStart(p_sys->p_event, &hwnd, &cfg);
-
-        p_sys->parent_window = hwnd.parent_window;
-        p_sys->hparent       = hwnd.hparent;
-        p_sys->hwnd          = hwnd.hwnd;
-        p_sys->hvideownd     = hwnd.hvideownd;
-        p_sys->hfswnd        = hwnd.hfswnd;
-
-        Init(p_vout);
-
-        /* Reset the flag */
-        p_sys->i_changes &= ~DX_DESKTOP_CHANGE;
+        sys->changes &= ~DX_POSITION_CHANGE;
     }
-
-    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)
-{
-    vout_sys_t *p_sys = p_vout->p_sys;
-    LPDIRECT3DDEVICE9 p_d3ddev = p_sys->p_d3ddev;
-    VLC_UNUSED(p_pic);
-
-    // Present the back buffer contents to the display
-    // No stretching should happen here !
-    RECT src = p_sys->rect_dest_clipped;
-    RECT dst = p_sys->rect_dest_clipped;
-    HRESULT hr = IDirect3DDevice9_Present(p_d3ddev, &src, &dst,
-                                          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;
+#endif
 }
 
-/*****************************************************************************
- * DirectD3DVoutCreate: Initialize and instance of Direct3D9
- *****************************************************************************
- * This function initialize Direct3D and analyze available resources from
- * default adapter.
- *****************************************************************************/
-static int Direct3DCreate(vout_thread_t *p_vout)
+/**
+ * It initializes an instance of Direct3D9
+ */
+static int Direct3DCreate(vout_display_t *vd)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
+    vout_display_sys_t *sys = vd->sys;
 
-    p_sys->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
-    if (!p_sys->hd3d9_dll) {
-        msg_Warn(p_vout, "cannot load d3d9.dll, aborting");
+    sys->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
+    if (!sys->hd3d9_dll) {
+        msg_Warn(vd, "cannot load d3d9.dll, aborting");
         return VLC_EGENERIC;
     }
 
     LPDIRECT3D9 (WINAPI *OurDirect3DCreate9)(UINT SDKVersion);
     OurDirect3DCreate9 =
-        (void *)GetProcAddress(p_sys->hd3d9_dll, TEXT("Direct3DCreate9"));
+        (void *)GetProcAddress(sys->hd3d9_dll, TEXT("Direct3DCreate9"));
     if (!OurDirect3DCreate9) {
-        msg_Err(p_vout, "Cannot locate reference to Direct3DCreate9 ABI in DLL");
+        msg_Err(vd, "Cannot locate reference to Direct3DCreate9 ABI in DLL");
         return VLC_EGENERIC;
     }
 
     /* Create the D3D object. */
-    LPDIRECT3D9 p_d3dobj = OurDirect3DCreate9(D3D_SDK_VERSION);
-    if (!p_d3dobj) {
-       msg_Err(p_vout, "Could not create Direct3D9 instance.");
+    LPDIRECT3D9 d3dobj = OurDirect3DCreate9(D3D_SDK_VERSION);
+    if (!d3dobj) {
+       msg_Err(vd, "Could not create Direct3D9 instance.");
        return VLC_EGENERIC;
     }
-    p_sys->p_d3dobj = p_d3dobj;
+    sys->d3dobj = d3dobj;
 
     /*
     ** Get device capabilities
     */
     D3DCAPS9 d3dCaps;
     ZeroMemory(&d3dCaps, sizeof(d3dCaps));
-    HRESULT hr = IDirect3D9_GetDeviceCaps(p_d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps);
+    HRESULT hr = IDirect3D9_GetDeviceCaps(d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps);
     if (FAILED(hr)) {
-       msg_Err(p_vout, "Could not read adapter capabilities. (hr=0x%lX)", hr);
+       msg_Err(vd, "Could not read adapter capabilities. (hr=0x%lX)", hr);
        return VLC_EGENERIC;
     }
     /* TODO: need to test device capabilities and select the right render function */
@@ -440,45 +488,49 @@ static int Direct3DCreate(vout_thread_t *p_vout)
     return VLC_SUCCESS;
 }
 
-/*****************************************************************************
- * DirectD3DVoutRelease: release an instance of Direct3D9
- *****************************************************************************/
-static void Direct3DRelease(vout_thread_t *p_vout)
+/**
+ * It releases an instance of Direct3D9
+ */
+static void Direct3DDestroy(vout_display_t *vd)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
+    vout_display_sys_t *sys = vd->sys;
 
-    if (p_sys->p_d3dobj)
-       IDirect3D9_Release(p_sys->p_d3dobj);
-    if (p_sys->hd3d9_dll)
-        FreeLibrary(p_sys->hd3d9_dll);
+    if (sys->d3dobj)
+       IDirect3D9_Release(sys->d3dobj);
+    if (sys->hd3d9_dll)
+        FreeLibrary(sys->hd3d9_dll);
 
-    p_sys->p_d3dobj = NULL;
-    p_sys->hd3d9_dll = NULL;
+    sys->d3dobj = NULL;
+    sys->hd3d9_dll = NULL;
 }
 
-static int Direct3DFillPresentationParameters(vout_thread_t *p_vout)
+
+/**
+ * It setup vout_display_sys_t::d3dpp and vout_display_sys_t::rect_display
+ * from the default adapter.
+ */
+static int Direct3DFillPresentationParameters(vout_display_t *vd)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
-    LPDIRECT3D9 p_d3dobj = p_sys->p_d3dobj;
-    D3DDISPLAYMODE d3ddm;
-    HRESULT hr;
+    vout_display_sys_t *sys = vd->sys;
 
     /*
     ** 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);
+    D3DDISPLAYMODE d3ddm;
+    HRESULT hr = IDirect3D9_GetAdapterDisplayMode(sys->d3dobj,
+                                                  D3DADAPTER_DEFAULT, &d3ddm);
     if (FAILED(hr)) {
-       msg_Err(p_vout, "Could not read adapter display mode. (hr=0x%lX)", hr);
+       msg_Err(vd, "Could not read adapter display mode. (hr=0x%lX)", hr);
        return VLC_EGENERIC;
     }
 
     /* Set up the structure used to create the D3DDevice. */
-    D3DPRESENT_PARAMETERS *d3dpp = &p_vout->p_sys->d3dpp;
+    D3DPRESENT_PARAMETERS *d3dpp = &vd->sys->d3dpp;
     ZeroMemory(d3dpp, sizeof(D3DPRESENT_PARAMETERS));
     d3dpp->Flags                  = D3DPRESENTFLAG_VIDEO;
     d3dpp->Windowed               = TRUE;
-    d3dpp->hDeviceWindow          = p_vout->p_sys->hvideownd;
+    d3dpp->hDeviceWindow          = vd->sys->hvideownd;
     d3dpp->BackBufferWidth        = d3ddm.Width;
     d3dpp->BackBufferHeight       = d3ddm.Height;
     d3dpp->SwapEffect             = D3DSWAPEFFECT_COPY;
@@ -488,17 +540,17 @@ static int Direct3DFillPresentationParameters(vout_thread_t *p_vout)
     d3dpp->BackBufferCount        = 1;
     d3dpp->EnableAutoDepthStencil = FALSE;
 
-    const unsigned i_adapter_count = IDirect3D9_GetAdapterCount(p_d3dobj);
-    for( unsigned i = 1; i < i_adapter_count; i++ )
-    {
-        hr = IDirect3D9_GetAdapterDisplayMode(p_d3dobj, i, &d3ddm );
-        if( FAILED(hr) )
+    const unsigned adapter_count = IDirect3D9_GetAdapterCount(sys->d3dobj);
+    for (unsigned i = 1; i < adapter_count; i++) {
+        hr = IDirect3D9_GetAdapterDisplayMode(sys->d3dobj, i, &d3ddm);
+        if (FAILED(hr))
             continue;
         d3dpp->BackBufferWidth  = __MAX(d3dpp->BackBufferWidth,  d3ddm.Width);
         d3dpp->BackBufferHeight = __MAX(d3dpp->BackBufferHeight, d3ddm.Height);
     }
 
-    RECT *display = &p_vout->p_sys->rect_display;
+    /* */
+    RECT *display = &vd->sys->rect_display;
     display->left   = 0;
     display->top    = 0;
     display->right  = d3dpp->BackBufferWidth;
@@ -507,108 +559,152 @@ static int Direct3DFillPresentationParameters(vout_thread_t *p_vout)
     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 Direct3DOpen(vout_thread_t *p_vout)
+/* */
+static int  Direct3DCreateResources (vout_display_t *, video_format_t *);
+static void Direct3DDestroyResources(vout_display_t *);
+
+/**
+ * It creates a Direct3D device and the associated resources.
+ */
+static int Direct3DOpen(vout_display_t *vd, video_format_t *fmt)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
-    LPDIRECT3D9 p_d3dobj = p_sys->p_d3dobj;
-    LPDIRECT3DDEVICE9 p_d3ddev;
-    HRESULT hr;
+    vout_display_sys_t *sys = vd->sys;
+    LPDIRECT3D9 d3dobj = sys->d3dobj;
 
-    if (Direct3DFillPresentationParameters(p_vout))
+    if (Direct3DFillPresentationParameters(vd))
         return VLC_EGENERIC;
 
     // Create the D3DDevice
-    hr = IDirect3D9_CreateDevice(p_d3dobj, D3DADAPTER_DEFAULT,
-                                 D3DDEVTYPE_HAL, p_sys->hvideownd,
-                                 D3DCREATE_SOFTWARE_VERTEXPROCESSING|
-                                 D3DCREATE_MULTITHREADED,
-                                 &p_sys->d3dpp, &p_d3ddev);
+    LPDIRECT3DDEVICE9 d3ddev;
+    HRESULT hr = IDirect3D9_CreateDevice(d3dobj, D3DADAPTER_DEFAULT,
+                                         D3DDEVTYPE_HAL, sys->hvideownd,
+                                         D3DCREATE_SOFTWARE_VERTEXPROCESSING|
+                                         D3DCREATE_MULTITHREADED,
+                                         &sys->d3dpp, &d3ddev);
     if (FAILED(hr)) {
-       msg_Err(p_vout, "Could not create the D3D device! (hr=0x%lX)", hr);
+       msg_Err(vd, "Could not create the D3D device! (hr=0x%lX)", hr);
        return VLC_EGENERIC;
     }
-    p_sys->p_d3ddev = p_d3ddev;
+    sys->d3ddev = d3ddev;
+
+    UpdateRects(vd, NULL, NULL, true);
 
-    msg_Dbg(p_vout, "Direct3D device adapter successfully initialized");
+    if (Direct3DCreateResources(vd, fmt)) {
+        msg_Err(vd, "Failed to allocate resources");
+        return VLC_EGENERIC;
+    }
+
+    /* Change the window title bar text */
+    EventThreadUpdateTitle(sys->event, VOUT_TITLE " (Direct3D output)");
+
+    msg_Dbg(vd, "Direct3D device adapter successfully initialized");
     return VLC_SUCCESS;
 }
 
-/*****************************************************************************
- * DirectD3DClose: release the Direct3D9 device
- *****************************************************************************/
-static void Direct3DClose(vout_thread_t *p_vout)
+/**
+ * It releases the Direct3D9 device and its resources.
+ */
+static void Direct3DClose(vout_display_t *vd)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
+    vout_display_sys_t *sys = vd->sys;
+
+    Direct3DDestroyResources(vd);
 
-    if (p_sys->p_d3ddev)
-       IDirect3DDevice9_Release(p_sys->p_d3ddev);
+    if (sys->d3ddev)
+       IDirect3DDevice9_Release(sys->d3ddev);
 
-    p_sys->p_d3ddev = NULL;
-    p_sys->hmonitor = NULL;
+    sys->d3ddev = NULL;
+    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 Direct3DResetDevice(vout_thread_t *p_vout)
+/**
+ * It reset the Direct3D9 device and its resources.
+ */
+static int Direct3DReset(vout_display_t *vd)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
-    LPDIRECT3DDEVICE9 p_d3ddev = p_sys->p_d3ddev;
-    HRESULT hr;
+    vout_display_sys_t *sys = vd->sys;
+    LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev;
 
-    if (Direct3DFillPresentationParameters(p_vout))
+    if (Direct3DFillPresentationParameters(vd))
         return VLC_EGENERIC;
 
-    // release all D3D objects
-    Direct3DReleaseScene(p_vout);
-    Direct3DReleasePictures(p_vout);
+    /* release all D3D objects */
+    Direct3DDestroyResources(vd);
 
-    hr = IDirect3DDevice9_Reset(p_d3ddev, &p_sys->d3dpp);
+    /* */
+    HRESULT hr = IDirect3DDevice9_Reset(d3ddev, &sys->d3dpp);
     if (FAILED(hr)) {
-        msg_Err(p_vout, "%s failed ! (hr=%08lX)", __FUNCTION__, hr);
+        msg_Err(vd, "%s failed ! (hr=%08lX)", __FUNCTION__, hr);
+        return VLC_EGENERIC;
+    }
+
+    UpdateRects(vd, NULL, NULL, true);
+
+    /* re-create them */
+    if (Direct3DCreateResources(vd, &vd->fmt)) {
+        msg_Dbg(vd, "%s failed !", __FUNCTION__);
+        return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
+/* */
+static int  Direct3DCreatePool(vout_display_t *vd, video_format_t *fmt);
+static void Direct3DDestroyPool(vout_display_t *vd);
+
+static int  Direct3DCreateScene(vout_display_t *vd);
+static void Direct3DDestroyScene(vout_display_t *vd);
+
+/**
+ * It creates the picture and scene resources.
+ */
+static int Direct3DCreateResources(vout_display_t *vd, video_format_t *fmt)
+{
+    if (Direct3DCreatePool(vd, fmt)) {
+        msg_Err(vd, "Direct3D picture pool initialization failed");
         return VLC_EGENERIC;
     }
-    // re-create them
-    if (Direct3DCreatePictures(p_vout, 1) || Direct3DCreateScene(p_vout)) {
-        msg_Dbg(p_vout, "%s failed !", __FUNCTION__);
+    if (Direct3DCreateScene(vd)) {
+        msg_Err(vd, "Direct3D scene initialization failed !");
         return VLC_EGENERIC;
     }
     return VLC_SUCCESS;
 }
+/**
+ * It destroys the picture and scene resources.
+ */
+static void Direct3DDestroyResources(vout_display_t *vd)
+{
+    Direct3DDestroyScene(vd);
+    Direct3DDestroyPool(vd);
+}
 
-static int Direct3DCheckFormat(vout_thread_t *p_vout,
-                               D3DFORMAT target, D3DFORMAT format)
+/**
+ * It tests if the conversion from src to dst is supported.
+ */
+static int Direct3DCheckConversion(vout_display_t *vd,
+                                   D3DFORMAT src, D3DFORMAT dst)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
-    LPDIRECT3D9 p_d3dobj = p_sys->p_d3dobj;
+    vout_display_sys_t *sys = vd->sys;
+    LPDIRECT3D9 d3dobj = sys->d3dobj;
     HRESULT hr;
 
     /* test whether device can create a surface of that format */
-    hr = IDirect3D9_CheckDeviceFormat(p_d3dobj, D3DADAPTER_DEFAULT,
-                                      D3DDEVTYPE_HAL, target, 0,
-                                      D3DRTYPE_SURFACE, format);
+    hr = IDirect3D9_CheckDeviceFormat(d3dobj, D3DADAPTER_DEFAULT,
+                                      D3DDEVTYPE_HAL, dst, 0,
+                                      D3DRTYPE_SURFACE, src);
     if (SUCCEEDED(hr)) {
         /* test whether device can perform color-conversion
         ** from that format to target format
         */
-        hr = IDirect3D9_CheckDeviceFormatConversion(p_d3dobj,
+        hr = IDirect3D9_CheckDeviceFormatConversion(d3dobj,
                                                     D3DADAPTER_DEFAULT,
                                                     D3DDEVTYPE_HAL,
-                                                    format, target);
+                                                    src, dst);
     }
     if (!SUCCEEDED(hr)) {
         if (D3DERR_NOTAVAILABLE != hr)
-            msg_Err(p_vout, "Could not query adapter supported formats. (hr=0x%lX)", hr);
+            msg_Err(vd, "Could not query adapter supported formats. (hr=0x%lX)", hr);
         return VLC_EGENERIC;
     }
     return VLC_SUCCESS;
@@ -617,14 +713,14 @@ static int Direct3DCheckFormat(vout_thread_t *p_vout,
 typedef struct
 {
     const char   *name;
-    D3DFORMAT    format;
-    vlc_fourcc_t fourcc;
+    D3DFORMAT    format;    /* D3D format */
+    vlc_fourcc_t fourcc;    /* VLC fourcc */
     uint32_t     rmask;
     uint32_t     gmask;
     uint32_t     bmask;
 } d3d_format_t;
 
-static const d3d_format_t p_d3d_formats[] = {
+static const d3d_format_t d3d_formats[] = {
     /* YV12 is always used for planar 420, the planes are then swapped in Lock() */
     { "YV12",       MAKEFOURCC('Y','V','1','2'),    VLC_CODEC_YV12,  0,0,0 },
     { "YV12",       MAKEFOURCC('Y','V','1','2'),    VLC_CODEC_I420,  0,0,0 },
@@ -640,33 +736,35 @@ static const d3d_format_t p_d3d_formats[] = {
     { NULL, 0, 0, 0,0,0}
 };
 
-static const d3d_format_t *Direct3DFindFormat(vout_thread_t *p_vout, vlc_fourcc_t i_chroma, D3DFORMAT target)
+/**
+ * It returns the format (closest to chroma) that can be converted to target */
+static const d3d_format_t *Direct3DFindFormat(vout_display_t *vd, vlc_fourcc_t chroma, D3DFORMAT target)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
+    vout_display_sys_t *sys = vd->sys;
 
     for (unsigned pass = 0; pass < 2; pass++) {
-        const vlc_fourcc_t *p_chromas;
+        const vlc_fourcc_t *list;
 
-        if (pass == 0 && p_sys->b_hw_yuv && vlc_fourcc_IsYUV(i_chroma))
-            p_chromas = vlc_fourcc_GetYUVFallback(i_chroma);
+        if (pass == 0 && sys->allow_hw_yuv && vlc_fourcc_IsYUV(chroma))
+            list = vlc_fourcc_GetYUVFallback(chroma);
         else if (pass == 1)
-            p_chromas = vlc_fourcc_GetRGBFallback(i_chroma);
+            list = vlc_fourcc_GetRGBFallback(chroma);
         else
             continue;
 
-        for (unsigned i = 0; p_chromas[i] != 0; i++) {
-            for (unsigned j = 0; p_d3d_formats[j].name; j++) {
-                const d3d_format_t *p_format = &p_d3d_formats[j];
+        for (unsigned i = 0; list[i] != 0; i++) {
+            for (unsigned j = 0; d3d_formats[j].name; j++) {
+                const d3d_format_t *format = &d3d_formats[j];
 
-                if (p_format->fourcc != p_chromas[i])
+                if (format->fourcc != list[i])
                     continue;
 
-                msg_Warn(p_vout, "trying surface pixel format: %s",
-                         p_format->name);
-                if (!Direct3DCheckFormat(p_vout, target, p_format->format)) {
-                    msg_Dbg(p_vout, "selected surface pixel format is %s",
-                            p_format->name);
-                    return p_format;
+                msg_Warn(vd, "trying surface pixel format: %s",
+                         format->name);
+                if (!Direct3DCheckConversion(vd, format->format, target)) {
+                    msg_Dbg(vd, "selected surface pixel format is %s",
+                            format->name);
+                    return format;
                 }
             }
         }
@@ -674,474 +772,402 @@ static const d3d_format_t *Direct3DFindFormat(vout_thread_t *p_vout, vlc_fourcc_
     return NULL;
 }
 
-/*****************************************************************************
- * Direct3DCreatePictures: 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 Direct3DCreatePictures(vout_thread_t *p_vout, size_t i_num_pics)
-{
-    vout_sys_t *p_sys = p_vout->p_sys;
-    LPDIRECT3DDEVICE9 p_d3ddev = p_sys->p_d3ddev;
-    HRESULT hr;
-    size_t c;
-    // if vout is already running, use current chroma, otherwise choose from upstream
-    vlc_fourcc_t i_chroma = p_vout->output.i_chroma ? p_vout->output.i_chroma
-                                                    : p_vout->render.i_chroma;
-
-    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
-    */
-    const d3d_format_t *p_format = Direct3DFindFormat(p_vout, i_chroma, p_sys->d3dpp.BackBufferFormat);
-    if (!p_format) {
-        msg_Err(p_vout, "surface pixel format is not supported.");
-        return VLC_EGENERIC;
-    }
-    p_vout->output.i_chroma = p_format->fourcc;
-    p_vout->output.i_rmask  = p_format->rmask;
-    p_vout->output.i_gmask  = p_format->gmask;
-    p_vout->output.i_bmask  = p_format->bmask;
-
-    /* */
-    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,
-                                                          p_format->format,
-                                                          D3DPOOL_DEFAULT,
-                                                          &p_d3dsurf,
-                                                          NULL);
-        if (FAILED(hr)) {
-            msg_Err(p_vout, "Failed to create picture surface. (hr=0x%lx)", hr);
-            Direct3DReleasePictures(p_vout);
-            return VLC_EGENERIC;
-        }
-
-        /* fill surface with black color */
-        IDirect3DDevice9_ColorFill(p_d3ddev, p_d3dsurf, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0));
-
-        /* */
-        video_format_Setup(&p_pic->format, p_vout->output.i_chroma, p_vout->output.i_width, p_vout->output.i_height, p_vout->output.i_aspect);
-
-        /* 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_CODEC_RGB8:
-            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_CODEC_RGB15:
-        case VLC_CODEC_RGB16:
-            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_CODEC_RGB24:
-            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_CODEC_RGB32:
-            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_CODEC_UYVY:
-        case VLC_CODEC_YUYV:
-            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_CODEC_I420:
-        case VLC_CODEC_J420:
-        case VLC_CODEC_YV12:
-            p_pic->i_planes = 3;
-            for (int n = 0; n < p_pic->i_planes; n++)
-            {
-                const unsigned d = 1 + (n > 0);
-                plane_t *p = &p_pic->p[n];
-
-                p->i_pixel_pitch = 1;
-                p->i_lines         =
-                p->i_visible_lines = p_vout->output.i_height / d;
-                p->i_visible_pitch = p_vout->output.i_width / d;
-            }
-            break;
-        default:
-            Direct3DReleasePictures(p_vout);
-            return VLC_EGENERIC;
-        }
-        p_pic->i_status = DESTROYED_PICTURE;
-        p_pic->i_type   = DIRECT_PICTURE;
-        p_pic->b_slow   = true;
-        p_pic->pf_lock  = Direct3DLockSurface;
-        p_pic->pf_unlock = Direct3DUnlockSurface;
-        PP_OUTPUTPICTURE[c] = p_pic;
-
-        I_OUTPUTPICTURES = ++c;
-    }
-
-    msg_Dbg(p_vout, "%u Direct3D pictures created successfully", c);
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Direct3DReleasePictures: destroy a picture vector
- *****************************************************************************
- * release all video resources used for pictures
- *****************************************************************************/
-static void Direct3DReleasePictures(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)
-            continue;
-
-        LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;
-        if (p_d3dsurf)
-            IDirect3DSurface9_Release(p_d3dsurf);
-
-        p_pic->p_sys = NULL;
-    }
-    msg_Dbg(p_vout, "%u Direct3D pictures released.", c);
-
-    I_OUTPUTPICTURES = 0;
-}
-
-/*****************************************************************************
- * Direct3DLockSurface: 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 Direct3DLockSurface(vout_thread_t *p_vout, picture_t *p_pic)
+/**
+ * It locks the surface associated to the picture and get the surface
+ * descriptor which amongst other things has the pointer to the picture
+ * data and its pitch.
+ */
+static int Direct3DLockSurface(picture_t *picture)
 {
-    LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;
-
-    if (!p_d3dsurf)
-        return VLC_EGENERIC;
-
     /* Lock the surface to get a valid pointer to the picture buffer */
     D3DLOCKED_RECT d3drect;
-    HRESULT hr = IDirect3DSurface9_LockRect(p_d3dsurf, &d3drect, NULL, 0);
+    HRESULT hr = IDirect3DSurface9_LockRect(picture->p_sys->surface, &d3drect, NULL, 0);
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        //msg_Dbg(vd, "%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;
+    picture->p->p_pixels = d3drect.pBits;
+    picture->p->i_pitch  = d3drect.Pitch;
 
     /*  Fill chroma planes for planar YUV */
-    if (p_pic->format.i_chroma == VLC_CODEC_I420 ||
-        p_pic->format.i_chroma == VLC_CODEC_J420 ||
-        p_pic->format.i_chroma == VLC_CODEC_YV12) {
+    if (picture->format.i_chroma == VLC_CODEC_I420 ||
+        picture->format.i_chroma == VLC_CODEC_J420 ||
+        picture->format.i_chroma == VLC_CODEC_YV12) {
 
-        for (int n = 1; n < p_pic->i_planes; n++) {
-            const plane_t *o = &p_pic->p[n-1];
-            plane_t *p = &p_pic->p[n];
+        for (int n = 1; n < picture->i_planes; n++) {
+            const plane_t *o = &picture->p[n-1];
+            plane_t *p = &picture->p[n];
 
             p->p_pixels = o->p_pixels + o->i_lines * o->i_pitch;
             p->i_pitch  = d3drect.Pitch / 2;
         }
         /* The d3d buffer is always allocated as YV12 */
-        if (vlc_fourcc_AreUVPlanesSwapped(p_pic->format.i_chroma, VLC_CODEC_YV12)) {
-            uint8_t *p_tmp = p_pic->p[1].p_pixels;
-            p_pic->p[1].p_pixels = p_pic->p[2].p_pixels;
-            p_pic->p[2].p_pixels = p_tmp;
+        if (vlc_fourcc_AreUVPlanesSwapped(picture->format.i_chroma, VLC_CODEC_YV12)) {
+            uint8_t *p_tmp = picture->p[1].p_pixels;
+            picture->p[1].p_pixels = picture->p[2].p_pixels;
+            picture->p[2].p_pixels = p_tmp;
         }
     }
-
     return VLC_SUCCESS;
 }
+/**
+ * It unlocks the surface associated to the picture.
+ */
+static void Direct3DUnlockSurface(picture_t *picture)
+{
+    /* Unlock the Surface */
+    HRESULT hr = IDirect3DSurface9_UnlockRect(picture->p_sys->surface);
+    if (FAILED(hr)) {
+        //msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+    }
+}
 
-/*****************************************************************************
- * Direct3DUnlockSurface: Unlock a surface locked by Direct3DLockSurface().
- *****************************************************************************/
-static int Direct3DUnlockSurface(vout_thread_t *p_vout, picture_t *p_pic)
+/**
+ * It creates the pool of picture (only 1).
+ *
+ * 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 Direct3DCreatePool(vout_display_t *vd, video_format_t *fmt)
 {
-    LPDIRECT3DSURFACE9 p_d3dsurf = (LPDIRECT3DSURFACE9)p_pic->p_sys;
+    vout_display_sys_t *sys = vd->sys;
+    LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev;
 
-    if (!p_d3dsurf)
+    /* */
+    *fmt = vd->source;
+
+    /* 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 */
+    const d3d_format_t *d3dfmt = Direct3DFindFormat(vd, fmt->i_chroma, sys->d3dpp.BackBufferFormat);
+    if (!d3dfmt) {
+        msg_Err(vd, "surface pixel format is not supported.");
         return VLC_EGENERIC;
-
-    /* Unlock the Surface */
-    HRESULT hr = IDirect3DSurface9_UnlockRect(p_d3dsurf);
+    }
+    fmt->i_chroma = d3dfmt->fourcc;
+    fmt->i_rmask  = d3dfmt->rmask;
+    fmt->i_gmask  = d3dfmt->gmask;
+    fmt->i_bmask  = d3dfmt->bmask;
+
+    /* We create one picture.
+     * It is useless to create more as we can't be used for direct rendering */
+
+    /* Create a surface */
+    LPDIRECT3DSURFACE9 surface;
+    HRESULT hr = IDirect3DDevice9_CreateOffscreenPlainSurface(d3ddev,
+                                                              fmt->i_width,
+                                                              fmt->i_height,
+                                                              d3dfmt->format,
+                                                              D3DPOOL_DEFAULT,
+                                                              &surface,
+                                                              NULL);
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        msg_Err(vd, "Failed to create picture surface. (hr=0x%lx)", hr);
         return VLC_EGENERIC;
     }
+    /* fill surface with black color */
+    IDirect3DDevice9_ColorFill(d3ddev, surface, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0));
+
+    /* Create the associated picture */
+    picture_resource_t *rsc = &sys->resource;
+    rsc->p_sys = malloc(sizeof(*rsc->p_sys));
+    if (!rsc->p_sys) {
+        IDirect3DSurface9_Release(surface);
+        return VLC_ENOMEM;
+    }
+    rsc->p_sys->surface = surface;
+    for (int i = 0; i < PICTURE_PLANE_MAX; i++) {
+        rsc->p[i].p_pixels = NULL;
+        rsc->p[i].i_pitch = 0;
+        rsc->p[i].i_lines = fmt->i_height / (i > 0 ? 2 : 1);
+    }
+    picture_t *picture = picture_NewFromResource(fmt, rsc);
+    if (!picture) {
+        IDirect3DSurface9_Release(surface);
+        free(rsc->p_sys);
+        return VLC_ENOMEM;
+    }
+
+    /* Wrap it into a picture pool */
+    picture_pool_configuration_t pool_cfg;
+    memset(&pool_cfg, 0, sizeof(pool_cfg));
+    pool_cfg.picture_count = 1;
+    pool_cfg.picture       = &picture;
+    pool_cfg.lock          = Direct3DLockSurface;
+    pool_cfg.unlock        = Direct3DUnlockSurface;
+
+    sys->pool = picture_pool_NewExtended(&pool_cfg);
+    if (!sys->pool) {
+        picture_Release(picture);
+        IDirect3DSurface9_Release(surface);
+        return VLC_ENOMEM;
+    }
     return VLC_SUCCESS;
 }
+/**
+ * It destroys the pool of picture and its resources.
+ */
+static void Direct3DDestroyPool(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    if (sys->pool) {
+        picture_resource_t *rsc = &sys->resource;
+        IDirect3DSurface9_Release(rsc->p_sys->surface);
+
+        picture_pool_Delete(sys->pool);
+    }
+    sys->pool = NULL;
+}
 
-/*****************************************************************************
- * Direct3DCreateScene: allocate and initialize a 3D scene
- *****************************************************************************
- * for advanced blending/filtering a texture needs be used in a 3D scene.
- *****************************************************************************/
-static int Direct3DCreateScene(vout_thread_t *p_vout)
+/* */
+typedef struct
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
-    LPDIRECT3DDEVICE9       p_d3ddev = p_sys->p_d3ddev;
-    LPDIRECT3DTEXTURE9      p_d3dtex;
-    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc;
+    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)
 
+/**
+ * It allocates and initializes the resources needed to render the scene.
+ */
+static int Direct3DCreateScene(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+    LPDIRECT3DDEVICE9       d3ddev = sys->d3ddev;
     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_sys->d3dpp.BackBufferWidth,
-                                        p_sys->d3dpp.BackBufferHeight,
+     * 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
+     */
+    LPDIRECT3DTEXTURE9 d3dtex;
+    hr = IDirect3DDevice9_CreateTexture(d3ddev,
+                                        sys->d3dpp.BackBufferWidth,
+                                        sys->d3dpp.BackBufferHeight,
                                         1,
                                         D3DUSAGE_RENDERTARGET,
-                                        p_sys->d3dpp.BackBufferFormat,
+                                        sys->d3dpp.BackBufferFormat,
                                         D3DPOOL_DEFAULT,
-                                        &p_d3dtex,
+                                        &d3dtex,
                                         NULL);
     if (FAILED(hr)) {
-        msg_Err(p_vout, "Failed to create texture. (hr=0x%lx)", hr);
+        msg_Err(vd, "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,
+    LPDIRECT3DVERTEXBUFFER9 d3dvtc;
+    hr = IDirect3DDevice9_CreateVertexBuffer(d3ddev,
                                              sizeof(CUSTOMVERTEX)*4,
                                              D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
                                              D3DFVF_CUSTOMVERTEX,
                                              D3DPOOL_DEFAULT,
-                                             &p_d3dvtc,
+                                             &d3dvtc,
                                              NULL);
     if (FAILED(hr)) {
-        msg_Err(p_vout, "Failed to create vertex buffer. (hr=0x%lx)", hr);
-            IDirect3DTexture9_Release(p_d3dtex);
+        msg_Err(vd, "Failed to create vertex buffer. (hr=0x%lx)", hr);
+        IDirect3DTexture9_Release(d3dtex);
         return VLC_EGENERIC;
     }
 
-    p_sys->p_d3dtex = p_d3dtex;
-    p_sys->p_d3dvtc = p_d3dvtc;
+    /* */
+    sys->d3dtex = d3dtex;
+    sys->d3dvtc = 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);
+    IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+    IDirect3DDevice9_SetSamplerState(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);
+    IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+    IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
 
     // set maximum ambient light
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255));
+    IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255));
 
     // Turn off culling
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_CULLMODE, D3DCULL_NONE);
+    IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_CULLMODE, D3DCULL_NONE);
 
     // Turn off the zbuffer
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_ZENABLE, D3DZB_FALSE);
+    IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ZENABLE, D3DZB_FALSE);
 
     // Turn off lights
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_LIGHTING, FALSE);
+    IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_LIGHTING, FALSE);
 
     // Enable dithering
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_DITHERENABLE, TRUE);
+    IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_DITHERENABLE, TRUE);
 
     // disable stencil
-    IDirect3DDevice9_SetRenderState(p_d3ddev, D3DRS_STENCILENABLE, FALSE);
+    IDirect3DDevice9_SetRenderState(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);
+    IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHABLENDENABLE, TRUE);
+    IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
+    IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
+    IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHATESTENABLE,TRUE);
+    IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHAREF, 0x10);
+    IDirect3DDevice9_SetRenderState(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);
+    IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_COLOROP,D3DTOP_MODULATE);
+    IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_COLORARG1,D3DTA_TEXTURE);
+    IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_COLORARG2,D3DTA_DIFFUSE);
 
     // turn off alpha operation
-    IDirect3DDevice9_SetTextureStageState(p_d3ddev, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+    IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
 
-    msg_Dbg(p_vout, "Direct3D scene created successfully");
+    msg_Dbg(vd, "Direct3D scene created successfully");
 
     return VLC_SUCCESS;
 }
 
-/*****************************************************************************
- * Direct3DReleaseScene
- *****************************************************************************/
-static void Direct3DReleaseScene(vout_thread_t *p_vout)
+/**
+ * It releases the scene resources.
+ */
+static void Direct3DDestroyScene(vout_display_t *vd)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
+    vout_display_sys_t *sys = vd->sys;
 
-    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc = p_sys->p_d3dvtc;
-    if (p_d3dvtc)
-        IDirect3DVertexBuffer9_Release(p_d3dvtc);
+    LPDIRECT3DVERTEXBUFFER9 d3dvtc = sys->d3dvtc;
+    if (d3dvtc)
+        IDirect3DVertexBuffer9_Release(d3dvtc);
 
-    LPDIRECT3DTEXTURE9 p_d3dtex = p_sys->p_d3dtex;
-    if (p_d3dtex)
-        IDirect3DTexture9_Release(p_d3dtex);
+    LPDIRECT3DTEXTURE9 d3dtex = sys->d3dtex;
+    if (d3dtex)
+        IDirect3DTexture9_Release(d3dtex);
 
-    p_sys->p_d3dvtc = NULL;
-    p_sys->p_d3dtex = NULL;
-    msg_Dbg(p_vout, "Direct3D scene released successfully");
+    sys->d3dvtc = NULL;
+    sys->d3dtex = NULL;
+    msg_Dbg(vd, "Direct3D scene released successfully");
 }
 
-/*****************************************************************************
- * Render: copy picture surface into a texture and render into a scene
- *****************************************************************************
+/**
+ * It copies picture surface into a texture and renders 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 Direct3DRenderScene(vout_thread_t *p_vout, picture_t *p_pic)
+ */
+static void Direct3DRenderScene(vout_display_t *vd, LPDIRECT3DSURFACE9 surface)
 {
-    vout_sys_t *p_sys = p_vout->p_sys;
-    LPDIRECT3DDEVICE9 p_d3ddev = p_sys->p_d3ddev;
+    vout_display_sys_t *sys = vd->sys;
+    LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev;
     HRESULT hr;
 
     // check if device is still available
-    hr = IDirect3DDevice9_TestCooperativeLevel(p_d3ddev);
+    hr = IDirect3DDevice9_TestCooperativeLevel(d3ddev);
     if (FAILED(hr)) {
-        if (hr != D3DERR_DEVICENOTRESET || Direct3DResetDevice(p_vout)) {
-            // device is not usable at present (lost device, out of video mem ?)
-            return;
+        if (hr == D3DERR_DEVICENOTRESET && !sys->reset_device) {
+            vout_display_SendEventPicturesInvalid(vd);
+            sys->reset_device = true;
         }
+        return;
     }
     /* */
-    LPDIRECT3DTEXTURE9      p_d3dtex  = p_sys->p_d3dtex;
-    LPDIRECT3DVERTEXBUFFER9 p_d3dvtc  = p_sys->p_d3dvtc;
+    LPDIRECT3DTEXTURE9      d3dtex  = sys->d3dtex;
+    LPDIRECT3DVERTEXBUFFER9 d3dvtc  = sys->d3dvtc;
 
     /* Clear the backbuffer and the zbuffer */
-    hr = IDirect3DDevice9_Clear(p_d3ddev, 0, NULL, D3DCLEAR_TARGET,
+    hr = IDirect3DDevice9_Clear(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);
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
         return;
     }
     /*  retrieve picture surface */
-    LPDIRECT3DSURFACE9 p_d3dsrc = (LPDIRECT3DSURFACE9)p_pic->p_sys;
-    if (!p_d3dsrc) {
-        msg_Dbg(p_vout, "no surface to render ?");
+    LPDIRECT3DSURFACE9 d3dsrc = surface;
+    if (!d3dsrc) {
+        msg_Dbg(vd, "no surface to render ?");
         return;
     }
 
     /* retrieve texture top-level surface */
-    LPDIRECT3DSURFACE9 p_d3ddest;
-    hr = IDirect3DTexture9_GetSurfaceLevel(p_d3dtex, 0, &p_d3ddest);
+    LPDIRECT3DSURFACE9 d3ddest;
+    hr = IDirect3DTexture9_GetSurfaceLevel(d3dtex, 0, &d3ddest);
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
         return;
     }
 
     /* Copy picture surface into texture surface
      * color space conversion and scaling happen here */
-    RECT src = p_vout->p_sys->rect_src_clipped;
-    RECT dst = p_vout->p_sys->rect_dest_clipped;
+    RECT src = vd->sys->rect_src_clipped;
+    RECT dst = vd->sys->rect_dest_clipped;
 
-    hr = IDirect3DDevice9_StretchRect(p_d3ddev, p_d3dsrc, &src, p_d3ddest, &dst, D3DTEXF_LINEAR);
-    IDirect3DSurface9_Release(p_d3ddest);
+    hr = IDirect3DDevice9_StretchRect(d3ddev, d3dsrc, &src, d3ddest, &dst, D3DTEXF_LINEAR);
+    IDirect3DSurface9_Release(d3ddest);
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
         return;
     }
 
     /* Update the vertex buffer */
-    CUSTOMVERTEX *p_vertices;
-    hr = IDirect3DVertexBuffer9_Lock(p_d3dvtc, 0, 0, (&p_vertices), D3DLOCK_DISCARD);
+    CUSTOMVERTEX *vertices;
+    hr = IDirect3DVertexBuffer9_Lock(d3dvtc, 0, 0, &vertices, D3DLOCK_DISCARD);
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
         return;
     }
 
     /* Setup vertices */
-    float f_width  = (float)p_vout->p_sys->d3dpp.BackBufferWidth;
-    float f_height = (float)p_vout->p_sys->d3dpp.BackBufferHeight;
+    const float f_width  = vd->sys->d3dpp.BackBufferWidth;
+    const float f_height = vd->sys->d3dpp.BackBufferHeight;
 
     /* -0.5f is a "feature" of DirectX and it seems to apply to Direct3d also */
     /* http://www.sjbrown.co.uk/2003/05/01/fix-directx-rasterisation/ */
-    p_vertices[0].x       = -0.5f;       // left
-    p_vertices[0].y       = -0.5f;       // 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 - 0.5f;    // right
-    p_vertices[1].y       = -0.5f;       // 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 - 0.5f;    // right
-    p_vertices[2].y       = f_height - 0.5f;   // 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.5f;       // left
-    p_vertices[3].y       = f_height - 0.5f;   // 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);
+    vertices[0].x       = -0.5f;       // left
+    vertices[0].y       = -0.5f;       // top
+    vertices[0].z       = 0.0f;
+    vertices[0].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
+    vertices[0].rhw     = 1.0f;
+    vertices[0].tu      = 0.0f;
+    vertices[0].tv      = 0.0f;
+
+    vertices[1].x       = f_width - 0.5f;    // right
+    vertices[1].y       = -0.5f;       // top
+    vertices[1].z       = 0.0f;
+    vertices[1].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
+    vertices[1].rhw     = 1.0f;
+    vertices[1].tu      = 1.0f;
+    vertices[1].tv      = 0.0f;
+
+    vertices[2].x       = f_width - 0.5f;    // right
+    vertices[2].y       = f_height - 0.5f;   // bottom
+    vertices[2].z       = 0.0f;
+    vertices[2].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
+    vertices[2].rhw     = 1.0f;
+    vertices[2].tu      = 1.0f;
+    vertices[2].tv      = 1.0f;
+
+    vertices[3].x       = -0.5f;       // left
+    vertices[3].y       = f_height - 0.5f;   // bottom
+    vertices[3].z       = 0.0f;
+    vertices[3].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
+    vertices[3].rhw     = 1.0f;
+    vertices[3].tu      = 0.0f;
+    vertices[3].tv      = 1.0f;
+
+    hr= IDirect3DVertexBuffer9_Unlock(d3dvtc);
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
         return;
     }
 
     // Begin the scene
-    hr = IDirect3DDevice9_BeginScene(p_d3ddev);
+    hr = IDirect3DDevice9_BeginScene(d3ddev);
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
         return;
     }
 
@@ -1149,41 +1175,41 @@ static void Direct3DRenderScene(vout_thread_t *p_vout, picture_t *p_pic)
     // 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);
+    hr = IDirect3DDevice9_SetTexture(d3ddev, 0, (LPDIRECT3DBASETEXTURE9)d3dtex);
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(p_d3ddev);
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        IDirect3DDevice9_EndScene(d3ddev);
         return;
     }
 
     // Render the vertex buffer contents
-    hr = IDirect3DDevice9_SetStreamSource(p_d3ddev, 0, p_d3dvtc, 0, sizeof(CUSTOMVERTEX));
+    hr = IDirect3DDevice9_SetStreamSource(d3ddev, 0, d3dvtc, 0, sizeof(CUSTOMVERTEX));
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(p_d3ddev);
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        IDirect3DDevice9_EndScene(d3ddev);
         return;
     }
 
     // we use FVF instead of vertex shader
-    hr = IDirect3DDevice9_SetFVF(p_d3ddev, D3DFVF_CUSTOMVERTEX);
+    hr = IDirect3DDevice9_SetFVF(d3ddev, D3DFVF_CUSTOMVERTEX);
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(p_d3ddev);
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        IDirect3DDevice9_EndScene(d3ddev);
         return;
     }
 
     // draw rectangle
-    hr = IDirect3DDevice9_DrawPrimitive(p_d3ddev, D3DPT_TRIANGLEFAN, 0, 2);
+    hr = IDirect3DDevice9_DrawPrimitive(d3ddev, D3DPT_TRIANGLEFAN, 0, 2);
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(p_d3ddev);
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        IDirect3DDevice9_EndScene(d3ddev);
         return;
     }
 
     // End the scene
-    hr = IDirect3DDevice9_EndScene(p_d3ddev);
+    hr = IDirect3DDevice9_EndScene(d3ddev);
     if (FAILED(hr)) {
-        msg_Dbg(p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
         return;
     }
 }
@@ -1195,24 +1221,28 @@ static int DesktopCallback(vlc_object_t *object, char const *psz_cmd,
                             vlc_value_t oldval, vlc_value_t newval,
                             void *p_data)
 {
+    vout_display_t *vd = (vout_display_t *)object;
+    vout_display_sys_t *sys = vd->sys;
     VLC_UNUSED(psz_cmd);
     VLC_UNUSED(oldval);
     VLC_UNUSED(p_data);
 
-    vout_thread_t *p_vout = (vout_thread_t *)object;
-
-    if ((newval.b_bool && !p_vout->p_sys->b_desktop) ||
-        (!newval.b_bool && p_vout->p_sys->b_desktop)) {
+    vlc_mutex_lock(&sys->lock);
+    const bool ch_desktop = !sys->desktop_requested != !newval.b_bool;
+    sys->ch_desktop |= ch_desktop;
+    sys->desktop_requested = newval.b_bool;
+    vlc_mutex_unlock(&sys->lock);
 
-        playlist_t *p_playlist = pl_Hold(p_vout);
+    /* FIXME we should have a way to export variable to be saved */
+    if (ch_desktop) {
+        playlist_t *p_playlist = pl_Hold(vd);
         if (p_playlist) {
             /* Modify playlist as well because the vout might have to be
              * restarted */
             var_Create(p_playlist, "direct3d-desktop", VLC_VAR_BOOL);
-            var_Set(p_playlist, "direct3d-desktop", newval);
-            pl_Release(p_vout);
+            var_SetBool(p_playlist, "direct3d-desktop", newval.b_bool);
+            pl_Release(vd);
         }
-        p_vout->p_sys->i_changes |= DX_DESKTOP_CHANGE;
     }
     return VLC_SUCCESS;
 }
index fb80bae15c8190876b3f2a9094a27c2dd69992e7..8f7bec0bae7ccfef55ed6f18186656eaed46c4a5 100644 (file)
@@ -31,8 +31,7 @@
 #endif
 
 #include <vlc_common.h>
-#include <vlc_playlist.h>
-#include <vlc_vout.h>
+#include <vlc_vout_display.h>
 #include <vlc_vout_window.h>
 
 #include <windows.h>
@@ -52,7 +51,7 @@
 #endif
 
 #include <vlc_keys.h>
-#include "vout.h"
+#include "common.h"
 
 #ifdef UNDER_CE
 #include <aygshell.h>
@@ -75,7 +74,7 @@
 
 struct event_thread_t
 {
-    vout_thread_t *p_vout;
+    vout_display_t *vd;
 
     /* */
     vlc_thread_t thread;
@@ -100,26 +99,22 @@ struct event_thread_t
     int               i_window_style;
     vout_window_cfg_t wnd_cfg;
 
-    /* */
-    unsigned i_changes;
-
     /* */
     vout_window_t *parent_window;
     HWND hparent;
     HWND hwnd;
     HWND hvideownd;
     HWND hfswnd;
+    video_format_t       source;
+    vout_display_place_t place;
+
+    bool has_moved;
 };
 
 static int  DirectXCreateWindow( event_thread_t * );
 static void DirectXCloseWindow ( event_thread_t * );
 static long FAR PASCAL DirectXEventProc( HWND, UINT, WPARAM, LPARAM );
 
-static void DirectXPopupMenu( event_thread_t *p_event, bool b_open )
-{
-    var_SetBool( p_event->p_vout->p_libvlc, "intf-popupmenu", b_open );
-}
-
 static int DirectXConvertKey( int i_key );
 
 /*****************************************************************************
@@ -133,11 +128,9 @@ static int DirectXConvertKey( int i_key );
 static void *EventThread( void *p_this )
 {
     event_thread_t *p_event = (event_thread_t *)p_this;
-    vout_thread_t *p_vout = p_event->p_vout;
+    vout_display_t *vd = p_event->vd;
     MSG msg;
     POINT old_mouse_pos = {0,0}, mouse_pos;
-    vlc_value_t val;
-    unsigned int i_width, i_height, i_x, i_y;
     HMODULE hkernel32;
     int canc = vlc_savecancel ();
 
@@ -173,7 +166,7 @@ static void *EventThread( void *p_this )
             /* Prevent monitor from powering off */
             OurSetThreadExecutionState( ES_DISPLAY_REQUIRED | ES_CONTINUOUS );
         else
-            msg_Dbg( p_vout, "no support for SetThreadExecutionState()" );
+            msg_Dbg( vd, "no support for SetThreadExecutionState()" );
     }
 #endif
 
@@ -181,6 +174,9 @@ static void *EventThread( void *p_this )
     /* GetMessage will sleep if there's no message in the queue */
     for( ;; )
     {
+        vout_display_place_t place;
+        video_format_t       source;
+
         if( !GetMessage( &msg, 0, 0, 0 ) )
         {
             vlc_mutex_lock( &p_event->lock );
@@ -199,37 +195,30 @@ static void *EventThread( void *p_this )
         /* */
         switch( msg.message )
         {
-
         case WM_MOUSEMOVE:
             vlc_mutex_lock( &p_event->lock );
-            vout_PlacePicture( p_event->p_vout,
-                               p_event->wnd_cfg.width,
-                               p_event->wnd_cfg.height,
-                               &i_x, &i_y, &i_width, &i_height );
+            place  = p_event->place;
+            source = p_event->source;
             vlc_mutex_unlock( &p_event->lock );
 
-            if( msg.hwnd == p_event->hvideownd )
+            if( place.width > 0 && place.height > 0 )
             {
-                /* 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 );
-
-                var_SetBool( p_event->p_vout, "mouse-moved", true );
+                if( msg.hwnd == p_event->hvideownd )
+                {
+                    /* Child window */
+                    place.x = 0;
+                    place.y = 0;
+                }
+                const int x = source.i_x_offset +
+                    (int64_t)(GET_X_LPARAM(msg.lParam) - place.x) * source.i_width  / place.width;
+                const int y = source.i_y_offset +
+                    (int64_t)(GET_Y_LPARAM(msg.lParam) - place.y) * source.i_height / place.height;
+                vout_display_SendEventMouseMoved(vd, x, y);
             }
-
+            /* Fall through */
         case WM_NCMOUSEMOVE:
             GetCursorPos( &mouse_pos );
+            /* FIXME, why this >2 limits ? */
             if( (abs(mouse_pos.x - old_mouse_pos.x) > 2 ||
                 (abs(mouse_pos.y - old_mouse_pos.y)) > 2 ) )
             {
@@ -238,132 +227,114 @@ static void *EventThread( void *p_this )
 
                 if( p_event->b_cursor_hidden )
                 {
-                    p_event->b_cursor_hidden = 0;
+                    p_event->b_cursor_hidden = false;
                     ShowCursor( TRUE );
                 }
             }
             break;
 
         case WM_VLC_HIDE_MOUSE:
-            if( p_event->b_cursor_hidden ) break;
+            if( p_event->b_cursor_hidden )
+                break;
             p_event->b_cursor_hidden = true;
             GetCursorPos( &old_mouse_pos );
             ShowCursor( FALSE );
             break;
 
         case WM_VLC_SHOW_MOUSE:
-            if( !p_event->b_cursor_hidden ) break;
+            if( !p_event->b_cursor_hidden )
+                break;
             p_event->b_cursor_hidden = 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, false );
+            vout_display_SendEventMousePressed(vd, MOUSE_BUTTON_LEFT);
             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 );
-
-            var_SetBool( p_event->p_vout, "mouse-clicked", true );
+            vout_display_SendEventMouseReleased(vd, MOUSE_BUTTON_LEFT);
             break;
-
         case WM_LBUTTONDBLCLK:
-            vlc_mutex_lock( &p_event->lock );
-            p_event->i_changes |= VOUT_FULLSCREEN_CHANGE;
-            vlc_mutex_unlock( &p_event->lock );
+            vout_display_SendEventMouseDoubleClick(vd);
             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, false );
+            vout_display_SendEventMousePressed(vd, MOUSE_BUTTON_CENTER);
             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 );
+            vout_display_SendEventMouseReleased(vd, MOUSE_BUTTON_CENTER);
             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, false );
+            vout_display_SendEventMousePressed(vd, MOUSE_BUTTON_RIGHT);
             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, true );
+            vout_display_SendEventMouseReleased(vd, MOUSE_BUTTON_RIGHT);
             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 )
+            int i_key = DirectXConvertKey( msg.wParam );
+            if( !i_key )
             {
                 /* This appears to be a "normal" (ascii) key */
-                val.i_int = tolower( MapVirtualKey( msg.wParam, 2 ) );
+                i_key = tolower( MapVirtualKey( msg.wParam, 2 ) );
             }
 
-            if( val.i_int )
+            if( i_key )
             {
                 if( GetKeyState(VK_CONTROL) & 0x8000 )
                 {
-                    val.i_int |= KEY_MODIFIER_CTRL;
+                    i_key |= KEY_MODIFIER_CTRL;
                 }
                 if( GetKeyState(VK_SHIFT) & 0x8000 )
                 {
-                    val.i_int |= KEY_MODIFIER_SHIFT;
+                    i_key |= KEY_MODIFIER_SHIFT;
                 }
                 if( GetKeyState(VK_MENU) & 0x8000 )
                 {
-                    val.i_int |= KEY_MODIFIER_ALT;
+                    i_key |= KEY_MODIFIER_ALT;
                 }
 
-                var_Set( p_vout->p_libvlc, "key-pressed", val );
+                vout_display_SendEventKey(vd, i_key);
             }
             break;
+        }
 
         case WM_MOUSEWHEEL:
+        {
+            int i_key;
             if( GET_WHEEL_DELTA_WPARAM( msg.wParam ) > 0 )
             {
-                val.i_int = KEY_MOUSEWHEELUP;
+                i_key = KEY_MOUSEWHEELUP;
             }
             else
             {
-                val.i_int = KEY_MOUSEWHEELDOWN;
+                i_key = KEY_MOUSEWHEELDOWN;
             }
-            if( val.i_int )
+            if( i_key )
             {
                 if( GetKeyState(VK_CONTROL) & 0x8000 )
                 {
-                    val.i_int |= KEY_MODIFIER_CTRL;
+                    i_key |= KEY_MODIFIER_CTRL;
                 }
                 if( GetKeyState(VK_SHIFT) & 0x8000 )
                 {
-                    val.i_int |= KEY_MODIFIER_SHIFT;
+                    i_key |= KEY_MODIFIER_SHIFT;
                 }
                 if( GetKeyState(VK_MENU) & 0x8000 )
                 {
-                    val.i_int |= KEY_MODIFIER_ALT;
+                    i_key |= KEY_MODIFIER_ALT;
                 }
-
-                var_Set( p_vout->p_libvlc, "key-pressed", val );
+                vout_display_SendEventKey(vd, i_key);
             }
             break;
+        }
 
         case WM_VLC_CHANGE_TEXT:
         {
@@ -405,11 +376,11 @@ static void *EventThread( void *p_this )
     /* Check for WM_QUIT if we created the window */
     if( !p_event->hparent && msg.message == WM_QUIT )
     {
-        msg_Warn( p_vout, "WM_QUIT... should not happen!!" );
+        msg_Warn( vd, "WM_QUIT... should not happen!!" );
         p_event->hwnd = NULL; /* Window already destroyed */
     }
 
-    msg_Dbg( p_vout, "DirectXEventThread terminating" );
+    msg_Dbg( vd, "DirectXEventThread terminating" );
 
     DirectXCloseWindow( p_event );
     vlc_restorecancel(canc);
@@ -428,7 +399,7 @@ static void *EventThread( void *p_this )
  *****************************************************************************/
 static int DirectXCreateWindow( event_thread_t *p_event )
 {
-    vout_thread_t *p_vout = p_event->p_vout;
+    vout_display_t *vd = p_event->vd;
     HINSTANCE  hInstance;
     HMENU      hMenu;
     RECT       rect_window;
@@ -437,7 +408,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
     char       vlc_path[MAX_PATH+1];
     int        i_style, i_stylex;
 
-    msg_Dbg( p_vout, "DirectXCreateWindow" );
+    msg_Dbg( vd, "DirectXCreateWindow" );
 
     /* Get this module's instance */
     hInstance = GetModuleHandle(NULL);
@@ -447,7 +418,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
     {
     #endif
         /* If an external window was specified, we'll draw in it. */
-        p_event->parent_window = vout_window_New( VLC_OBJECT(p_vout), NULL, &p_event->wnd_cfg );
+        p_event->parent_window = vout_display_NewWindow(vd, &p_event->wnd_cfg );
         if( p_event->parent_window )
             p_event->hparent = p_event->parent_window->handle.hwnd;
         else
@@ -461,7 +432,8 @@ static int DirectXCreateWindow( event_thread_t *p_event )
         if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SHELLDLL_DefView"), NULL );
         if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SysListView32"), NULL );
         if( !hwnd )
-            msg_Err( p_vout, "Couldn't find desktop icon window. Desktop mode can't be established." );
+            msg_Err( vd, "Couldn't find desktop icon window. Desktop mode can't be established." );
+        p_event->parent_window = NULL;
         p_event->hparent = hwnd;
     }
     #endif
@@ -498,7 +470,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
          * then fine, otherwise return with an error. */
         if( !GetClassInfo( hInstance, _T("VLC DirectX"), &wndclass ) )
         {
-            msg_Err( p_vout, "DirectXCreateWindow RegisterClass FAILED (err=%lu)", GetLastError() );
+            msg_Err( vd, "DirectXCreateWindow RegisterClass FAILED (err=%lu)", GetLastError() );
             return VLC_EGENERIC;
         }
     }
@@ -514,7 +486,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
          * 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() );
+            msg_Err( vd, "DirectXCreateWindow RegisterClass FAILED (err=%lu)", GetLastError() );
             return VLC_EGENERIC;
         }
     }
@@ -528,7 +500,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
     rect_window.right  = rect_window.left + p_event->wnd_cfg.width;
     rect_window.bottom = rect_window.top  + p_event->wnd_cfg.height;
 
-    if( var_GetBool( p_vout, "video-deco" ) )
+    if( var_GetBool( vd, "video-deco" ) )
     {
         /* Open with window decoration */
         AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 );
@@ -567,11 +539,11 @@ static int DirectXCreateWindow( event_thread_t *p_event )
                     p_event->hparent,                       /* parent window */
                     NULL,                          /* no menu in this window */
                     hInstance,            /* handle of this program instance */
-                    (LPVOID)p_event );           /* send p_vout to WM_CREATE */
+                    (LPVOID)p_event );           /* send vd to WM_CREATE */
 
     if( !p_event->hwnd )
     {
-        msg_Warn( p_vout, "DirectXCreateWindow create window FAILED (err=%lu)", GetLastError() );
+        msg_Warn( vd, "DirectXCreateWindow create window FAILED (err=%lu)", GetLastError() );
         return VLC_EGENERIC;
     }
 
@@ -610,20 +582,21 @@ static int DirectXCreateWindow( event_thread_t *p_event )
     /* 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. */
+    /* FIXME vd->source.i_width/i_height seems wrong */
     p_event->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_event->hwnd,                   /* parent window */
+        vd->source.i_width,          /* default width */
+        vd->source.i_height,        /* default height */
+        p_event->hwnd,               /* parent window */
         NULL, hInstance,
-        (LPVOID)p_event );    /* send p_vout to WM_CREATE */
+        (LPVOID)p_event );    /* send vd to WM_CREATE */
 
     if( !p_event->hvideownd )
-        msg_Warn( p_vout, "can't create video sub-window" );
+        msg_Warn( vd, "can't create video sub-window" );
     else
-        msg_Dbg( p_vout, "created video sub-window" );
+        msg_Dbg( vd, "created video sub-window" );
 
     /* Now display the window */
     ShowWindow( p_event->hwnd, SW_SHOW );
@@ -638,16 +611,17 @@ static int DirectXCreateWindow( event_thread_t *p_event )
  *****************************************************************************/
 static void DirectXCloseWindow( event_thread_t *p_event )
 {
-    vout_thread_t *p_vout = p_event->p_vout;
-    msg_Dbg( p_vout, "DirectXCloseWindow" );
+    vout_display_t *vd = p_event->vd;
+    msg_Dbg( vd, "DirectXCloseWindow" );
 
     DestroyWindow( p_event->hwnd );
-    if( p_event->hfswnd ) DestroyWindow( p_event->hfswnd );
+    if( p_event->hfswnd )
+        DestroyWindow( p_event->hfswnd );
 
     #ifdef MODULE_NAME_IS_direct3d
     if( !p_event->use_desktop )
     #endif
-        vout_window_Delete( p_event->parent_window );
+        vout_display_DeleteWindow( vd, p_event->parent_window );
     p_event->hwnd = NULL;
 
     /* We don't unregister the Window Class because it could lead to race
@@ -673,7 +647,7 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
 
     if( message == WM_CREATE )
     {
-        /* Store p_vout for future use */
+        /* Store vd for future use */
         p_event = (event_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams;
         SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)p_event );
         return TRUE;
@@ -689,14 +663,14 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
             return DefWindowProc(hwnd, message, wParam, lParam);
         }
     }
-    vout_thread_t *p_vout = p_event->p_vout;
+    vout_display_t *vd = p_event->vd;
 
 #ifndef UNDER_CE
     /* 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" );
+        //if( vd ) msg_Dbg( vd, "WinProc WM_SYSCOMMAND screensaver" );
         return 0; /* this stops them from happening */
     }
 #endif
@@ -751,24 +725,19 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
     {
 
     case WM_WINDOWPOSCHANGED:
-        UpdateRects( p_vout, true );
+        vlc_mutex_lock( &p_event->lock );
+        p_event->has_moved = true;
+        vlc_mutex_unlock( &p_event->lock );
         return 0;
 
     /* the user wants to close the window */
     case WM_CLOSE:
-    {
-        playlist_t * p_playlist = pl_Hold( p_vout );
-        if( p_playlist )
-        {
-            playlist_Stop( p_playlist );
-            pl_Release( p_vout );
-        }
+        vout_display_SendEventClose(vd);
         return 0;
-    }
 
     /* the window has been closed so shut down everything now */
     case WM_DESTROY:
-        msg_Dbg( p_vout, "WinProc WM_DESTROY" );
+        msg_Dbg( vd, "WinProc WM_DESTROY" );
         /* just destroy the window */
         PostQuitMessage( 0 );
         return 0;
@@ -776,14 +745,15 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
     case WM_SYSCOMMAND:
         switch (wParam)
         {
-            case IDM_TOGGLE_ON_TOP:            /* toggle the "on top" status */
-            {
-                msg_Dbg( p_vout, "WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP");
-
-                /* Change the current value */
-                var_ToggleBool( p_vout, "video-on-top" );
-                return 0;
-            }
+        case IDM_TOGGLE_ON_TOP:            /* toggle the "on top" status */
+        {
+            msg_Dbg(vd, "WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP");
+            HMENU hMenu = GetSystemMenu(vd->sys->hwnd, FALSE);
+            vout_display_SendEventOnTop(vd, (GetMenuState(hMenu, IDM_TOGGLE_ON_TOP, MF_BYCOMMAND) & MF_CHECKED) == 0);
+            return 0;
+        }
+        default:
+            break;
         }
         break;
 
@@ -816,13 +786,11 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
         GXResume();
 #endif
 #ifdef UNDER_CE
+        /* FIXME vd->cfg is not lock[ed/able] */
+#warning "FIXME: race condition"
         if( p_event->hparent &&
-            hwnd != p_event->hfswnd && p_vout->b_fullscreen )
-        {
-            vlc_mutex_lock( &p_event->lock );
-            p_event->i_changes |= VOUT_FULLSCREEN_CHANGE;
-            vlc_mutex_unlock( &p_event->lock );
-        }
+            hwnd != p_event->hfswnd && vd->cfg->is_fullscreen )
+            vout_display_SendEventFullscreen(vd, false);
 
         if( hwnd == p_event->hfswnd )
         {
@@ -839,7 +807,7 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
         return 0;
 
     default:
-        //msg_Dbg( p_vout, "WinProc WM Default %i", message );
+        //msg_Dbg( vd, "WinProc WM Default %i", message );
         break;
     }
 
@@ -915,10 +883,7 @@ static int DirectXConvertKey( int i_key )
 
 void EventThreadMouseAutoHide( event_thread_t *p_event )
 {
-    vout_thread_t *p_vout = p_event->p_vout;
-
-    if( p_vout->b_fullscreen &&
-        !p_event->b_cursor_hidden &&
+    if (!p_event->b_cursor_hidden &&
         (mdate() - p_event->i_lastmoved) > p_event->i_mouse_hide_timeout )
     {
         /* Hide the cursor only if it is inside our window */
@@ -942,7 +907,7 @@ void EventThreadMouseShow( event_thread_t *p_event )
 }
 void EventThreadUpdateTitle( event_thread_t *p_event, const char *psz_fallback )
 {
-    char *psz_title = var_GetNonEmptyString( p_event->p_vout, "video-title" );
+    char *psz_title = var_GetNonEmptyString( p_event->vd, "video-title" );
     if( !psz_title )
         psz_title = strdup( psz_fallback );
     if( !psz_title )
@@ -955,15 +920,6 @@ void EventThreadUpdateTitle( event_thread_t *p_event, const char *psz_fallback )
 
     PostMessage( p_event->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
 }
-unsigned EventThreadRetreiveChanges( event_thread_t *p_event )
-{
-    vlc_mutex_lock( &p_event->lock );
-    unsigned i_changes = p_event->i_changes;
-    p_event->i_changes = 0;
-    vlc_mutex_unlock( &p_event->lock );
-
-    return i_changes;
-}
 int EventThreadGetWindowStyle( event_thread_t *p_event )
 {
     /* No need to lock, it is serialized by EventThreadStart */
@@ -986,14 +942,33 @@ void EventThreadUpdateWindowPosition( event_thread_t *p_event, bool *pb_changed,
     vlc_mutex_unlock( &p_event->lock );
 }
 
+void EventThreadUpdateSourceAndPlace( event_thread_t *p_event,
+                                      const video_format_t *p_source,
+                                      const vout_display_place_t *p_place )
+{
+    vlc_mutex_lock( &p_event->lock );
+    p_event->source = *p_source;
+    p_event->place  = *p_place;
+    vlc_mutex_unlock( &p_event->lock );
+}
+
 void EventThreadUseOverlay( event_thread_t *p_event, bool b_used )
 {
     vlc_mutex_lock( &p_event->lock );
     p_event->use_overlay = b_used;
     vlc_mutex_unlock( &p_event->lock );
 }
+bool EventThreadGetAndResetHasMoved( event_thread_t *p_event )
+{
+    vlc_mutex_lock( &p_event->lock );
+    const bool has_moved = p_event->has_moved;
+    p_event->has_moved = false;
+    vlc_mutex_unlock( &p_event->lock );
+
+    return has_moved;
+}
 
-event_thread_t *EventThreadCreate( vout_thread_t *p_vout, const vout_window_cfg_t *p_wnd_cfg )
+event_thread_t *EventThreadCreate( vout_display_t *vd)
 {
      /* Create the Vout EventThread, this thread is created by us to isolate
      * the Win32 PeekMessage function calls. We want to do this because
@@ -1002,22 +977,23 @@ event_thread_t *EventThreadCreate( vout_thread_t *p_vout, const vout_window_cfg_
      * 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" );
+    msg_Dbg( vd, "creating Vout EventThread" );
     event_thread_t *p_event = malloc( sizeof(*p_event) );
     if( !p_event )
         return NULL;
 
-    p_event->p_vout = p_vout;
+    p_event->vd = vd;
     vlc_mutex_init( &p_event->lock );
     vlc_cond_init( &p_event->wait );
 
     p_event->b_cursor_hidden      = false;
     p_event->i_lastmoved          = mdate();
     p_event->i_mouse_hide_timeout =
-        var_GetInteger(p_vout, "mouse-hide-timeout") * 1000;
+        var_GetInteger(vd, "mouse-hide-timeout") * 1000;
     p_event->psz_title = NULL;
-    p_event->wnd_cfg = *p_wnd_cfg;
-   
+    p_event->source = vd->source;
+    vout_display_PlacePicture(&p_event->place, &vd->source, vd->cfg, true);
+
     return p_event;
 }
 
@@ -1033,8 +1009,9 @@ int EventThreadStart( event_thread_t *p_event, event_hwnd_t *p_hwnd, const event
 {
     p_event->use_desktop = p_cfg->use_desktop;
     p_event->use_overlay = p_cfg->use_overlay;
+    p_event->wnd_cfg     = p_cfg->win;
 
-    p_event->i_changes = 0;
+    p_event->has_moved = false;
 
     p_event->b_ready = false;
     p_event->b_done  = false;
@@ -1043,7 +1020,7 @@ int EventThreadStart( event_thread_t *p_event, event_hwnd_t *p_hwnd, const event
     if( vlc_clone( &p_event->thread, EventThread, p_event,
                    VLC_THREAD_PRIORITY_LOW ) )
     {
-        msg_Err( p_event->p_vout, "cannot create Vout EventThread" );
+        msg_Err( p_event->vd, "cannot create Vout EventThread" );
         return VLC_EGENERIC;
     }
 
@@ -1059,12 +1036,10 @@ int EventThreadStart( event_thread_t *p_event, event_hwnd_t *p_hwnd, const event
         p_event->b_ready = false;
         return VLC_EGENERIC;
     }
-    msg_Dbg( p_event->p_vout, "Vout EventThread running" );
+    msg_Dbg( p_event->vd, "Vout EventThread running" );
 
-    if( !p_event->use_desktop )
-        p_hwnd->parent_window = p_event->parent_window;
-    else
-        p_hwnd->parent_window = NULL;
+    /* */
+    p_hwnd->parent_window = p_event->parent_window;
     p_hwnd->hparent       = p_event->hparent;
     p_hwnd->hwnd          = p_event->hwnd;
     p_hwnd->hvideownd     = p_event->hvideownd;
index 4cc1d4ee18d3bfabc27c1675ba22ad562ed499ab..80eb9b67dbf68c647884d8b03ed3d8fb8f32521e 100644 (file)
@@ -32,6 +32,8 @@ typedef struct event_thread_t event_thread_t;
 typedef struct {
     bool use_desktop; /* direct3d */
     bool use_overlay; /* directx */
+
+    vout_window_cfg_t win;
 } event_cfg_t;
 
 typedef struct {
@@ -42,7 +44,7 @@ typedef struct {
     HWND hfswnd;
 } event_hwnd_t;
 
-event_thread_t *EventThreadCreate( vout_thread_t *, const vout_window_cfg_t * );
+event_thread_t *EventThreadCreate( vout_display_t *);
 void            EventThreadDestroy( event_thread_t * );
 int             EventThreadStart( event_thread_t *, event_hwnd_t *, const event_cfg_t * );
 void            EventThreadStop( event_thread_t * );
@@ -50,8 +52,12 @@ void            EventThreadStop( event_thread_t * );
 void            EventThreadMouseAutoHide( event_thread_t * );
 void            EventThreadMouseShow( event_thread_t * );
 void            EventThreadUpdateTitle( event_thread_t *, const char *psz_fallback );
-unsigned        EventThreadRetreiveChanges( event_thread_t * );
 int             EventThreadGetWindowStyle( event_thread_t * );
 void            EventThreadUpdateWindowPosition( event_thread_t *, bool *pb_changed,
                                                  int x, int y, int w, int h );
+void            EventThreadUpdateSourceAndPlace( event_thread_t *p_event,
+                                                 const video_format_t *p_source,
+                                                 const vout_display_place_t *p_place );
 void            EventThreadUseOverlay( event_thread_t *, bool b_used );
+bool            EventThreadGetAndResetHasMoved( event_thread_t * );
+