It also fixes a few remaining race conditions.
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 = \
#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>
#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);
}
/*****************************************************************************
* 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
* 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
#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 */
#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
#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
--- /dev/null
+/*****************************************************************************
+ * 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
#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>
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 ()
/*****************************************************************************
* 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;
}
*/
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;
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 */
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;
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;
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;
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 },
{ 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;
}
}
}
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;
}
// 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;
}
}
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;
}
#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>
#endif
#include <vlc_keys.h>
-#include "vout.h"
+#include "common.h"
#ifdef UNDER_CE
#include <aygshell.h>
struct event_thread_t
{
- vout_thread_t *p_vout;
+ vout_display_t *vd;
/* */
vlc_thread_t thread;
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 );
/*****************************************************************************
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 ();
/* 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
/* 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 );
/* */
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 ) )
{
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:
{
/* 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);
*****************************************************************************/
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;
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);
{
#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
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
* 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;
}
}
* 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;
}
}
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 );
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;
}
/* 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 );
*****************************************************************************/
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
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;
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
{
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;
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;
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 )
{
return 0;
default:
- //msg_Dbg( p_vout, "WinProc WM Default %i", message );
+ //msg_Dbg( vd, "WinProc WM Default %i", message );
break;
}
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 */
}
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 )
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 */
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
* 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;
}
{
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;
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;
}
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;
typedef struct {
bool use_desktop; /* direct3d */
bool use_overlay; /* directx */
+
+ vout_window_cfg_t win;
} event_cfg_t;
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 * );
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 * );
+