* display video in window mode.
*
*****************************************************************************/
-
-#include <errno.h> /* ENOMEM */
-
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
+#include <assert.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
-#include <vlc_vout.h>
+#include <vlc_vout_display.h>
#include <vlc_playlist.h> /* needed for wallpaper */
-#include <windows.h>
#include <ddraw.h>
-#include <commctrl.h>
+#include <commctrl.h> /* ListView_(Get|Set)* */
#ifndef UNDER_CE
# include <multimon.h>
# define MONITOR_DEFAULTTONEAREST 2
#endif
-#include "vout.h"
-
-/*****************************************************************************
- * picture_sys_t: direct buffer method descriptor
- *****************************************************************************
- * This structure is part of the picture descriptor, it describes the
- * DirectX specific properties of a direct buffer.
- *****************************************************************************/
-struct picture_sys_t
-{
- LPDIRECTDRAWSURFACE2 p_surface;
- LPDIRECTDRAWSURFACE2 p_front_surface;
- DDSURFACEDESC ddsd;
-};
-
-/*****************************************************************************
- * DirectDraw GUIDs.
- * Defining them here allows us to get rid of the dxguid library during
- * the linking stage.
- *****************************************************************************/
-#include <initguid.h>
-#undef GUID_EXT
-#define GUID_EXT
-DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
-DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );
+#include "common.h"
-/*****************************************************************************
- * Local prototypes.
- *****************************************************************************/
-static int OpenVideo ( vlc_object_t * );
-static void CloseVideo ( vlc_object_t * );
-
-static int Init ( vout_thread_t * );
-static void End ( vout_thread_t * );
-static int Manage ( vout_thread_t * );
-static void Display ( vout_thread_t *, picture_t * );
-static void FirstDisplay( vout_thread_t *, picture_t * );
-static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
-
-static int NewPictureVec ( vout_thread_t *, picture_t * );
-static void FreePictureVec ( vout_thread_t *, picture_t *, int );
-static int UpdatePictureStruct( vout_thread_t *, picture_t * );
-
-static int DirectXInitDDraw ( vout_thread_t *p_vout );
-static void DirectXCloseDDraw ( vout_thread_t *p_vout );
-static int DirectXCreateDisplay ( vout_thread_t *p_vout );
-static void DirectXCloseDisplay ( vout_thread_t *p_vout );
-static int DirectXCreateSurface ( vout_thread_t *p_vout,
- LPDIRECTDRAWSURFACE2 *, int, int, int );
-static void DirectXCloseSurface ( vout_thread_t *p_vout,
- LPDIRECTDRAWSURFACE2 );
-static int DirectXCreateClipper ( vout_thread_t *p_vout );
-static void DirectXGetDDrawCaps ( vout_thread_t *p_vout );
-static int DirectXLockSurface ( vout_thread_t *p_vout, picture_t *p_pic );
-static int DirectXUnlockSurface ( vout_thread_t *p_vout, picture_t *p_pic );
-
-static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *i_color );
-
-void SwitchWallpaperMode( vout_thread_t *, bool );
-
-/* Object variables callbacks */
-static int FindDevicesCallback( vlc_object_t *, char const *,
- vlc_value_t, vlc_value_t, void * );
-static int WallpaperCallback( vlc_object_t *, char const *,
- vlc_value_t, vlc_value_t, void * );
+#ifdef UNICODE
+# error "Unicode mode not supported"
+#endif
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#define HW_YUV_TEXT N_("Use hardware YUV->RGB conversions")
-#define HW_YUV_LONGTEXT N_( \
+#define HW_YUV_LONGTEXT N_(\
"Try to use hardware acceleration for YUV->RGB conversions. " \
- "This option doesn't have any effect when using overlays." )
+ "This option doesn't have any effect when using overlays.")
#define SYSMEM_TEXT N_("Use video buffers in system memory")
-#define SYSMEM_LONGTEXT N_( \
+#define SYSMEM_LONGTEXT N_(\
"Create video buffers in system memory instead of video memory. This " \
"isn't recommended as usually using video memory allows to benefit from " \
"more hardware acceleration (like rescaling or YUV->RGB conversions). " \
- "This option doesn't have any effect when using overlays." )
+ "This option doesn't have any effect when using overlays.")
#define TRIPLEBUF_TEXT N_("Use triple buffering for overlays")
-#define TRIPLEBUF_LONGTEXT N_( \
+#define TRIPLEBUF_LONGTEXT N_(\
"Try to use triple buffering when using YUV overlays. That results in " \
- "much better video quality (no flickering)." )
+ "much better video quality (no flickering).")
#define DEVICE_TEXT N_("Name of desired display device")
#define DEVICE_LONGTEXT N_("In a multiple monitor configuration, you can " \
"specify the Windows device name of the display that you want the video " \
"window to open on. For example, \"\\\\.\\DISPLAY1\" or " \
- "\"\\\\.\\DISPLAY2\"." )
-
-#define WALLPAPER_TEXT N_("Enable wallpaper mode ")
-#define WALLPAPER_LONGTEXT N_( \
- "The wallpaper mode allows you to display the video as the desktop " \
- "background. Note that this feature only works in overlay mode and " \
- "the desktop must not already have a wallpaper." )
-
-static const char *const ppsz_dev[] = { "" };
-static const char *const ppsz_dev_text[] = { N_("Default") };
-
-vlc_module_begin ()
- set_shortname( "DirectX" )
- set_category( CAT_VIDEO )
- set_subcategory( SUBCAT_VIDEO_VOUT )
- add_bool( "directx-hw-yuv", 1, NULL, HW_YUV_TEXT, HW_YUV_LONGTEXT,
- true )
- add_bool( "directx-use-sysmem", 0, NULL, SYSMEM_TEXT, SYSMEM_LONGTEXT,
- true )
- add_bool( "directx-3buffering", 1, NULL, TRIPLEBUF_TEXT,
- TRIPLEBUF_LONGTEXT, true )
-
- add_string( "directx-device", "", NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
- true )
- change_string_list( ppsz_dev, ppsz_dev_text, FindDevicesCallback )
- change_action_add( FindDevicesCallback, N_("Refresh list") )
-
- add_bool( "directx-wallpaper", 0, NULL, WALLPAPER_TEXT, WALLPAPER_LONGTEXT,
- true )
-
- set_description( N_("DirectX video output") )
- set_capability( "video output", 100 )
- add_shortcut( "directx" )
- set_callbacks( OpenVideo, CloseVideo )
-
- /* FIXME: Hack to avoid unregistering our window class */
- linked_with_a_crap_library_which_uses_atexit ()
-vlc_module_end ()
-
-#if 0 /* FIXME */
- /* check if we registered a window class because we need to
- * unregister it */
- WNDCLASS wndclass;
- if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )
- UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );
-#endif
+ "\"\\\\.\\DISPLAY2\".")
+
+#define DX_HELP N_("Recommended video output for Windows XP. " \
+ "Incompatible with Vista's Aero interface" )
+
+static const char * const device[] = { "" };
+static const char * const device_text[] = { N_("Default") };
+
+static int Open (vlc_object_t *);
+static void Close(vlc_object_t *);
+
+static int FindDevicesCallback(vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void *);
+vlc_module_begin()
+ set_shortname("DirectX")
+ set_description(N_("DirectX (DirectDraw) video output"))
+ set_help(DX_HELP)
+ set_category(CAT_VIDEO)
+ set_subcategory(SUBCAT_VIDEO_VOUT)
+ add_bool("directx-hw-yuv", true, NULL, HW_YUV_TEXT, HW_YUV_LONGTEXT,
+ true)
+ add_bool("directx-use-sysmem", false, NULL, SYSMEM_TEXT, SYSMEM_LONGTEXT,
+ true)
+ add_bool("directx-3buffering", true, NULL, TRIPLEBUF_TEXT,
+ TRIPLEBUF_LONGTEXT, true)
+ add_string("directx-device", "", NULL, DEVICE_TEXT, DEVICE_LONGTEXT, true)
+ change_string_list(device, device_text, FindDevicesCallback)
+ change_action_add(FindDevicesCallback, N_("Refresh list"))
+
+ set_capability("vout display", 100)
+ add_shortcut("directx")
+ set_callbacks(Open, Close)
+vlc_module_end()
/*****************************************************************************
- * OpenVideo: allocate DirectX video thread output method
- *****************************************************************************
- * This function allocates and initialize the DirectX vout method.
+ * Local prototypes.
*****************************************************************************/
-static int OpenVideo( vlc_object_t *p_this )
-{
- vout_thread_t * p_vout = (vout_thread_t *)p_this;
- vlc_value_t val;
- HMODULE huser32;
-
- /* Allocate structure */
- p_vout->p_sys = calloc( 1, sizeof( vout_sys_t ) );
- if( p_vout->p_sys == NULL )
- return VLC_ENOMEM;
-
- /* Initialisations */
- p_vout->pf_init = Init;
- p_vout->pf_end = End;
- p_vout->pf_manage = Manage;
- p_vout->pf_render = NULL;
- p_vout->pf_display = FirstDisplay;
-
- p_vout->p_sys->p_ddobject = NULL;
- p_vout->p_sys->p_display = NULL;
- p_vout->p_sys->p_current_surface = NULL;
- p_vout->p_sys->p_clipper = NULL;
- p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
- p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
- p_vout->p_sys->i_changes = 0;
- p_vout->p_sys->b_wallpaper = 0;
- vlc_mutex_init( &p_vout->p_sys->lock );
- SetRectEmpty( &p_vout->p_sys->rect_display );
- SetRectEmpty( &p_vout->p_sys->rect_parent );
-
- /* Multimonitor stuff */
- p_vout->p_sys->hmonitor = NULL;
- p_vout->p_sys->p_display_driver = NULL;
- p_vout->p_sys->MonitorFromWindow = NULL;
- p_vout->p_sys->GetMonitorInfo = NULL;
- if( (huser32 = GetModuleHandle( _T("USER32") ) ) )
- {
- p_vout->p_sys->MonitorFromWindow = (HMONITOR (WINAPI *)( HWND, DWORD ))
- GetProcAddress( huser32, _T("MonitorFromWindow") );
- p_vout->p_sys->GetMonitorInfo =
-#ifndef UNICODE
- GetProcAddress( huser32, "GetMonitorInfoA" );
-#else
- GetProcAddress( huser32, _T("GetMonitorInfoW") );
-#endif
- }
-
- var_Create( p_vout, "overlay", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
- var_Create( p_vout, "directx-use-sysmem", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
- var_Create( p_vout, "directx-hw-yuv", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
- var_Create( p_vout, "directx-3buffering", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
- var_Create( p_vout, "directx-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
- var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
- var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
- p_vout->p_sys->b_cursor_hidden = 0;
- p_vout->p_sys->i_lastmoved = mdate();
- p_vout->p_sys->i_mouse_hide_timeout =
- var_GetInteger(p_vout, "mouse-hide-timeout") * 1000;
+struct picture_sys_t {
+ LPDIRECTDRAWSURFACE2 surface;
+ LPDIRECTDRAWSURFACE2 front_surface;
+ picture_t *fallback;
+};
- /* Set main window's size */
- p_vout->p_sys->i_window_width = p_vout->i_window_width;
- p_vout->p_sys->i_window_height = p_vout->i_window_height;
+/*****************************************************************************
+ * DirectDraw GUIDs.
+ * Defining them here allows us to get rid of the dxguid library during
+ * the linking stage.
+ *****************************************************************************/
+#include <initguid.h>
+#undef GUID_EXT
+#define GUID_EXT
+DEFINE_GUID(IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56);
+DEFINE_GUID(IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27);
- if ( !CreateEventThread( p_vout ) )
- goto error;
+static picture_pool_t *Pool (vout_display_t *, unsigned);
+static void Display(vout_display_t *, picture_t *);
+static int Control(vout_display_t *, int, va_list);
+static void Manage (vout_display_t *);
- /* Initialise DirectDraw */
- if( DirectXInitDDraw( p_vout ) )
- {
- msg_Err( p_vout, "cannot initialize DirectX DirectDraw" );
- goto error;
- }
+/* */
+static int WallpaperCallback(vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void *);
- /* Create the directx display */
- if( DirectXCreateDisplay( p_vout ) )
- {
- msg_Err( p_vout, "cannot initialize DirectX DirectDraw" );
- goto error;
- }
+static int DirectXOpen(vout_display_t *, video_format_t *fmt);
+static void DirectXClose(vout_display_t *);
- /* Variable to indicate if the window should be on top of others */
- /* Trigger a callback right now */
- var_TriggerCallback( p_vout, "video-on-top" );
+static int DirectXLock(picture_t *);
+static void DirectXUnlock(picture_t *);
- /* Variable to indicate if the window should be on top of others */
- /* Trigger a callback right now */
- var_Create( p_vout, "directx-wallpaper", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
- val.psz_string = _("Wallpaper");
- var_Change( p_vout, "directx-wallpaper", VLC_VAR_SETTEXT, &val, NULL );
- var_AddCallback( p_vout, "directx-wallpaper", WallpaperCallback, NULL );
- var_TriggerCallback( p_vout, "directx-wallpaper" );
+static int DirectXUpdateOverlay(vout_display_t *, LPDIRECTDRAWSURFACE2 surface);
- DisableScreensaver ( p_vout );
+static void WallpaperChange(vout_display_t *vd, bool use_wallpaper);
- return VLC_SUCCESS;
+/** This function allocates and initialize the DirectX vout display.
+ */
+static int Open(vlc_object_t *object)
+{
+ vout_display_t *vd = (vout_display_t *)object;
+ vout_display_sys_t *sys;
- error:
- CloseVideo( VLC_OBJECT(p_vout) );
- return VLC_EGENERIC;
-}
+ /* Allocate structure */
+ vd->sys = sys = calloc(1, sizeof(*sys));
+ if (!sys)
+ return VLC_ENOMEM;
-/*****************************************************************************
- * Init: initialize DirectX video thread output method
- *****************************************************************************
- * This function create the directx surfaces needed by the output thread.
- * It is called at the beginning of the thread.
- *****************************************************************************/
-static int Init( vout_thread_t *p_vout )
-{
- int i_chroma_backup;
-
- /* Get a few default parameters */
- p_vout->p_sys->b_using_overlay = var_GetBool( p_vout, "overlay" );
- p_vout->p_sys->b_use_sysmem = var_GetBool( p_vout, "directx-use-sysmem" );
- p_vout->p_sys->b_hw_yuv = var_GetBool( p_vout, "directx-hw-yuv" );
- p_vout->p_sys->b_3buf_overlay = var_GetBool( p_vout, "directx-3buffering" );
-
- /* Initialise DirectDraw if not already done.
- * We do this here because on multi-monitor systems we may have to
- * re-create the directdraw surfaces. */
- if( !p_vout->p_sys->p_ddobject &&
- DirectXInitDDraw( p_vout ) != VLC_SUCCESS )
- {
- msg_Err( p_vout, "cannot initialize DirectDraw" );
+ /* Load direct draw DLL */
+ sys->hddraw_dll = LoadLibrary(_T("DDRAW.DLL"));
+ if (!sys->hddraw_dll) {
+ msg_Warn(vd, "DirectXInitDDraw failed loading ddraw.dll");
+ free(sys);
return VLC_EGENERIC;
}
- /* Create the directx display */
- if( !p_vout->p_sys->p_display &&
- DirectXCreateDisplay( p_vout ) != VLC_SUCCESS )
- {
- msg_Err( p_vout, "cannot initialize DirectDraw" );
- return VLC_EGENERIC;
+ /* */
+ HMODULE huser32 = GetModuleHandle(_T("USER32"));
+ if (huser32) {
+ sys->MonitorFromWindow = (void*)GetProcAddress(huser32, _T("MonitorFromWindow"));
+ sys->GetMonitorInfo = (void*)GetProcAddress(huser32, _T("GetMonitorInfoA"));
+ } else {
+ sys->MonitorFromWindow = NULL;
+ sys->GetMonitorInfo = NULL;
}
- /* Initialize the output structure.
- * Since DirectDraw can do rescaling for us, stick to the default
- * coordinates and aspect. */
- p_vout->output.i_width = p_vout->render.i_width;
- p_vout->output.i_height = p_vout->render.i_height;
- p_vout->output.i_aspect = p_vout->render.i_aspect;
- p_vout->fmt_out = p_vout->fmt_in;
- UpdateRects( p_vout, true );
-
-#define MAX_DIRECTBUFFERS 1
- /* Right now we use only 1 directbuffer because we don't want the
- * video decoder to decode directly into direct buffers as they are
- * created into video memory and video memory is _really_ slow */
-
- /* Choose the chroma we will try first. */
- switch( p_vout->render.i_chroma )
- {
- case VLC_CODEC_YUYV:
- p_vout->output.i_chroma = VLC_CODEC_YUYV;
- break;
- case VLC_CODEC_UYVY:
- p_vout->output.i_chroma = VLC_CODEC_UYVY;
- break;
- case VLC_CODEC_YVYU:
- p_vout->output.i_chroma = VLC_CODEC_YVYU;
- break;
- default:
- p_vout->output.i_chroma = VLC_CODEC_YV12;
- break;
- }
+ /* */
+ sys->use_wallpaper = var_CreateGetBool(vd, "video-wallpaper");
+ /* FIXME */
+ sys->use_overlay = false;//var_CreateGetBool(vd, "overlay"); /* FIXME */
+ sys->restore_overlay = false;
+ var_Create(vd, "directx-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
- NewPictureVec( p_vout, p_vout->p_picture );
+ /* Initialisation */
+ if (CommonInit(vd))
+ goto error;
- i_chroma_backup = p_vout->output.i_chroma;
+ /* */
+ video_format_t fmt = vd->fmt;
- if( !I_OUTPUTPICTURES )
- {
- /* hmmm, it didn't work! Let's try commonly supported chromas */
- if( p_vout->output.i_chroma != VLC_CODEC_I420 )
- {
- p_vout->output.i_chroma = VLC_CODEC_YV12;
- NewPictureVec( p_vout, p_vout->p_picture );
- }
- if( !I_OUTPUTPICTURES )
- {
- /* hmmm, it still didn't work! Let's try another one */
- p_vout->output.i_chroma = VLC_CODEC_YUYV;
- NewPictureVec( p_vout, p_vout->p_picture );
- }
- }
+ if (DirectXOpen(vd, &fmt))
+ goto error;
- if( !I_OUTPUTPICTURES )
- {
- /* If it still didn't work then don't try to use an overlay */
- p_vout->output.i_chroma = i_chroma_backup;
- p_vout->p_sys->b_using_overlay = 0;
- msg_Warn( p_vout, "Could not initialize directx overlay" ) ;
- NewPictureVec( p_vout, p_vout->p_picture );
- }
+ /* */
+ vout_display_info_t info = vd->info;
+ info.is_slow = true;
+ info.has_double_click = true;
+ info.has_hide_mouse = false;
+ info.has_pictures_invalid = true;
+ info.has_event_thread = true;
- /* Change the window title bar text */
- PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
+ /* Interaction TODO support starting with wallpaper mode */
+ vlc_mutex_init(&sys->lock);
+ sys->ch_wallpaper = sys->use_wallpaper;
+ sys->wallpaper_requested = sys->use_wallpaper;
+ sys->use_wallpaper = false;
- p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
+ vlc_value_t val;
+ val.psz_string = _("Wallpaper");
+ var_Change(vd, "video-wallpaper", VLC_VAR_SETTEXT, &val, NULL);
+ var_AddCallback(vd, "video-wallpaper", WallpaperCallback, NULL);
+
+ /* Setup vout_display now that everything is fine */
+ vd->fmt = fmt;
+ vd->info = info;
+
+ vd->pool = Pool;
+ vd->prepare = NULL;
+ vd->display = Display;
+ vd->control = Control;
+ vd->manage = Manage;
return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * End: terminate Sys video thread output method
- *****************************************************************************
- * Terminate an output method created by Create.
- * It is called at the end of the thread.
- *****************************************************************************/
-static void End( vout_thread_t *p_vout )
-{
- FreePictureVec( p_vout, p_vout->p_picture, I_OUTPUTPICTURES );
-
- DirectXCloseDisplay( p_vout );
- DirectXCloseDDraw( p_vout );
- return;
+error:
+ DirectXClose(vd);
+ CommonClean(vd);
+ if (sys->hddraw_dll)
+ FreeLibrary(sys->hddraw_dll);
+ free(sys);
+ return VLC_EGENERIC;
}
-/*****************************************************************************
- * CloseVideo: destroy Sys video thread output method
- *****************************************************************************
- * Terminate an output method created by Create
- *****************************************************************************/
-static void CloseVideo( vlc_object_t *p_this )
+/** Terminate a vout display created by Open.
+ */
+static void Close(vlc_object_t *object)
{
- vout_thread_t * p_vout = (vout_thread_t *)p_this;
+ vout_display_t *vd = (vout_display_t *)object;
+ vout_display_sys_t *sys = vd->sys;
- StopEventThread( p_vout );
+ var_DelCallback(vd, "video-wallpaper", WallpaperCallback, NULL);
+ vlc_mutex_destroy(&sys->lock);
/* Make sure the wallpaper is restored */
- var_DelCallback( p_vout, "directx-wallpaper", WallpaperCallback, NULL );
- SwitchWallpaperMode( p_vout, false );
+ WallpaperChange(vd, false);
+
+ DirectXClose(vd);
- RestoreScreensaver( p_vout );
+ CommonClean(vd);
- free( p_vout->p_sys );
+ if (sys->hddraw_dll)
+ FreeLibrary(sys->hddraw_dll);
+ free(sys);
}
-/*****************************************************************************
- * 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 picture_pool_t *Pool(vout_display_t *vd, unsigned count)
{
- /* If we do not control our window, we check for geometry changes
- * ourselves because the parent might not send us its events. */
- vlc_mutex_lock( &p_vout->p_sys->lock );
- if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
- {
- RECT rect_parent;
- POINT point;
+ VLC_UNUSED(count);
+ return vd->sys->pool;
+}
+static void Display(vout_display_t *vd, picture_t *picture)
+{
+ vout_display_sys_t *sys = vd->sys;
- vlc_mutex_unlock( &p_vout->p_sys->lock );
+ assert(sys->display);
- GetClientRect( p_vout->p_sys->hparent, &rect_parent );
- point.x = point.y = 0;
- ClientToScreen( p_vout->p_sys->hparent, &point );
- OffsetRect( &rect_parent, point.x, point.y );
+ /* Our surface can be lost so be sure to check this
+ * and restore it if need be */
+ if (IDirectDrawSurface2_IsLost(sys->display) == DDERR_SURFACELOST) {
+ if (IDirectDrawSurface2_Restore(sys->display) == DD_OK) {
+ if (sys->use_overlay)
+ DirectXUpdateOverlay(vd, NULL);
+ }
+ }
+ if (sys->restore_overlay)
+ DirectXUpdateOverlay(vd, NULL);
- if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
- {
- p_vout->p_sys->rect_parent = rect_parent;
+ /* */
+ DirectXUnlock(picture);
- /* 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 );
+ if (sys->use_overlay) {
+ /* Flip the overlay buffers if we are using back buffers */
+ if (picture->p_sys->surface != picture->p_sys->front_surface) {
+ HRESULT hr = IDirectDrawSurface2_Flip(picture->p_sys->front_surface,
+ NULL, DDFLIP_WAIT);
+ if (hr != DD_OK)
+ msg_Warn(vd, "could not flip overlay (error %li)", hr);
+ }
+ } else {
+ /* Blit video surface to display with the NOTEARING option */
+ DDBLTFX ddbltfx;
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
- SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
- rect_parent.right - rect_parent.left,
- rect_parent.bottom - rect_parent.top, 0 );
+ HRESULT hr = IDirectDrawSurface2_Blt(sys->display,
+ &sys->rect_dest_clipped,
+ picture->p_sys->surface,
+ &sys->rect_src_clipped,
+ DDBLT_ASYNC, &ddbltfx);
+ if (hr != DD_OK)
+ msg_Warn(vd, "could not blit surface (error %li)", hr);
+ }
+ DirectXLock(picture);
+
+ if (sys->is_first_display) {
+ IDirectDraw_WaitForVerticalBlank(sys->ddobject,
+ DDWAITVB_BLOCKBEGIN, NULL);
+ if (sys->use_overlay) {
+ HBRUSH brush = CreateSolidBrush(sys->i_rgb_colorkey);
+ /* set the colorkey as the backgound brush for the video window */
+ SetClassLongPtr(sys->hvideownd, GCLP_HBRBACKGROUND, (LONG_PTR)brush);
}
}
- else
- {
- vlc_mutex_unlock( &p_vout->p_sys->lock );
- }
+ CommonDisplay(vd);
- /*
- * Position Change
- */
- if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE )
- {
- p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
+ picture_Release(picture);
+}
+static int Control(vout_display_t *vd, int query, va_list args)
+{
+ vout_display_sys_t *sys = vd->sys;
+
+ switch (query) {
+ case VOUT_DISPLAY_RESET_PICTURES:
+ DirectXClose(vd);
+ /* Make sure the wallpaper is restored */
+ if (sys->use_wallpaper) {
+ vlc_mutex_lock(&sys->lock);
+ if (!sys->ch_wallpaper) {
+ sys->ch_wallpaper = true;
+ sys->wallpaper_requested = true;
+ }
+ vlc_mutex_unlock(&sys->lock);
- /* Check if we are still on the same monitor */
- if( p_vout->p_sys->MonitorFromWindow &&
- p_vout->p_sys->hmonitor !=
- p_vout->p_sys->MonitorFromWindow( p_vout->p_sys->hwnd,
- MONITOR_DEFAULTTONEAREST ) )
- {
- /* This will force the vout core to recreate the picture buffers */
- p_vout->i_changes |= VOUT_PICTURE_BUFFERS_CHANGE;
+ WallpaperChange(vd, false);
}
+ return DirectXOpen(vd, &vd->fmt);
+ default:
+ return CommonControl(vd, query, args);
}
+}
+static void Manage(vout_display_t *vd)
+{
+ vout_display_sys_t *sys = vd->sys;
- /* autoscale toggle */
- if( p_vout->i_changes & VOUT_SCALE_CHANGE )
- {
- p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
+ CommonManage(vd);
- p_vout->b_autoscale = var_GetBool( p_vout, "autoscale" );
- p_vout->i_zoom = (int) ZOOM_FP_FACTOR;
+ if (sys->changes & DX_POSITION_CHANGE) {
+ /* Update overlay */
+ if (sys->use_overlay)
+ DirectXUpdateOverlay(vd, NULL);
- UpdateRects( p_vout, true );
+ /* Check if we are still on the same monitor */
+ if (sys->MonitorFromWindow &&
+ sys->hmonitor != sys->MonitorFromWindow(sys->hwnd, MONITOR_DEFAULTTONEAREST)) {
+ vout_display_SendEventPicturesInvalid(vd);
+ }
+ /* */
+ sys->changes &= ~DX_POSITION_CHANGE;
}
- /* scaling factor */
- if( p_vout->i_changes & VOUT_ZOOM_CHANGE )
- {
- p_vout->i_changes &= ~VOUT_ZOOM_CHANGE;
+ /* Wallpaper mode change */
+ vlc_mutex_lock(&sys->lock);
+ const bool ch_wallpaper = sys->ch_wallpaper;
+ const bool wallpaper_requested = sys->wallpaper_requested;
+ sys->ch_wallpaper = false;
+ vlc_mutex_unlock(&sys->lock);
- p_vout->b_autoscale = false;
- p_vout->i_zoom =
- (int)( ZOOM_FP_FACTOR * var_GetFloat( p_vout, "scale" ) );
- UpdateRects( p_vout, true );
- }
+ if (ch_wallpaper)
+ WallpaperChange(vd, wallpaper_requested);
- /* 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 );
- }
+ /* */
+ if (sys->restore_overlay)
+ DirectXUpdateOverlay(vd, NULL);
+}
- /* 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. */
+/* */
+static int DirectXOpenDDraw(vout_display_t *);
+static void DirectXCloseDDraw(vout_display_t *);
- if( p_vout->p_sys->i_changes & DX_WALLPAPER_CHANGE )
- {
- SwitchWallpaperMode( p_vout, !p_vout->p_sys->b_wallpaper );
- p_vout->p_sys->i_changes &= ~DX_WALLPAPER_CHANGE;
- DirectDrawUpdateOverlay( p_vout );
- }
+static int DirectXOpenDisplay(vout_display_t *vd);
+static void DirectXCloseDisplay(vout_display_t *vd);
- /*
- * Fullscreen change
- */
- if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
- || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
- {
- Win32ToggleFullscreen( p_vout );
+static int DirectXCreatePool(vout_display_t *, bool *, video_format_t *);
+static void DirectXDestroyPool(vout_display_t *);
- p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
- p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
- }
+static int DirectXOpen(vout_display_t *vd, video_format_t *fmt)
+{
+ vout_display_sys_t *sys = vd->sys;
- /*
- * Pointer change
- */
- if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&
- (mdate() - p_vout->p_sys->i_lastmoved) >
- p_vout->p_sys->i_mouse_hide_timeout )
- {
- POINT point;
- HWND hwnd;
-
- /* Hide the cursor only if it is inside our window */
- GetCursorPos( &point );
- hwnd = WindowFromPoint(point);
- if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )
- {
- PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
- }
- else
- {
- p_vout->p_sys->i_lastmoved = mdate();
- }
- }
+ assert(!sys->ddobject);
+ assert(!sys->display);
+ assert(!sys->clipper);
- /*
- * "Always on top" status change
- */
- if( p_vout->p_sys->b_on_top_change )
- {
- vlc_value_t val;
- HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
-
- var_Get( p_vout, "video-on-top", &val );
-
- /* Set the window on top if necessary */
- if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
- & WS_EX_TOPMOST ) )
- {
- CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
- MF_BYCOMMAND | MFS_CHECKED );
- SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE );
- }
- else
- /* The window shouldn't be on top */
- if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
- & WS_EX_TOPMOST ) )
- {
- CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
- MF_BYCOMMAND | MFS_UNCHECKED );
- SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE );
- }
+ /* Initialise DirectDraw */
+ if (DirectXOpenDDraw(vd)) {
+ msg_Err(vd, "cannot initialize DirectX DirectDraw");
+ return VLC_EGENERIC;
+ }
- p_vout->p_sys->b_on_top_change = false;
+ /* Create the directx display */
+ if (DirectXOpenDisplay(vd)) {
+ msg_Err(vd, "cannot initialize DirectX DirectDraw");
+ return VLC_EGENERIC;
}
+ UpdateRects(vd, NULL, NULL, true);
- /* Check if the event thread is still running */
- if( !vlc_object_alive (p_vout->p_sys->p_event) )
- {
- return VLC_EGENERIC; /* exit */
+ /* Create the picture pool */
+ if (DirectXCreatePool(vd, &sys->use_overlay, fmt)) {
+ msg_Err(vd, "cannot create any DirectX surface");
+ return VLC_EGENERIC;
}
+ /* */
+ if (sys->use_overlay)
+ DirectXUpdateOverlay(vd, NULL);
+ EventThreadUseOverlay(sys->event, sys->use_overlay);
+
+ /* Change the window title bar text */
+ const char *fallback;
+ if (sys->use_overlay)
+ fallback = VOUT_TITLE " (hardware YUV overlay DirectX output)";
+ else if (vlc_fourcc_IsYUV(fmt->i_chroma))
+ fallback = VOUT_TITLE " (hardware YUV DirectX output)";
+ else
+ fallback = VOUT_TITLE " (software RGB DirectX output)";
+ EventThreadUpdateTitle(sys->event, fallback);
+
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 )
+static void DirectXClose(vout_display_t *vd)
{
- HRESULT dxresult;
+ DirectXDestroyPool(vd);
+ DirectXCloseDisplay(vd);
+ DirectXCloseDDraw(vd);
+}
- if( (p_vout->p_sys->p_display == NULL) )
- {
- msg_Warn( p_vout, "no display!" );
- return;
- }
+/* */
+static BOOL WINAPI DirectXOpenDDrawCallback(GUID *guid, LPTSTR desc,
+ LPTSTR drivername, VOID *context,
+ HMONITOR hmon)
+{
+ vout_display_t *vd = context;
+ vout_display_sys_t *sys = vd->sys;
- /* Our surface can be lost so be sure to check this
- * and restore it if need be */
- if( IDirectDrawSurface2_IsLost( p_vout->p_sys->p_display )
- == DDERR_SURFACELOST )
- {
- if( IDirectDrawSurface2_Restore( p_vout->p_sys->p_display ) == DD_OK &&
- p_vout->p_sys->b_using_overlay )
- DirectDrawUpdateOverlay( p_vout );
- }
+ /* This callback function is called by DirectDraw once for each
+ * available DirectDraw device.
+ *
+ * Returning TRUE keeps enumerating.
+ */
+ if (!hmon)
+ return TRUE;
- if( !p_vout->p_sys->b_using_overlay )
- {
- DDBLTFX ddbltfx;
+ msg_Dbg(vd, "DirectXEnumCallback: %s, %s", desc, drivername);
- /* We ask for the "NOTEARING" option */
- memset( &ddbltfx, 0, sizeof(DDBLTFX) );
- ddbltfx.dwSize = sizeof(DDBLTFX);
- ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
+ char *device = var_GetString(vd, "directx-device");
- /* Blit video surface to display */
- dxresult = IDirectDrawSurface2_Blt( p_vout->p_sys->p_display,
- &p_vout->p_sys->rect_dest_clipped,
- p_pic->p_sys->p_surface,
- &p_vout->p_sys->rect_src_clipped,
- DDBLT_ASYNC, &ddbltfx );
- if( dxresult != DD_OK )
- {
- msg_Warn( p_vout, "could not blit surface (error %li)", dxresult );
- return;
+ /* Check for forced device */
+ if (device && *device && !strcmp(drivername, device)) {
+ MONITORINFO monitor_info;
+ monitor_info.cbSize = sizeof(MONITORINFO);
+
+ if (sys->GetMonitorInfo(hmon, &monitor_info)) {
+ RECT rect;
+
+ /* Move window to the right screen */
+ GetWindowRect(sys->hwnd, &rect);
+ if (!IntersectRect(&rect, &rect, &monitor_info.rcWork)) {
+ rect.left = monitor_info.rcWork.left;
+ rect.top = monitor_info.rcWork.top;
+ msg_Dbg(vd, "DirectXEnumCallback: setting window "
+ "position to %ld,%ld", rect.left, rect.top);
+ SetWindowPos(sys->hwnd, NULL,
+ rect.left, rect.top, 0, 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+ }
}
+ sys->hmonitor = hmon;
}
- else /* using overlay */
- {
- /* Flip the overlay buffers if we are using back buffers */
- if( p_pic->p_sys->p_front_surface == p_pic->p_sys->p_surface )
- {
- return;
- }
-
- dxresult = IDirectDrawSurface2_Flip( p_pic->p_sys->p_front_surface,
- NULL, DDFLIP_WAIT );
- if( dxresult != DD_OK )
- {
- msg_Warn( p_vout, "could not flip overlay (error %li)", dxresult );
- }
+ free(device);
- /* set currently displayed pic */
- p_vout->p_sys->p_current_surface = p_pic->p_sys->p_front_surface;
+ if (hmon == sys->hmonitor) {
+ msg_Dbg(vd, "selecting %s, %s", desc, drivername);
- /* Lock surface to get all the required info */
- if( DirectXLockSurface( p_vout, p_pic ) )
- {
- /* AAARRGG */
- msg_Warn( p_vout, "cannot lock surface" );
- return;
- }
- DirectXUnlockSurface( p_vout, p_pic );
+ free(sys->display_driver);
+ sys->display_driver = malloc(sizeof(*guid));
+ if (sys->display_driver)
+ *sys->display_driver = *guid;
}
-}
-
-/*
-** this function is only used once when the first picture is received
-** this function will show the video window once video is ready for
-** display.
-*/
-
-static void FirstDisplay( vout_thread_t *p_vout, picture_t *p_pic )
-{
- /* get initial picture rendered on overlay surface */
- Display(p_vout, p_pic);
-
- IDirectDraw_WaitForVerticalBlank(p_vout->p_sys->p_ddobject,
- DDWAITVB_BLOCKBEGIN, NULL);
- if( p_vout->p_sys->b_using_overlay )
- {
- /* set the colorkey as the backgound brush for the video window */
- SetClassLongPtr( p_vout->p_sys->hvideownd, GCLP_HBRBACKGROUND,
- (LONG_PTR)CreateSolidBrush( p_vout->p_sys->i_rgb_colorkey ) );
- }
- /*
- ** Video window is initially hidden, show it now since we got a
- ** picture to show.
- */
- SetWindowPos( p_vout->p_sys->hvideownd, NULL, 0, 0, 0, 0,
- SWP_ASYNCWINDOWPOS|
- SWP_FRAMECHANGED|
- SWP_SHOWWINDOW|
- SWP_NOMOVE|
- SWP_NOSIZE|
- SWP_NOZORDER );
-
- /* use and restores proper display function for further pictures */
- p_vout->pf_display = Display;
+ return TRUE;
}
-
-/* following functions are local */
-
-/*****************************************************************************
- * DirectXEnumCallback: Device enumeration
- *****************************************************************************
- * This callback function is called by DirectDraw once for each
- * available DirectDraw device.
- *****************************************************************************/
-BOOL WINAPI DirectXEnumCallback( GUID* p_guid, LPTSTR psz_desc,
- LPTSTR psz_drivername, VOID* p_context,
- HMONITOR hmon )
+/**
+ * Probe the capabilities of the hardware
+ *
+ * It is nice to know which features are supported by the hardware so we can
+ * find ways to optimize our rendering.
+ */
+static void DirectXGetDDrawCaps(vout_display_t *vd)
{
- vout_thread_t *p_vout = (vout_thread_t *)p_context;
- vlc_value_t device;
-
- msg_Dbg( p_vout, "DirectXEnumCallback: %s, %s", psz_desc, psz_drivername );
-
- if( hmon )
- {
- var_Get( p_vout, "directx-device", &device );
-
- if( ( !device.psz_string || !*device.psz_string ) &&
- hmon == p_vout->p_sys->hmonitor )
- {
- free( device.psz_string );
- }
- else if( strcmp( psz_drivername, device.psz_string ) == 0 )
- {
- MONITORINFO monitor_info;
- monitor_info.cbSize = sizeof( MONITORINFO );
-
- if( p_vout->p_sys->GetMonitorInfo( hmon, &monitor_info ) )
- {
- RECT rect;
-
- /* Move window to the right screen */
- GetWindowRect( p_vout->p_sys->hwnd, &rect );
- if( !IntersectRect( &rect, &rect, &monitor_info.rcWork ) )
- {
- rect.left = monitor_info.rcWork.left;
- rect.top = monitor_info.rcWork.top;
- msg_Dbg( p_vout, "DirectXEnumCallback: setting window "
- "position to %ld,%ld", rect.left, rect.top );
- SetWindowPos( p_vout->p_sys->hwnd, NULL,
- rect.left, rect.top, 0, 0,
- SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
- }
- }
-
- p_vout->p_sys->hmonitor = hmon;
- free( device.psz_string );
- }
- else
- {
- free( device.psz_string );
- return TRUE; /* Keep enumerating */
- }
+ vout_display_sys_t *sys = vd->sys;
- msg_Dbg( p_vout, "selecting %s, %s", psz_desc, psz_drivername );
- p_vout->p_sys->p_display_driver = malloc( sizeof(GUID) );
- if( p_vout->p_sys->p_display_driver )
- memcpy( p_vout->p_sys->p_display_driver, p_guid, sizeof(GUID) );
+ /* This is just an indication of whether or not we'll support overlay,
+ * but with this test we don't know if we support YUV overlay */
+ DDCAPS ddcaps;
+ ZeroMemory(&ddcaps, sizeof(ddcaps));
+ ddcaps.dwSize = sizeof(ddcaps);
+ HRESULT hr = IDirectDraw2_GetCaps(sys->ddobject, &ddcaps, NULL);
+ if (hr != DD_OK) {
+ msg_Warn(vd, "cannot get caps");
+ return;
}
- return TRUE; /* Keep enumerating */
+ /* Determine if the hardware supports overlay surfaces */
+ const bool has_overlay = ddcaps.dwCaps & DDCAPS_OVERLAY;
+ /* Determine if the hardware supports overlay surfaces */
+ const bool has_overlay_fourcc = ddcaps.dwCaps & DDCAPS_OVERLAYFOURCC;
+ /* Determine if the hardware supports overlay deinterlacing */
+ const bool can_deinterlace = ddcaps.dwCaps & DDCAPS2_CANFLIPODDEVEN;
+ /* Determine if the hardware supports colorkeying */
+ const bool has_color_key = ddcaps.dwCaps & DDCAPS_COLORKEY;
+ /* Determine if the hardware supports scaling of the overlay surface */
+ const bool can_stretch = ddcaps.dwCaps & DDCAPS_OVERLAYSTRETCH;
+ /* Determine if the hardware supports color conversion during a blit */
+ sys->can_blit_fourcc = ddcaps.dwCaps & DDCAPS_BLTFOURCC;
+ /* Determine overlay source boundary alignment */
+ const bool align_boundary_src = ddcaps.dwCaps & DDCAPS_ALIGNBOUNDARYSRC;
+ /* Determine overlay destination boundary alignment */
+ const bool align_boundary_dest = ddcaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST;
+ /* Determine overlay destination size alignment */
+ const bool align_size_src = ddcaps.dwCaps & DDCAPS_ALIGNSIZESRC;
+ /* Determine overlay destination size alignment */
+ const bool align_size_dest = ddcaps.dwCaps & DDCAPS_ALIGNSIZEDEST;
+
+ msg_Dbg(vd, "DirectDraw Capabilities: overlay=%i yuvoverlay=%i "
+ "can_deinterlace_overlay=%i colorkey=%i stretch=%i "
+ "bltfourcc=%i",
+ has_overlay, has_overlay_fourcc, can_deinterlace,
+ has_color_key, can_stretch, sys->can_blit_fourcc);
+
+ if (align_boundary_src || align_boundary_dest || align_size_src || align_size_dest) {
+ if (align_boundary_src)
+ vd->sys->i_align_src_boundary = ddcaps.dwAlignBoundarySrc;
+ if (align_boundary_dest)
+ vd->sys->i_align_dest_boundary = ddcaps.dwAlignBoundaryDest;
+ if (align_size_src)
+ vd->sys->i_align_src_size = ddcaps.dwAlignSizeSrc;
+ if (align_size_dest)
+ vd->sys->i_align_dest_size = ddcaps.dwAlignSizeDest;
+
+ msg_Dbg(vd,
+ "align_boundary_src=%i,%i align_boundary_dest=%i,%i "
+ "align_size_src=%i,%i align_size_dest=%i,%i",
+ align_boundary_src, vd->sys->i_align_src_boundary,
+ align_boundary_dest, vd->sys->i_align_dest_boundary,
+ align_size_src, vd->sys->i_align_src_size,
+ align_size_dest, vd->sys->i_align_dest_size);
+ }
}
-/*****************************************************************************
- * DirectXInitDDraw: Takes care of all the DirectDraw initialisations
- *****************************************************************************
- * This function initialise and allocate resources for DirectDraw.
- *****************************************************************************/
-static int DirectXInitDDraw( vout_thread_t *p_vout )
-{
- HRESULT dxresult;
- HRESULT (WINAPI *OurDirectDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
- HRESULT (WINAPI *OurDirectDrawEnumerateEx)( LPDDENUMCALLBACKEXA, LPVOID,
- DWORD );
- LPDIRECTDRAW p_ddobject;
- msg_Dbg( p_vout, "DirectXInitDDraw" );
- /* Load direct draw DLL */
- p_vout->p_sys->hddraw_dll = LoadLibrary(_T("DDRAW.DLL"));
- if( p_vout->p_sys->hddraw_dll == NULL )
- {
- msg_Warn( p_vout, "DirectXInitDDraw failed loading ddraw.dll" );
- goto error;
- }
+/* */
+static int DirectXOpenDDraw(vout_display_t *vd)
+{
+ vout_display_sys_t *sys = vd->sys;
+ HRESULT hr;
+ /* */
+ HRESULT (WINAPI *OurDirectDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
OurDirectDrawCreate =
- (void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
- _T("DirectDrawCreate") );
- if( OurDirectDrawCreate == NULL )
- {
- msg_Err( p_vout, "DirectXInitDDraw failed GetProcAddress" );
- goto error;
+ (void *)GetProcAddress(sys->hddraw_dll, _T("DirectDrawCreate"));
+ if (!OurDirectDrawCreate) {
+ msg_Err(vd, "DirectXInitDDraw failed GetProcAddress");
+ return VLC_EGENERIC;
}
- OurDirectDrawEnumerateEx =
- (void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
-#ifndef UNICODE
- "DirectDrawEnumerateExA" );
-#else
- _T("DirectDrawEnumerateExW") );
-#endif
-
- if( OurDirectDrawEnumerateEx && p_vout->p_sys->MonitorFromWindow )
- {
- vlc_value_t device;
+ /* */
+ if (sys->MonitorFromWindow) {
+ HRESULT (WINAPI *OurDirectDrawEnumerateEx)(LPDDENUMCALLBACKEXA, LPVOID, DWORD);
+ OurDirectDrawEnumerateEx =
+ (void *)GetProcAddress(sys->hddraw_dll, _T("DirectDrawEnumerateExA"));
- var_Get( p_vout, "directx-device", &device );
- if( device.psz_string )
- {
- msg_Dbg( p_vout, "directx-device: %s", device.psz_string );
- free( device.psz_string );
- }
+ if (OurDirectDrawEnumerateEx) {
+ char *device = var_GetString(vd, "directx-device");
+ if (device) {
+ msg_Dbg(vd, "directx-device: %s", device);
+ free(device);
+ }
- p_vout->p_sys->hmonitor =
- p_vout->p_sys->MonitorFromWindow( p_vout->p_sys->hwnd,
- MONITOR_DEFAULTTONEAREST );
+ sys->hmonitor = sys->MonitorFromWindow(sys->hwnd, MONITOR_DEFAULTTONEAREST);
- /* Enumerate displays */
- OurDirectDrawEnumerateEx( DirectXEnumCallback, p_vout,
- DDENUM_ATTACHEDSECONDARYDEVICES );
+ /* Enumerate displays */
+ OurDirectDrawEnumerateEx(DirectXOpenDDrawCallback,
+ vd, DDENUM_ATTACHEDSECONDARYDEVICES);
+ }
}
/* Initialize DirectDraw now */
- dxresult = OurDirectDrawCreate( p_vout->p_sys->p_display_driver,
- &p_ddobject, NULL );
- if( dxresult != DD_OK )
- {
- msg_Err( p_vout, "DirectXInitDDraw cannot initialize DDraw" );
- goto error;
+ LPDIRECTDRAW ddobject;
+ hr = OurDirectDrawCreate(sys->display_driver, &ddobject, NULL);
+ if (hr != DD_OK) {
+ msg_Err(vd, "DirectXInitDDraw cannot initialize DDraw");
+ return VLC_EGENERIC;
}
/* Get the IDirectDraw2 interface */
- dxresult = IDirectDraw_QueryInterface( p_ddobject, &IID_IDirectDraw2,
- (LPVOID *)&p_vout->p_sys->p_ddobject );
+ hr = IDirectDraw_QueryInterface(ddobject, &IID_IDirectDraw2,
+ &sys->ddobject);
/* Release the unused interface */
- IDirectDraw_Release( p_ddobject );
- if( dxresult != DD_OK )
- {
- msg_Err( p_vout, "cannot get IDirectDraw2 interface" );
- goto error;
+ IDirectDraw_Release(ddobject);
+
+ if (hr != DD_OK) {
+ msg_Err(vd, "cannot get IDirectDraw2 interface");
+ sys->ddobject = NULL;
+ return VLC_EGENERIC;
}
/* Set DirectDraw Cooperative level, ie what control we want over Windows
* display */
- dxresult = IDirectDraw2_SetCooperativeLevel( p_vout->p_sys->p_ddobject,
- NULL, DDSCL_NORMAL );
- if( dxresult != DD_OK )
- {
- msg_Err( p_vout, "cannot set direct draw cooperative level" );
- goto error;
+ hr = IDirectDraw2_SetCooperativeLevel(sys->ddobject, NULL, DDSCL_NORMAL);
+ if (hr != DD_OK) {
+ msg_Err(vd, "cannot set direct draw cooperative level");
+ return VLC_EGENERIC;
}
/* Get the size of the current display device */
- if( p_vout->p_sys->hmonitor && p_vout->p_sys->GetMonitorInfo )
- {
+ if (sys->hmonitor && sys->GetMonitorInfo) {
MONITORINFO monitor_info;
- monitor_info.cbSize = sizeof( MONITORINFO );
- p_vout->p_sys->GetMonitorInfo( p_vout->p_sys->hmonitor,
- &monitor_info );
- p_vout->p_sys->rect_display = monitor_info.rcMonitor;
- }
- else
- {
- p_vout->p_sys->rect_display.left = 0;
- p_vout->p_sys->rect_display.top = 0;
- p_vout->p_sys->rect_display.right = GetSystemMetrics(SM_CXSCREEN);
- p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
- }
-
- msg_Dbg( p_vout, "screen dimensions (%lix%li,%lix%li)",
- p_vout->p_sys->rect_display.left,
- p_vout->p_sys->rect_display.top,
- p_vout->p_sys->rect_display.right,
- p_vout->p_sys->rect_display.bottom );
+ monitor_info.cbSize = sizeof(MONITORINFO);
+ sys->GetMonitorInfo(vd->sys->hmonitor, &monitor_info);
+ sys->rect_display = monitor_info.rcMonitor;
+ } else {
+ sys->rect_display.left = 0;
+ sys->rect_display.top = 0;
+ sys->rect_display.right = GetSystemMetrics(SM_CXSCREEN);
+ sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
+ }
+
+ msg_Dbg(vd, "screen dimensions (%lix%li,%lix%li)",
+ sys->rect_display.left,
+ sys->rect_display.top,
+ sys->rect_display.right,
+ sys->rect_display.bottom);
/* Probe the capabilities of the hardware */
- DirectXGetDDrawCaps( p_vout );
+ DirectXGetDDrawCaps(vd);
- msg_Dbg( p_vout, "End DirectXInitDDraw" );
return VLC_SUCCESS;
-
- error:
- if( p_vout->p_sys->p_ddobject )
- IDirectDraw2_Release( p_vout->p_sys->p_ddobject );
- if( p_vout->p_sys->hddraw_dll )
- FreeLibrary( p_vout->p_sys->hddraw_dll );
- p_vout->p_sys->hddraw_dll = NULL;
- p_vout->p_sys->p_ddobject = NULL;
- return VLC_EGENERIC;
}
-/*****************************************************************************
- * DirectXCreateDisplay: create the DirectDraw display.
- *****************************************************************************
- * Create and initialize display according to preferences specified in the vout
- * thread fields.
- *****************************************************************************/
-static int DirectXCreateDisplay( vout_thread_t *p_vout )
+static void DirectXCloseDDraw(vout_display_t *vd)
{
- HRESULT dxresult;
- DDSURFACEDESC ddsd;
- LPDIRECTDRAWSURFACE p_display;
+ vout_display_sys_t *sys = vd->sys;
+ if (sys->ddobject)
+ IDirectDraw2_Release(sys->ddobject);
- msg_Dbg( p_vout, "DirectXCreateDisplay" );
+ sys->ddobject = NULL;
- /* Now get the primary surface. This surface is what you actually see
- * on your screen */
- memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
- ddsd.dwSize = sizeof(DDSURFACEDESC);
- ddsd.dwFlags = DDSD_CAPS;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
-
- dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
- &ddsd, &p_display, NULL );
- if( dxresult != DD_OK )
- {
- msg_Err( p_vout, "cannot get primary surface (error %li)", dxresult );
- return VLC_EGENERIC;
- }
+ free(sys->display_driver);
+ sys->display_driver = NULL;
- dxresult = IDirectDrawSurface_QueryInterface( p_display,
- &IID_IDirectDrawSurface2,
- (LPVOID *)&p_vout->p_sys->p_display );
- /* Release the old interface */
- IDirectDrawSurface_Release( p_display );
- if ( dxresult != DD_OK )
- {
- msg_Err( p_vout, "cannot query IDirectDrawSurface2 interface "
- "(error %li)", dxresult );
- return VLC_EGENERIC;
- }
-
- /* The clipper will be used only in non-overlay mode */
- DirectXCreateClipper( p_vout );
-
- /* Make sure the colorkey will be painted */
- p_vout->p_sys->i_colorkey = 1;
- p_vout->p_sys->i_rgb_colorkey =
- DirectXFindColorkey( p_vout, &p_vout->p_sys->i_colorkey );
-
- UpdateRects( p_vout, true );
-
- return VLC_SUCCESS;
+ sys->hmonitor = NULL;
}
-/*****************************************************************************
- * DirectXCreateClipper: Create a clipper that will be used when blitting the
- * RGB surface to the main display.
- *****************************************************************************
+/**
+ * Create a clipper that will be used when blitting the RGB surface to the main display.
+ *
* This clipper prevents us to modify by mistake anything on the screen
* which doesn't belong to our window. For example when a part of our video
* window is hidden by another window.
- *****************************************************************************/
-static int DirectXCreateClipper( vout_thread_t *p_vout )
+ */
+static void DirectXCreateClipper(vout_display_t *vd)
{
- HRESULT dxresult;
-
- msg_Dbg( p_vout, "DirectXCreateClipper" );
+ vout_display_sys_t *sys = vd->sys;
+ HRESULT hr;
/* Create the clipper */
- dxresult = IDirectDraw2_CreateClipper( p_vout->p_sys->p_ddobject, 0,
- &p_vout->p_sys->p_clipper, NULL );
- if( dxresult != DD_OK )
- {
- msg_Warn( p_vout, "cannot create clipper (error %li)", dxresult );
+ hr = IDirectDraw2_CreateClipper(sys->ddobject, 0, &sys->clipper, NULL);
+ if (hr != DD_OK) {
+ msg_Warn(vd, "cannot create clipper (error %li)", hr);
goto error;
}
/* Associate the clipper to the window */
- dxresult = IDirectDrawClipper_SetHWnd( p_vout->p_sys->p_clipper, 0,
- p_vout->p_sys->hvideownd );
- if( dxresult != DD_OK )
- {
- msg_Warn( p_vout, "cannot attach clipper to window (error %li)",
- dxresult );
+ hr = IDirectDrawClipper_SetHWnd(sys->clipper, 0, sys->hvideownd);
+ if (hr != DD_OK) {
+ msg_Warn(vd, "cannot attach clipper to window (error %li)", hr);
goto error;
}
/* associate the clipper with the surface */
- dxresult = IDirectDrawSurface_SetClipper(p_vout->p_sys->p_display,
- p_vout->p_sys->p_clipper);
- if( dxresult != DD_OK )
+ hr = IDirectDrawSurface_SetClipper(sys->display, sys->clipper);
+ if (hr != DD_OK)
{
- msg_Warn( p_vout, "cannot attach clipper to surface (error %li)",
- dxresult );
+ msg_Warn(vd, "cannot attach clipper to surface (error %li)", hr);
goto error;
}
- return VLC_SUCCESS;
+ return;
- error:
- if( p_vout->p_sys->p_clipper )
- {
- IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
+error:
+ if (sys->clipper)
+ IDirectDrawClipper_Release(sys->clipper);
+ sys->clipper = NULL;
+}
+
+/**
+ * It finds out the 32bits RGB pixel value of the colorkey.
+ */
+static uint32_t DirectXFindColorkey(vout_display_t *vd, uint32_t *color)
+{
+ vout_display_sys_t *sys = vd->sys;
+ HRESULT hr;
+
+ /* */
+ DDSURFACEDESC ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ hr = IDirectDrawSurface2_Lock(sys->display, NULL, &ddsd, DDLOCK_WAIT, NULL);
+ if (hr != DD_OK)
+ return 0;
+
+ uint32_t backup = *(uint32_t *)ddsd.lpSurface;
+
+ switch (ddsd.ddpfPixelFormat.dwRGBBitCount) {
+ case 4:
+ *(uint8_t *)ddsd.lpSurface = *color | (*color << 4);
+ break;
+ case 8:
+ *(uint8_t *)ddsd.lpSurface = *color;
+ break;
+ case 15:
+ case 16:
+ *(uint16_t *)ddsd.lpSurface = *color;
+ break;
+ case 24:
+ /* Seems to be problematic so we'll just put black as the colorkey */
+ *color = 0;
+ default:
+ *(uint32_t *)ddsd.lpSurface = *color;
+ break;
}
- p_vout->p_sys->p_clipper = NULL;
- return VLC_EGENERIC;
+ IDirectDrawSurface2_Unlock(sys->display, NULL);
+
+ /* */
+ HDC hdc;
+ COLORREF rgb;
+ if (IDirectDrawSurface2_GetDC(sys->display, &hdc) == DD_OK) {
+ rgb = GetPixel(hdc, 0, 0);
+ IDirectDrawSurface2_ReleaseDC(sys->display, hdc);
+ } else {
+ rgb = 0;
+ }
+
+ /* Restore the pixel value */
+ ddsd.dwSize = sizeof(ddsd);
+ if (IDirectDrawSurface2_Lock(sys->display, NULL, &ddsd, DDLOCK_WAIT, NULL) == DD_OK) {
+ *(uint32_t *)ddsd.lpSurface = backup;
+ IDirectDrawSurface2_Unlock(sys->display, NULL);
+ }
+
+ return rgb;
}
-/*****************************************************************************
- * DirectXCreateSurface: create an YUV overlay or RGB surface for the video.
- *****************************************************************************
+/**
+ * Create and initialize display according to preferences specified in the vout
+ * thread fields.
+ */
+static int DirectXOpenDisplay(vout_display_t *vd)
+{
+ vout_display_sys_t *sys = vd->sys;
+ HRESULT hr;
+
+ /* Now get the primary surface. This surface is what you actually see
+ * on your screen */
+ DDSURFACEDESC ddsd;
+ ZeroMemory(&ddsd, sizeof(ddsd));
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ LPDIRECTDRAWSURFACE display;
+ hr = IDirectDraw2_CreateSurface(sys->ddobject, &ddsd, &display, NULL);
+ if (hr != DD_OK) {
+ msg_Err(vd, "cannot get primary surface (error %li)", hr);
+ return VLC_EGENERIC;
+ }
+
+ hr = IDirectDrawSurface_QueryInterface(display, &IID_IDirectDrawSurface2,
+ &sys->display);
+ /* Release the old interface */
+ IDirectDrawSurface_Release(display);
+
+ if (hr != DD_OK) {
+ msg_Err(vd, "cannot query IDirectDrawSurface2 interface (error %li)", hr);
+ sys->display = NULL;
+ return VLC_EGENERIC;
+ }
+
+ /* The clipper will be used only in non-overlay mode */
+ DirectXCreateClipper(vd);
+
+ /* Make sure the colorkey will be painted */
+ sys->i_colorkey = 1;
+ sys->i_rgb_colorkey = DirectXFindColorkey(vd, &sys->i_colorkey);
+
+ return VLC_SUCCESS;
+}
+static void DirectXCloseDisplay(vout_display_t *vd)
+{
+ vout_display_sys_t *sys = vd->sys;
+
+ if (sys->clipper != NULL)
+ IDirectDrawClipper_Release(sys->clipper);
+
+ if (sys->display != NULL)
+ IDirectDrawSurface2_Release(sys->display);
+
+ sys->clipper = NULL;
+ sys->display = NULL;
+}
+
+/**
+ * Create an YUV overlay or RGB surface for the video.
+ *
* The best method of display is with an YUV overlay because the YUV->RGB
* conversion is done in hardware.
* You can also create a plain RGB surface.
- * ( Maybe we could also try an RGB overlay surface, which could have hardware
+ * (Maybe we could also try an RGB overlay surface, which could have hardware
* scaling and which would also be faster in window mode because you don't
* need to do any blitting to the main display...)
- *****************************************************************************/
-static int DirectXCreateSurface( vout_thread_t *p_vout,
- LPDIRECTDRAWSURFACE2 *pp_surface_final,
- int i_chroma, int b_overlay,
- int i_backbuffers )
+ */
+static int DirectXCreateSurface(vout_display_t *vd,
+ LPDIRECTDRAWSURFACE2 *surface,
+ const video_format_t *fmt,
+ DWORD fourcc,
+ bool use_overlay,
+ bool use_sysmem,
+ int backbuffer_count)
{
- HRESULT dxresult;
- LPDIRECTDRAWSURFACE p_surface;
+ vout_display_sys_t *sys = vd->sys;
+
DDSURFACEDESC ddsd;
- /* Create the video surface */
- if( b_overlay )
- {
- /* Now try to create the YUV overlay surface.
- * This overlay will be displayed on top of the primary surface.
- * A color key is used to determine whether or not the overlay will be
- * displayed, ie the overlay will be displayed in place of the primary
- * surface wherever the primary surface will have this color.
- * The video window has been created with a background of this color so
- * the overlay will be only displayed on top of this window */
-
- memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
- ddsd.dwSize = sizeof(DDSURFACEDESC);
- ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+ ZeroMemory(&ddsd, sizeof(ddsd));
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
+ ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
+ ddsd.dwWidth = fmt->i_width;
+ ddsd.dwHeight = fmt->i_height;
+ if (fourcc) {
+ ddsd.dwFlags |= DDSD_PIXELFORMAT;
ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
- ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
- ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
- ddsd.dwFlags |= (i_backbuffers ? DDSD_BACKBUFFERCOUNT : 0);
- ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
- ddsd.ddsCaps.dwCaps |= (i_backbuffers ? DDSCAPS_COMPLEX | DDSCAPS_FLIP
- : 0 );
- ddsd.dwHeight = p_vout->render.i_height;
- ddsd.dwWidth = p_vout->render.i_width;
- ddsd.dwBackBufferCount = i_backbuffers;
-
- dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
- &ddsd, &p_surface, NULL );
- if( dxresult != DD_OK )
- {
- *pp_surface_final = NULL;
- return VLC_EGENERIC;
- }
+ ddsd.ddpfPixelFormat.dwFourCC = fourcc;
}
+ if (use_overlay) {
+ ddsd.dwFlags |= DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
+ if (backbuffer_count > 0)
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP;
- if( !b_overlay )
- {
- bool b_rgb_surface =
- ( i_chroma == VLC_CODEC_RGB8 )
- || ( i_chroma == VLC_CODEC_RGB15 )
- || ( i_chroma == VLC_CODEC_RGB16 )
- || ( i_chroma == VLC_CODEC_RGB24 )
- || ( i_chroma == VLC_CODEC_RGB32 );
-
- memset( &ddsd, 0, sizeof( DDSURFACEDESC ) );
- ddsd.dwSize = sizeof(DDSURFACEDESC);
- ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
- ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS;
+ if (backbuffer_count > 0) {
+ ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
+ ddsd.dwBackBufferCount = backbuffer_count;
+ }
+ } else {
+ ddsd.dwFlags |= DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
- ddsd.dwHeight = p_vout->render.i_height;
- ddsd.dwWidth = p_vout->render.i_width;
-
- if( p_vout->p_sys->b_use_sysmem )
+ if (use_sysmem)
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
else
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
-
- if( !b_rgb_surface )
- {
- ddsd.dwFlags |= DDSD_PIXELFORMAT;
- ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
- ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
- }
-
- dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
- &ddsd, &p_surface, NULL );
- if( dxresult != DD_OK )
- {
- *pp_surface_final = NULL;
- return VLC_EGENERIC;
- }
}
+ /* Create the video surface */
+ LPDIRECTDRAWSURFACE surface_v1;
+ if (IDirectDraw2_CreateSurface(sys->ddobject, &ddsd, &surface_v1, NULL) != DD_OK)
+ return VLC_EGENERIC;
+
/* Now that the surface is created, try to get a newer DirectX interface */
- dxresult = IDirectDrawSurface_QueryInterface( p_surface,
- &IID_IDirectDrawSurface2,
- (LPVOID *)pp_surface_final );
- IDirectDrawSurface_Release( p_surface ); /* Release the old interface */
- if ( dxresult != DD_OK )
- {
- msg_Err( p_vout, "cannot query IDirectDrawSurface2 interface "
- "(error %li)", dxresult );
- *pp_surface_final = NULL;
+ HRESULT hr = IDirectDrawSurface_QueryInterface(surface_v1,
+ &IID_IDirectDrawSurface2,
+ (LPVOID *)surface);
+ IDirectDrawSurface_Release(surface_v1);
+ if (hr != DD_OK) {
+ msg_Err(vd, "cannot query IDirectDrawSurface2 interface (error %li)", hr);
return VLC_EGENERIC;
}
- if( b_overlay )
- {
+ if (use_overlay) {
/* Check the overlay is useable as some graphics cards allow creating
* several overlays but only one can be used at one time. */
- p_vout->p_sys->p_current_surface = *pp_surface_final;
- if( DirectDrawUpdateOverlay( p_vout ) != VLC_SUCCESS )
- {
- IDirectDrawSurface2_Release( *pp_surface_final );
- *pp_surface_final = NULL;
- msg_Err( p_vout, "overlay unuseable (might already be in use)" );
+ if (DirectXUpdateOverlay(vd, *surface)) {
+ IDirectDrawSurface2_Release(*surface);
+ msg_Err(vd, "overlay unuseable (might already be in use)");
return VLC_EGENERIC;
}
}
return VLC_SUCCESS;
}
-/*****************************************************************************
- * DirectDrawUpdateOverlay: Move or resize overlay surface on video display.
- *****************************************************************************
- * This function is used to move or resize an overlay surface on the screen.
- * Ususally the overlay is moved by the user and thus, by a move or resize
- * event (in Manage).
- *****************************************************************************/
-int DirectDrawUpdateOverlay( vout_thread_t *p_vout )
+static void DirectXDestroySurface(LPDIRECTDRAWSURFACE2 surface)
{
- DDOVERLAYFX ddofx;
- DWORD dwFlags;
- HRESULT dxresult;
- RECT rect_src = p_vout->p_sys->rect_src_clipped;
- RECT rect_dest = p_vout->p_sys->rect_dest_clipped;
-
- if( !p_vout->p_sys->b_using_overlay ) return VLC_EGENERIC;
-
- if( p_vout->p_sys->b_wallpaper )
- {
- unsigned i_x, i_y, i_width, i_height;
-
- rect_src.left = p_vout->fmt_out.i_x_offset;
- rect_src.top = p_vout->fmt_out.i_y_offset;
- rect_src.right = rect_src.left + p_vout->fmt_out.i_visible_width;
- rect_src.bottom = rect_src.top + p_vout->fmt_out.i_visible_height;
-
- rect_dest = p_vout->p_sys->rect_display;
- vout_PlacePicture( p_vout, rect_dest.right, rect_dest.bottom,
- &i_x, &i_y, &i_width, &i_height );
-
- rect_dest.left += i_x;
- rect_dest.right = rect_dest.left + i_width;
- rect_dest.top += i_y;
- rect_dest.bottom = rect_dest.top + i_height;
- }
-
- vlc_mutex_lock( &p_vout->p_sys->lock );
- if( p_vout->p_sys->p_current_surface == NULL )
- {
- vlc_mutex_unlock( &p_vout->p_sys->lock );
- return VLC_EGENERIC;
- }
-
- /* The new window dimensions should already have been computed by the
- * caller of this function */
-
- /* Position and show the overlay */
- memset(&ddofx, 0, sizeof(DDOVERLAYFX));
- ddofx.dwSize = sizeof(DDOVERLAYFX);
- ddofx.dckDestColorkey.dwColorSpaceLowValue = p_vout->p_sys->i_colorkey;
- ddofx.dckDestColorkey.dwColorSpaceHighValue = p_vout->p_sys->i_colorkey;
+ IDirectDrawSurface2_Release(surface);
+}
+/**
+ * This function locks a surface and get the surface descriptor.
+ */
+static int DirectXLockSurface(LPDIRECTDRAWSURFACE2 front_surface,
+ LPDIRECTDRAWSURFACE2 surface,
+ DDSURFACEDESC *ddsd)
+{
+ HRESULT hr;
- dwFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
+ DDSURFACEDESC ddsd_dummy;
+ if (!ddsd)
+ ddsd = &ddsd_dummy;
- dxresult = IDirectDrawSurface2_UpdateOverlay(
- p_vout->p_sys->p_current_surface,
- &rect_src, p_vout->p_sys->p_display, &rect_dest,
- dwFlags, &ddofx );
+ ZeroMemory(ddsd, sizeof(*ddsd));
+ ddsd->dwSize = sizeof(*ddsd);
+ hr = IDirectDrawSurface2_Lock(surface, NULL, ddsd, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL);
+ if (hr != DD_OK) {
+ if (hr == DDERR_INVALIDPARAMS) {
+ /* DirectX 3 doesn't support the DDLOCK_NOSYSLOCK flag, resulting
+ * in an invalid params error */
+ hr = IDirectDrawSurface2_Lock(surface, NULL, ddsd, DDLOCK_WAIT, NULL);
+ }
+ if (hr == DDERR_SURFACELOST) {
+ /* Your surface can be lost so be sure
+ * to check this and restore it if needed */
- vlc_mutex_unlock( &p_vout->p_sys->lock );
+ /* When using overlays with back-buffers, we need to restore
+ * the front buffer so the back-buffers get restored as well. */
+ if (front_surface != surface)
+ IDirectDrawSurface2_Restore(front_surface);
+ else
+ IDirectDrawSurface2_Restore(surface);
- if(dxresult != DD_OK)
- {
- msg_Warn( p_vout, "DirectDrawUpdateOverlay cannot move/resize overlay" );
- return VLC_EGENERIC;
+ hr = IDirectDrawSurface2_Lock(surface, NULL, ddsd, DDLOCK_WAIT, NULL);
+ }
+ if (hr != DD_OK)
+ return VLC_EGENERIC;
}
-
return VLC_SUCCESS;
}
-
-/*****************************************************************************
- * DirectXCloseDDraw: Release the DDraw object allocated by DirectXInitDDraw
- *****************************************************************************
- * This function returns all resources allocated by DirectXInitDDraw.
- *****************************************************************************/
-static void DirectXCloseDDraw( vout_thread_t *p_vout )
+static void DirectXUnlockSurface(LPDIRECTDRAWSURFACE2 front_surface,
+ LPDIRECTDRAWSURFACE2 surface)
{
- msg_Dbg( p_vout, "DirectXCloseDDraw" );
- if( p_vout->p_sys->p_ddobject != NULL )
- {
- IDirectDraw2_Release(p_vout->p_sys->p_ddobject);
- p_vout->p_sys->p_ddobject = NULL;
- }
-
- if( p_vout->p_sys->hddraw_dll != NULL )
- {
- FreeLibrary( p_vout->p_sys->hddraw_dll );
- p_vout->p_sys->hddraw_dll = NULL;
- }
-
- free( p_vout->p_sys->p_display_driver );
- p_vout->p_sys->p_display_driver = NULL;
+ IDirectDrawSurface2_Unlock(surface, NULL);
+}
+static int DirectXCheckLockingSurface(LPDIRECTDRAWSURFACE2 front_surface,
+ LPDIRECTDRAWSURFACE2 surface)
+{
+ if (DirectXLockSurface(front_surface, surface, NULL))
+ return VLC_EGENERIC;
- p_vout->p_sys->hmonitor = NULL;
+ DirectXUnlockSurface(front_surface, surface);
+ return VLC_SUCCESS;
}
-/*****************************************************************************
- * DirectXCloseDisplay: close and reset the DirectX display device
- *****************************************************************************
- * This function returns all resources allocated by DirectXCreateDisplay.
- *****************************************************************************/
-static void DirectXCloseDisplay( vout_thread_t *p_vout )
-{
- msg_Dbg( p_vout, "DirectXCloseDisplay" );
- if( p_vout->p_sys->p_clipper != NULL )
- {
- msg_Dbg( p_vout, "DirectXCloseDisplay clipper" );
- IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
- p_vout->p_sys->p_clipper = NULL;
- }
- if( p_vout->p_sys->p_display != NULL )
- {
- msg_Dbg( p_vout, "DirectXCloseDisplay display" );
- IDirectDrawSurface2_Release( p_vout->p_sys->p_display );
- p_vout->p_sys->p_display = NULL;
- }
-}
+typedef struct {
+ vlc_fourcc_t codec;
+ DWORD fourcc;
+} dx_format_t;
-/*****************************************************************************
- * DirectXCloseSurface: close the YUV overlay or RGB surface.
- *****************************************************************************
- * This function returns all resources allocated for the surface.
- *****************************************************************************/
-static void DirectXCloseSurface( vout_thread_t *p_vout,
- LPDIRECTDRAWSURFACE2 p_surface )
+static DWORD DirectXGetFourcc(vlc_fourcc_t codec)
{
- msg_Dbg( p_vout, "DirectXCloseSurface" );
- if( p_surface != NULL )
- {
- IDirectDrawSurface2_Release( p_surface );
- }
+ static const dx_format_t dx_formats[] = {
+ { VLC_CODEC_YUYV, MAKEFOURCC('Y','U','Y','2') },
+ { VLC_CODEC_UYVY, MAKEFOURCC('U','Y','V','Y') },
+ { VLC_CODEC_YVYU, MAKEFOURCC('Y','V','Y','U') },
+ { VLC_CODEC_YV12, MAKEFOURCC('Y','V','1','2') },
+ { VLC_CODEC_I420, MAKEFOURCC('Y','V','1','2') },
+ { VLC_CODEC_J420, MAKEFOURCC('Y','V','1','2') },
+ { 0, 0 }
+ };
+
+ for (unsigned i = 0; dx_formats[i].codec != 0; i++) {
+ if (dx_formats[i].codec == codec)
+ return dx_formats[i].fourcc;
+ }
+ return 0;
}
-/*****************************************************************************
- * NewPictureVec: allocate a picture
- * FIXME? make it work for i_num_pic pictures...
- *****************************************************************************
- * Returns 0 on success, -1 otherwise
- *****************************************************************************/
-static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic )
+static int DirectXCreatePictureResourceYuvOverlay(vout_display_t *vd,
+ const video_format_t *fmt,
+ DWORD fourcc)
{
- int i;
- int i_ret = VLC_SUCCESS;
- LPDIRECTDRAWSURFACE2 p_surface;
-
- msg_Dbg( p_vout, "NewPictureVec overlay:%s chroma:%.4s",
- p_vout->p_sys->b_using_overlay ? "yes" : "no",
- (char *)&p_vout->output.i_chroma );
+ vout_display_sys_t *sys = vd->sys;
- I_OUTPUTPICTURES = 0;
+ bool allow_3buf = var_InheritBool(vd, "directx-3buffering");
- /* First we try to use an YUV overlay surface.
- * The overlay surface that we create won't be used to decode directly
+ /* The overlay surface that we create won't be used to decode directly
* into it because accessing video memory directly is way to slow (remember
* that pictures are decoded macroblock per macroblock). Instead the video
* will be decoded in picture buffers in system memory which will then be
* memcpy() to the overlay surface. */
- if( p_vout->p_sys->b_using_overlay )
- {
+ LPDIRECTDRAWSURFACE2 front_surface;
+ int ret = VLC_EGENERIC;
+ if (allow_3buf) {
/* Triple buffering rocks! it doesn't have any processing overhead
* (you don't have to wait for the vsync) and provides for a very nice
* video quality (no tearing). */
- if( p_vout->p_sys->b_3buf_overlay )
- i_ret = DirectXCreateSurface( p_vout, &p_surface,
- p_vout->output.i_chroma,
- p_vout->p_sys->b_using_overlay,
- 2 /* number of backbuffers */ );
-
- if( !p_vout->p_sys->b_3buf_overlay || i_ret != VLC_SUCCESS )
- {
- /* Try to reduce the number of backbuffers */
- i_ret = DirectXCreateSurface( p_vout, &p_surface,
- p_vout->output.i_chroma,
- p_vout->p_sys->b_using_overlay,
- 0 /* number of backbuffers */ );
- }
-
- if( i_ret == VLC_SUCCESS )
- {
- DDSCAPS dds_caps;
- picture_t front_pic;
- picture_sys_t front_pic_sys;
- front_pic.p_sys = &front_pic_sys;
-
- /* Allocate internal structure */
- p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
- if( p_pic[0].p_sys == NULL )
- {
- DirectXCloseSurface( p_vout, p_surface );
- return VLC_ENOMEM;
- }
-
- /* set front buffer */
- p_pic[0].p_sys->p_front_surface = p_surface;
-
- /* Get the back buffer */
- memset( &dds_caps, 0, sizeof( DDSCAPS ) );
- dds_caps.dwCaps = DDSCAPS_BACKBUFFER;
- if( DD_OK != IDirectDrawSurface2_GetAttachedSurface(
- p_surface, &dds_caps,
- &p_pic[0].p_sys->p_surface ) )
- {
- msg_Warn( p_vout, "NewPictureVec could not get back buffer" );
- /* front buffer is the same as back buffer */
- p_pic[0].p_sys->p_surface = p_surface;
- }
-
+ ret = DirectXCreateSurface(vd, &front_surface, fmt, fourcc, true, false, 2);
+ }
+ if (ret)
+ ret = DirectXCreateSurface(vd, &front_surface, fmt, fourcc, true, false, 0);
+ if (ret)
+ return VLC_EGENERIC;
+ msg_Dbg(vd, "YUV overlay surface created successfully");
- p_vout->p_sys->p_current_surface = front_pic.p_sys->p_surface =
- p_pic[0].p_sys->p_front_surface;
+ /* Get the back buffer */
+ LPDIRECTDRAWSURFACE2 surface;
+ DDSCAPS dds_caps;
+ ZeroMemory(&dds_caps, sizeof(dds_caps));
+ dds_caps.dwCaps = DDSCAPS_BACKBUFFER;
+ if (IDirectDrawSurface2_GetAttachedSurface(front_surface, &dds_caps, &surface) != DD_OK) {
+ msg_Warn(vd, "Failed to get surface back buffer");
+ /* front buffer is the same as back buffer */
+ surface = front_surface;
+ }
- /* Reset the front buffer memory */
- if( DirectXLockSurface( p_vout, &front_pic ) == VLC_SUCCESS )
- {
- int i,j;
- for( i = 0; i < front_pic.i_planes; i++ )
- for( j = 0; j < front_pic.p[i].i_visible_lines; j++)
- memset( front_pic.p[i].p_pixels + j *
- front_pic.p[i].i_pitch, 127,
- front_pic.p[i].i_visible_pitch );
+ if (DirectXCheckLockingSurface(front_surface, surface)) {
+ DirectXDestroySurface(front_surface);
+ return VLC_EGENERIC;
+ }
- DirectXUnlockSurface( p_vout, &front_pic );
- }
+ /* */
+ picture_resource_t *rsc = &sys->resource;
+ rsc->p_sys->front_surface = front_surface;
+ rsc->p_sys->surface = surface;
+ rsc->p_sys->fallback = NULL;
+ return VLC_SUCCESS;
+}
+static int DirectXCreatePictureResourceYuv(vout_display_t *vd,
+ const video_format_t *fmt,
+ DWORD fourcc)
+{
+ vout_display_sys_t *sys = vd->sys;
- DirectDrawUpdateOverlay( p_vout );
- I_OUTPUTPICTURES = 1;
- msg_Dbg( p_vout, "YUV overlay created successfully" );
- }
- }
+ bool allow_sysmem = var_InheritBool(vd, "directx-use-sysmem");
/* As we can't have an overlay, we'll try to create a plain offscreen
* surface. This surface will reside in video memory because there's a
* acceleration like rescaling, blitting or YUV->RGB conversions.
* We then only need to blit this surface onto the main display when we
* want to display it */
- if( !p_vout->p_sys->b_using_overlay )
- {
- if( p_vout->p_sys->b_hw_yuv )
- {
- DWORD i_codes;
- DWORD *pi_codes;
- bool b_result = false;
-
- /* Check if the chroma is supported first. This is required
- * because a few buggy drivers don't mind creating the surface
- * even if they don't know about the chroma. */
- if( IDirectDraw2_GetFourCCCodes( p_vout->p_sys->p_ddobject,
- &i_codes, NULL ) == DD_OK )
- {
- pi_codes = malloc( i_codes * sizeof(DWORD) );
- if( pi_codes && IDirectDraw2_GetFourCCCodes(
- p_vout->p_sys->p_ddobject, &i_codes, pi_codes ) == DD_OK )
- {
- for( i = 0; i < (int)i_codes; i++ )
- {
- if( p_vout->output.i_chroma == pi_codes[i] )
- {
- b_result = true;
- break;
- }
- }
- }
- }
-
- if( b_result )
- i_ret = DirectXCreateSurface( p_vout, &p_surface,
- p_vout->output.i_chroma,
- 0 /* no overlay */,
- 0 /* no back buffers */ );
- else
- p_vout->p_sys->b_hw_yuv = false;
- }
- if( i_ret || !p_vout->p_sys->b_hw_yuv )
- {
- /* Our last choice is to use a plain RGB surface */
- DDPIXELFORMAT ddpfPixelFormat;
-
- ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
- IDirectDrawSurface2_GetPixelFormat( p_vout->p_sys->p_display,
- &ddpfPixelFormat );
-
- if( ddpfPixelFormat.dwFlags & DDPF_RGB )
- {
- switch( ddpfPixelFormat.dwRGBBitCount )
- {
- case 8:
- p_vout->output.i_chroma = VLC_CODEC_RGB8;
- p_vout->output.pf_setpalette = SetPalette;
- break;
- case 15:
- p_vout->output.i_chroma = VLC_CODEC_RGB15;
- break;
- case 16:
- p_vout->output.i_chroma = VLC_CODEC_RGB16;
- break;
- case 24:
- p_vout->output.i_chroma = VLC_CODEC_RGB24;
- break;
- case 32:
- p_vout->output.i_chroma = VLC_CODEC_RGB32;
- break;
- default:
- msg_Err( p_vout, "unknown screen depth" );
- return VLC_EGENERIC;
- }
- p_vout->output.i_rmask = ddpfPixelFormat.dwRBitMask;
- p_vout->output.i_gmask = ddpfPixelFormat.dwGBitMask;
- p_vout->output.i_bmask = ddpfPixelFormat.dwBBitMask;
- }
-
- p_vout->p_sys->b_hw_yuv = 0;
+ /* Check if the chroma is supported first. This is required
+ * because a few buggy drivers don't mind creating the surface
+ * even if they don't know about the chroma. */
+ DWORD count;
+ if (IDirectDraw2_GetFourCCCodes(sys->ddobject, &count, NULL) != DD_OK)
+ return VLC_EGENERIC;
- i_ret = DirectXCreateSurface( p_vout, &p_surface,
- p_vout->output.i_chroma,
- 0 /* no overlay */,
- 0 /* no back buffers */ );
+ DWORD *list = calloc(count, sizeof(*list));
+ if (!list)
+ return VLC_ENOMEM;
+ if (IDirectDraw2_GetFourCCCodes(sys->ddobject, &count, list) != DD_OK) {
+ free(list);
+ return VLC_EGENERIC;
+ }
+ unsigned index;
+ for (index = 0; index < count; index++) {
+ if (list[index] == fourcc)
+ break;
+ }
+ free(list);
+ if (index >= count)
+ return VLC_EGENERIC;
- if( i_ret && !p_vout->p_sys->b_use_sysmem )
- {
- /* Give it a last try with b_use_sysmem enabled */
- p_vout->p_sys->b_use_sysmem = 1;
+ /* */
+ LPDIRECTDRAWSURFACE2 surface;
+ if (DirectXCreateSurface(vd, &surface, fmt, fourcc, false, allow_sysmem, 0))
+ return VLC_EGENERIC;
+ msg_Dbg(vd, "YUV plain surface created successfully");
- i_ret = DirectXCreateSurface( p_vout, &p_surface,
- p_vout->output.i_chroma,
- 0 /* no overlay */,
- 0 /* no back buffers */ );
- }
- }
+ if (DirectXCheckLockingSurface(surface, surface)) {
+ DirectXDestroySurface(surface);
+ return VLC_EGENERIC;
+ }
- if( i_ret == VLC_SUCCESS )
- {
- /* Allocate internal structure */
- p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
- if( p_pic[0].p_sys == NULL )
- {
- DirectXCloseSurface( p_vout, p_surface );
- return VLC_ENOMEM;
- }
+ /* */
+ picture_resource_t *rsc = &sys->resource;
+ rsc->p_sys->front_surface = surface;
+ rsc->p_sys->surface = surface;
+ rsc->p_sys->fallback = NULL;
+ return VLC_SUCCESS;
+}
+static int DirectXCreatePictureResourceRgb(vout_display_t *vd,
+ video_format_t *fmt)
+{
+ vout_display_sys_t *sys = vd->sys;
+ bool allow_sysmem = var_InheritBool(vd, "directx-use-sysmem");
- p_pic[0].p_sys->p_surface = p_pic[0].p_sys->p_front_surface
- = p_surface;
+ /* Our last choice is to use a plain RGB surface */
+ DDPIXELFORMAT ddpfPixelFormat;
+ ZeroMemory(&ddpfPixelFormat, sizeof(ddpfPixelFormat));
+ ddpfPixelFormat.dwSize = sizeof(ddpfPixelFormat);
- I_OUTPUTPICTURES = 1;
+ IDirectDrawSurface2_GetPixelFormat(sys->display, &ddpfPixelFormat);
+ if ((ddpfPixelFormat.dwFlags & DDPF_RGB) == 0)
+ return VLC_EGENERIC;
- msg_Dbg( p_vout, "created plain surface of chroma:%.4s",
- (char *)&p_vout->output.i_chroma );
- }
+ switch (ddpfPixelFormat.dwRGBBitCount) {
+ case 8:
+ fmt->i_chroma = VLC_CODEC_RGB8;
+ break;
+ case 15:
+ fmt->i_chroma = VLC_CODEC_RGB15;
+ break;
+ case 16:
+ fmt->i_chroma = VLC_CODEC_RGB16;
+ break;
+ case 24:
+ fmt->i_chroma = VLC_CODEC_RGB24;
+ break;
+ case 32:
+ fmt->i_chroma = VLC_CODEC_RGB32;
+ break;
+ default:
+ msg_Err(vd, "unknown screen depth");
+ return VLC_EGENERIC;
}
+ fmt->i_rmask = ddpfPixelFormat.dwRBitMask;
+ fmt->i_gmask = ddpfPixelFormat.dwGBitMask;
+ fmt->i_bmask = ddpfPixelFormat.dwBBitMask;
+ /* */
+ LPDIRECTDRAWSURFACE2 surface;
+ int ret = DirectXCreateSurface(vd, &surface, fmt, 0, false, allow_sysmem, 0);
+ if (ret && !allow_sysmem)
+ ret = DirectXCreateSurface(vd, &surface, fmt, 0, false, true, 0);
+ if (ret)
+ return VLC_EGENERIC;
+ msg_Dbg(vd, "RGB plain surface created successfully");
- /* Now that we've got all our direct-buffers, we can finish filling in the
- * picture_t structures */
- for( i = 0; i < I_OUTPUTPICTURES; i++ )
- {
- p_pic[i].i_status = DESTROYED_PICTURE;
- p_pic[i].i_type = DIRECT_PICTURE;
- p_pic[i].b_slow = true;
- p_pic[i].pf_lock = DirectXLockSurface;
- p_pic[i].pf_unlock = DirectXUnlockSurface;
- PP_OUTPUTPICTURE[i] = &p_pic[i];
-
- if( DirectXLockSurface( p_vout, &p_pic[i] ) != VLC_SUCCESS )
- {
- /* AAARRGG */
- FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
- I_OUTPUTPICTURES = 0;
- msg_Err( p_vout, "cannot lock surface" );
- return VLC_EGENERIC;
- }
- DirectXUnlockSurface( p_vout, &p_pic[i] );
+ if (DirectXCheckLockingSurface(surface, surface)) {
+ DirectXDestroySurface(surface);
+ return VLC_EGENERIC;
}
- msg_Dbg( p_vout, "End NewPictureVec (%s)",
- I_OUTPUTPICTURES ? "succeeded" : "failed" );
-
+ /* */
+ picture_resource_t *rsc = &sys->resource;
+ rsc->p_sys->front_surface = surface;
+ rsc->p_sys->surface = surface;
+ rsc->p_sys->fallback = NULL;
return VLC_SUCCESS;
}
-/*****************************************************************************
- * FreePicture: destroy a picture vector allocated with NewPictureVec
- *****************************************************************************
- *
- *****************************************************************************/
-static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic,
- int i_num_pics )
+static int DirectXCreatePictureResource(vout_display_t *vd,
+ bool *use_overlay,
+ video_format_t *fmt)
{
- int i;
+ vout_display_sys_t *sys = vd->sys;
- vlc_mutex_lock( &p_vout->p_sys->lock );
- p_vout->p_sys->p_current_surface = 0;
- vlc_mutex_unlock( &p_vout->p_sys->lock );
-
- for( i = 0; i < i_num_pics; i++ )
- {
- DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_front_surface );
+ /* */
+ picture_resource_t *rsc = &sys->resource;
+ rsc->p_sys = calloc(1, sizeof(*rsc->p_sys));
+ if (!rsc->p_sys)
+ return VLC_ENOMEM;
- for( i = 0; i < i_num_pics; i++ )
- {
- free( p_pic[i].p_sys );
+ /* */
+ bool allow_hw_yuv = sys->can_blit_fourcc &&
+ vlc_fourcc_IsYUV(fmt->i_chroma) &&
+ var_InheritBool(vd, "directx-hw-yuv");
+ bool allow_overlay = var_InheritBool(vd, "overlay");
+
+ /* Try to use an yuv surface */
+ if (allow_hw_yuv) {
+ const vlc_fourcc_t *list = vlc_fourcc_GetYUVFallback(fmt->i_chroma);
+ /* Try with overlay first */
+ for (unsigned pass = allow_overlay ? 0 : 1; pass < 2; pass++) {
+ for (unsigned i = 0; list[i] != 0; i++) {
+ const DWORD fourcc = DirectXGetFourcc(list[i]);
+ if (!fourcc)
+ continue;
+
+ if (pass == 0) {
+ if (DirectXCreatePictureResourceYuvOverlay(vd, fmt, fourcc))
+ continue;
+ } else {
+ if (DirectXCreatePictureResourceYuv(vd, fmt, fourcc))
+ continue;
+ }
+ /* */
+ *use_overlay = pass == 0;
+ fmt->i_chroma = list[i];
+ return VLC_SUCCESS;
+ }
}
}
-}
-/*****************************************************************************
- * UpdatePictureStruct: updates the internal data in the picture_t structure
- *****************************************************************************
- * This will setup stuff for use by the video_output thread
- *****************************************************************************/
-static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic )
+ /* Try plain RGB */
+ return DirectXCreatePictureResourceRgb(vd, fmt);
+}
+static void DirectXDestroyPictureResource(vout_display_t *vd)
{
- switch( p_vout->output.i_chroma )
- {
- case VLC_CODEC_RGB8:
- case VLC_CODEC_RGB15:
- case VLC_CODEC_RGB16:
- case VLC_CODEC_RGB24:
- case VLC_CODEC_RGB32:
- p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
- p_pic->p->i_lines = p_vout->output.i_height;
- p_pic->p->i_visible_lines = p_vout->output.i_height;
- p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
- switch( p_vout->output.i_chroma )
- {
- case VLC_CODEC_RGB8:
- p_pic->p->i_pixel_pitch = 1;
- break;
- case VLC_CODEC_RGB15:
- case VLC_CODEC_RGB16:
- p_pic->p->i_pixel_pitch = 2;
- break;
- case VLC_CODEC_RGB24:
- p_pic->p->i_pixel_pitch = 3;
- break;
- case VLC_CODEC_RGB32:
- p_pic->p->i_pixel_pitch = 4;
- break;
- default:
- return VLC_EGENERIC;
- }
- p_pic->p->i_visible_pitch = p_vout->output.i_width *
- p_pic->p->i_pixel_pitch;
- p_pic->i_planes = 1;
- break;
-
- case VLC_CODEC_YV12:
-
- /* U and V inverted compared to I420
- * Fixme: this should be handled by the vout core */
- p_vout->output.i_chroma = VLC_CODEC_I420;
-
- p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
- p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
- p_pic->p[Y_PLANE].i_visible_lines = p_vout->output.i_height;
- p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
- p_pic->p[Y_PLANE].i_pixel_pitch = 1;
- p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
- p_pic->p[Y_PLANE].i_pixel_pitch;
-
- p_pic->V_PIXELS = p_pic->Y_PIXELS
- + p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch;
- p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
- p_pic->p[V_PLANE].i_visible_lines = p_vout->output.i_height / 2;
- p_pic->p[V_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
- p_pic->p[V_PLANE].i_pixel_pitch = 1;
- p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
- p_pic->p[V_PLANE].i_pixel_pitch;
-
- p_pic->U_PIXELS = p_pic->V_PIXELS
- + p_pic->p[V_PLANE].i_lines * p_pic->p[V_PLANE].i_pitch;
- p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
- p_pic->p[U_PLANE].i_visible_lines = p_vout->output.i_height / 2;
- p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
- p_pic->p[U_PLANE].i_pixel_pitch = 1;
- p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
- p_pic->p[U_PLANE].i_pixel_pitch;
-
- p_pic->i_planes = 3;
- break;
+ vout_display_sys_t *sys = vd->sys;
- case VLC_CODEC_I420:
-
- p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
- p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
- p_pic->p[Y_PLANE].i_visible_lines = p_vout->output.i_height;
- p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
- p_pic->p[Y_PLANE].i_pixel_pitch = 1;
- p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
- p_pic->p[Y_PLANE].i_pixel_pitch;
-
- p_pic->U_PIXELS = p_pic->Y_PIXELS
- + p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch;
- p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
- p_pic->p[U_PLANE].i_visible_lines = p_vout->output.i_height / 2;
- p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
- p_pic->p[U_PLANE].i_pixel_pitch = 1;
- p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
- p_pic->p[U_PLANE].i_pixel_pitch;
-
- p_pic->V_PIXELS = p_pic->U_PIXELS
- + p_pic->p[U_PLANE].i_lines * p_pic->p[U_PLANE].i_pitch;
- p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
- p_pic->p[V_PLANE].i_visible_lines = p_vout->output.i_height / 2;
- p_pic->p[V_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
- p_pic->p[V_PLANE].i_pixel_pitch = 1;
- p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
- p_pic->p[V_PLANE].i_pixel_pitch;
-
- p_pic->i_planes = 3;
- break;
-
- case VLC_CODEC_UYVY:
- case VLC_CODEC_YUYV:
-
- p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
- p_pic->p->i_lines = p_vout->output.i_height;
- p_pic->p->i_visible_lines = p_vout->output.i_height;
- p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
- p_pic->p->i_pixel_pitch = 2;
- p_pic->p->i_visible_pitch = p_vout->output.i_width *
- p_pic->p->i_pixel_pitch;
-
- p_pic->i_planes = 1;
- break;
+ if (sys->resource.p_sys->front_surface != sys->resource.p_sys->surface)
+ DirectXDestroySurface(sys->resource.p_sys->surface);
+ DirectXDestroySurface(sys->resource.p_sys->front_surface);
+ if (sys->resource.p_sys->fallback)
+ picture_Release(sys->resource.p_sys->fallback);
+}
- default:
- /* Unknown chroma, tell the guy to get lost */
- msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",
- p_vout->output.i_chroma,
- (char*)&p_vout->output.i_chroma );
- return VLC_EGENERIC;
- }
+static int DirectXLock(picture_t *picture)
+{
+ DDSURFACEDESC ddsd;
+ if (DirectXLockSurface(picture->p_sys->front_surface,
+ picture->p_sys->surface, &ddsd))
+ return CommonUpdatePicture(picture, &picture->p_sys->fallback, NULL, 0);
+ CommonUpdatePicture(picture, NULL, ddsd.lpSurface, ddsd.lPitch);
return VLC_SUCCESS;
}
-
-/*****************************************************************************
- * DirectXGetDDrawCaps: Probe the capabilities of the hardware
- *****************************************************************************
- * It is nice to know which features are supported by the hardware so we can
- * find ways to optimize our rendering.
- *****************************************************************************/
-static void DirectXGetDDrawCaps( vout_thread_t *p_vout )
+static void DirectXUnlock(picture_t *picture)
{
- DDCAPS ddcaps;
- HRESULT dxresult;
-
- /* This is just an indication of whether or not we'll support overlay,
- * but with this test we don't know if we support YUV overlay */
- memset( &ddcaps, 0, sizeof( DDCAPS ));
- ddcaps.dwSize = sizeof(DDCAPS);
- dxresult = IDirectDraw2_GetCaps( p_vout->p_sys->p_ddobject,
- &ddcaps, NULL );
- if(dxresult != DD_OK )
- {
- msg_Warn( p_vout, "cannot get caps" );
- }
- else
- {
- bool bHasOverlay, bHasOverlayFourCC, bCanDeinterlace,
- bHasColorKey, bCanStretch, bCanBltFourcc,
- bAlignBoundarySrc, bAlignBoundaryDest,
- bAlignSizeSrc, bAlignSizeDest;
-
- /* Determine if the hardware supports overlay surfaces */
- bHasOverlay = (ddcaps.dwCaps & DDCAPS_OVERLAY) ? 1 : 0;
- /* Determine if the hardware supports overlay surfaces */
- bHasOverlayFourCC = (ddcaps.dwCaps & DDCAPS_OVERLAYFOURCC) ? 1 : 0;
- /* Determine if the hardware supports overlay deinterlacing */
- bCanDeinterlace = (ddcaps.dwCaps & DDCAPS2_CANFLIPODDEVEN) ? 1 : 0;
- /* Determine if the hardware supports colorkeying */
- bHasColorKey = (ddcaps.dwCaps & DDCAPS_COLORKEY) ? 1 : 0;
- /* Determine if the hardware supports scaling of the overlay surface */
- bCanStretch = (ddcaps.dwCaps & DDCAPS_OVERLAYSTRETCH) ? 1 : 0;
- /* Determine if the hardware supports color conversion during a blit */
- bCanBltFourcc = (ddcaps.dwCaps & DDCAPS_BLTFOURCC) ? 1 : 0;
- /* Determine overlay source boundary alignment */
- bAlignBoundarySrc = (ddcaps.dwCaps & DDCAPS_ALIGNBOUNDARYSRC) ? 1 : 0;
- /* Determine overlay destination boundary alignment */
- bAlignBoundaryDest = (ddcaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST) ? 1:0;
- /* Determine overlay destination size alignment */
- bAlignSizeSrc = (ddcaps.dwCaps & DDCAPS_ALIGNSIZESRC) ? 1 : 0;
- /* Determine overlay destination size alignment */
- bAlignSizeDest = (ddcaps.dwCaps & DDCAPS_ALIGNSIZEDEST) ? 1 : 0;
-
- msg_Dbg( p_vout, "DirectDraw Capabilities: overlay=%i yuvoverlay=%i "
- "can_deinterlace_overlay=%i colorkey=%i stretch=%i "
- "bltfourcc=%i",
- bHasOverlay, bHasOverlayFourCC, bCanDeinterlace,
- bHasColorKey, bCanStretch, bCanBltFourcc );
-
- if( bAlignBoundarySrc || bAlignBoundaryDest ||
- bAlignSizeSrc || bAlignSizeDest )
- {
- if( bAlignBoundarySrc ) p_vout->p_sys->i_align_src_boundary =
- ddcaps.dwAlignBoundarySrc;
- if( bAlignBoundaryDest ) p_vout->p_sys->i_align_dest_boundary =
- ddcaps.dwAlignBoundaryDest;
- if( bAlignSizeDest ) p_vout->p_sys->i_align_src_size =
- ddcaps.dwAlignSizeSrc;
- if( bAlignSizeDest ) p_vout->p_sys->i_align_dest_size =
- ddcaps.dwAlignSizeDest;
-
- msg_Dbg( p_vout, "align_boundary_src=%i,%i "
- "align_boundary_dest=%i,%i "
- "align_size_src=%i,%i align_size_dest=%i,%i",
- bAlignBoundarySrc, p_vout->p_sys->i_align_src_boundary,
- bAlignBoundaryDest, p_vout->p_sys->i_align_dest_boundary,
- bAlignSizeSrc, p_vout->p_sys->i_align_src_size,
- bAlignSizeDest, p_vout->p_sys->i_align_dest_size );
- }
-
- /* Don't ask for troubles */
- if( !bCanBltFourcc ) p_vout->p_sys->b_hw_yuv = FALSE;
- }
+ DirectXUnlockSurface(picture->p_sys->front_surface,
+ picture->p_sys->surface);
}
-/*****************************************************************************
- * DirectXLockSurface: Lock surface and get picture data pointer
- *****************************************************************************
- * This function locks a surface and get the surface descriptor which amongst
- * other things has the pointer to the picture data.
- *****************************************************************************/
-static int DirectXLockSurface( vout_thread_t *p_vout, picture_t *p_pic )
+static int DirectXCreatePool(vout_display_t *vd,
+ bool *use_overlay, video_format_t *fmt)
{
- HRESULT dxresult;
-
- /* Lock the surface to get a valid pointer to the picture buffer */
- memset( &p_pic->p_sys->ddsd, 0, sizeof( DDSURFACEDESC ));
- p_pic->p_sys->ddsd.dwSize = sizeof(DDSURFACEDESC);
- dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface,
- NULL, &p_pic->p_sys->ddsd,
- DDLOCK_NOSYSLOCK | DDLOCK_WAIT,
- NULL );
- if( dxresult != DD_OK )
- {
- if( dxresult == DDERR_INVALIDPARAMS )
- {
- /* DirectX 3 doesn't support the DDLOCK_NOSYSLOCK flag, resulting
- * in an invalid params error */
- dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface, NULL,
- &p_pic->p_sys->ddsd,
- DDLOCK_WAIT, NULL);
- }
- if( dxresult == DDERR_SURFACELOST )
- {
- /* Your surface can be lost so be sure
- * to check this and restore it if needed */
+ vout_display_sys_t *sys = vd->sys;
- /* When using overlays with back-buffers, we need to restore
- * the front buffer so the back-buffers get restored as well. */
- if( p_vout->p_sys->b_using_overlay )
- IDirectDrawSurface2_Restore( p_pic->p_sys->p_front_surface );
- else
- IDirectDrawSurface2_Restore( p_pic->p_sys->p_surface );
-
- dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface, NULL,
- &p_pic->p_sys->ddsd,
- DDLOCK_WAIT, NULL);
-#ifndef NDEBUG
- if( dxresult == DDERR_SURFACELOST )
- msg_Dbg( p_vout, "DirectXLockSurface: DDERR_SURFACELOST" );
-#endif
- }
- if( dxresult != DD_OK )
- {
- return VLC_EGENERIC;
- }
- }
+ /* */
+ *fmt = vd->source;
- /* Now we have a pointer to the surface memory, we can update our picture
- * structure. */
- if( UpdatePictureStruct( p_vout, p_pic )
- != VLC_SUCCESS )
- {
- DirectXUnlockSurface( p_vout, p_pic );
+ if (DirectXCreatePictureResource(vd, use_overlay, fmt))
return VLC_EGENERIC;
+
+ /* Create the associated picture */
+ picture_resource_t *rsc = &sys->resource;
+ 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 = 0;
+ }
+ picture_t *picture = picture_NewFromResource(fmt, rsc);
+ if (!picture) {
+ DirectXDestroyPictureResource(vd);
+ free(rsc->p_sys);
+ return VLC_ENOMEM;
}
- else
- return VLC_SUCCESS;
-}
-/*****************************************************************************
- * DirectXUnlockSurface: Unlock a surface locked by DirectXLockSurface().
- *****************************************************************************/
-static int DirectXUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )
+ /* Wrap it into a picture pool */
+ picture_pool_configuration_t cfg;
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.picture_count = 1;
+ cfg.picture = &picture;
+ cfg.lock = DirectXLock;
+ cfg.unlock = DirectXUnlock;
+
+ sys->pool = picture_pool_NewExtended(&cfg);
+ if (!sys->pool) {
+ picture_Release(picture);
+ DirectXDestroyPictureResource(vd);
+ return VLC_ENOMEM;
+ }
+ return VLC_SUCCESS;
+}
+static void DirectXDestroyPool(vout_display_t *vd)
{
- VLC_UNUSED( p_vout );
+ vout_display_sys_t *sys = vd->sys;
- /* Unlock the Surface */
- if( IDirectDrawSurface2_Unlock( p_pic->p_sys->p_surface, NULL ) == DD_OK )
- return VLC_SUCCESS;
- else
- return VLC_EGENERIC;
+ if (sys->pool) {
+ DirectXDestroyPictureResource(vd);
+ picture_pool_Delete(sys->pool);
+ }
+ sys->pool = NULL;
}
-/*****************************************************************************
- * DirectXFindColorkey: Finds out the 32bits RGB pixel value of the colorkey
- *****************************************************************************/
-static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *pi_color )
+/**
+ * Move or resize overlay surface on video display.
+ *
+ * This function is used to move or resize an overlay surface on the screen.
+ * Ususally the overlay is moved by the user and thus, by a move or resize
+ * event.
+ */
+static int DirectXUpdateOverlay(vout_display_t *vd, LPDIRECTDRAWSURFACE2 surface)
{
- DDSURFACEDESC ddsd;
- HRESULT dxresult;
- COLORREF i_rgb = 0;
- uint32_t i_pixel_backup;
- HDC hdc;
+ vout_display_sys_t *sys = vd->sys;
- ddsd.dwSize = sizeof(ddsd);
- dxresult = IDirectDrawSurface2_Lock( p_vout->p_sys->p_display, NULL,
- &ddsd, DDLOCK_WAIT, NULL );
- if( dxresult != DD_OK ) return 0;
+ RECT src = sys->rect_src_clipped;
+ RECT dst = sys->rect_dest_clipped;
- i_pixel_backup = *(uint32_t *)ddsd.lpSurface;
+ if (sys->use_wallpaper) {
+ src.left = vd->source.i_x_offset;
+ src.top = vd->source.i_y_offset;
+ src.right = vd->source.i_x_offset + vd->source.i_visible_width;
+ src.bottom = vd->source.i_y_offset + vd->source.i_visible_height;
+ AlignRect(&src, sys->i_align_src_boundary, sys->i_align_src_size);
- switch( ddsd.ddpfPixelFormat.dwRGBBitCount )
- {
- case 4:
- *(uint8_t *)ddsd.lpSurface = *pi_color | (*pi_color << 4);
- break;
- case 8:
- *(uint8_t *)ddsd.lpSurface = *pi_color;
- break;
- case 15:
- case 16:
- *(uint16_t *)ddsd.lpSurface = *pi_color;
- break;
- case 24:
- /* Seems to be problematic so we'll just put black as the colorkey */
- *pi_color = 0;
- default:
- *(uint32_t *)ddsd.lpSurface = *pi_color;
- break;
- }
+ vout_display_cfg_t cfg = *vd->cfg;
+ cfg.display.width = sys->rect_display.right;
+ cfg.display.height = sys->rect_display.bottom;
- IDirectDrawSurface2_Unlock( p_vout->p_sys->p_display, NULL );
+ vout_display_place_t place;
+ vout_display_PlacePicture(&place, &vd->source, &cfg, true);
- if( IDirectDrawSurface2_GetDC( p_vout->p_sys->p_display, &hdc ) == DD_OK )
- {
- i_rgb = GetPixel( hdc, 0, 0 );
- IDirectDrawSurface2_ReleaseDC( p_vout->p_sys->p_display, hdc );
+ dst.left = sys->rect_display.left + place.x;
+ dst.top = sys->rect_display.top + place.y;
+ dst.right = dst.left + place.width;
+ dst.bottom = dst.top + place.height;
+ AlignRect(&dst, sys->i_align_dest_boundary, sys->i_align_dest_size);
}
- ddsd.dwSize = sizeof(ddsd);
- dxresult = IDirectDrawSurface2_Lock( p_vout->p_sys->p_display, NULL,
- &ddsd, DDLOCK_WAIT, NULL );
- if( dxresult != DD_OK ) return i_rgb;
-
- *(uint32_t *)ddsd.lpSurface = i_pixel_backup;
+ if (!surface) {
+ if (!sys->pool)
+ return VLC_EGENERIC;
+ surface = sys->resource.p_sys->front_surface;
+ }
- IDirectDrawSurface2_Unlock( p_vout->p_sys->p_display, NULL );
+ /* The new window dimensions should already have been computed by the
+ * caller of this function */
- return i_rgb;
+ /* Position and show the overlay */
+ DDOVERLAYFX ddofx;
+ ZeroMemory(&ddofx, sizeof(ddofx));
+ ddofx.dwSize = sizeof(ddofx);
+ ddofx.dckDestColorkey.dwColorSpaceLowValue = sys->i_colorkey;
+ ddofx.dckDestColorkey.dwColorSpaceHighValue = sys->i_colorkey;
+
+ HRESULT hr = IDirectDrawSurface2_UpdateOverlay(surface,
+ &src, sys->display, &dst,
+ DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE, &ddofx);
+ sys->restore_overlay = hr != DD_OK;
+
+ if (hr != DD_OK) {
+ msg_Warn(vd, "DirectDrawUpdateOverlay cannot move/resize overlay");
+ return VLC_EGENERIC;
+ }
+ return VLC_SUCCESS;
}
-/*****************************************************************************
- * A few toolbox functions
- *****************************************************************************/
-void SwitchWallpaperMode( vout_thread_t *p_vout, bool b_on )
+/* */
+static void WallpaperChange(vout_display_t *vd, bool use_wallpaper)
{
- HWND hwnd;
+ vout_display_sys_t *sys = vd->sys;
- if( p_vout->p_sys->b_wallpaper == b_on ) return; /* Nothing to do */
+ if (!sys->use_wallpaper == !use_wallpaper)
+ return;
- hwnd = FindWindow( _T("Progman"), NULL );
- if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SHELLDLL_DefView"), NULL );
- if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SysListView32"), NULL );
- if( !hwnd )
- {
- msg_Warn( p_vout, "couldn't find \"SysListView32\" window, "
- "wallpaper mode not supported" );
+ HWND hwnd = FindWindow(_T("Progman"), NULL);
+ if (hwnd)
+ hwnd = FindWindowEx(hwnd, NULL, _T("SHELLDLL_DefView"), NULL);
+ if (hwnd)
+ hwnd = FindWindowEx(hwnd, NULL, _T("SysListView32"), NULL);
+ if (!hwnd) {
+ msg_Warn(vd, "couldn't find \"SysListView32\" window, "
+ "wallpaper mode not supported");
return;
}
- p_vout->p_sys->b_wallpaper = b_on;
-
- msg_Dbg( p_vout, "wallpaper mode %s", b_on ? "enabled" : "disabled" );
+ msg_Dbg(vd, "wallpaper mode %s", use_wallpaper ? "enabled" : "disabled");
+ sys->use_wallpaper = use_wallpaper;
- if( p_vout->p_sys->b_wallpaper )
- {
- p_vout->p_sys->color_bkg = ListView_GetBkColor( hwnd );
- p_vout->p_sys->color_bkgtxt = ListView_GetTextBkColor( hwnd );
+ if (sys->use_wallpaper) {
+ sys->color_bkg = ListView_GetBkColor(hwnd);
+ sys->color_bkgtxt = ListView_GetTextBkColor(hwnd);
- ListView_SetBkColor( hwnd, p_vout->p_sys->i_rgb_colorkey );
- ListView_SetTextBkColor( hwnd, p_vout->p_sys->i_rgb_colorkey );
- }
- else if( hwnd )
- {
- ListView_SetBkColor( hwnd, p_vout->p_sys->color_bkg );
- ListView_SetTextBkColor( hwnd, p_vout->p_sys->color_bkgtxt );
+ ListView_SetBkColor(hwnd, sys->i_rgb_colorkey);
+ ListView_SetTextBkColor(hwnd, sys->i_rgb_colorkey);
+ } else {
+ ListView_SetBkColor(hwnd, sys->color_bkg);
+ ListView_SetTextBkColor(hwnd, sys->color_bkgtxt);
}
/* Update desktop */
- InvalidateRect( hwnd, NULL, TRUE );
- UpdateWindow( hwnd );
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+
+ if (sys->use_overlay)
+ DirectXUpdateOverlay(vd, NULL);
+}
+
+/* */
+static int WallpaperCallback(vlc_object_t *object, char const *cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *data)
+{
+ vout_display_t *vd = (vout_display_t *)object;
+ vout_display_sys_t *sys = vd->sys;
+ VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
+
+ vlc_mutex_lock(&sys->lock);
+ const bool ch_wallpaper = !sys->wallpaper_requested != !newval.b_bool;
+ sys->ch_wallpaper |= ch_wallpaper;
+ sys->wallpaper_requested = newval.b_bool;
+ vlc_mutex_unlock(&sys->lock);
+
+ /* FIXME we should have a way to export variable to be saved */
+ if (ch_wallpaper) {
+ playlist_t *p_playlist = pl_Get(vd);
+ /* Modify playlist as well because the vout might have to be
+ * restarted */
+ var_Create(p_playlist, "video-wallpaper", VLC_VAR_BOOL);
+ var_SetBool(p_playlist, "video-wallpaper", newval.b_bool);
+ }
+ return VLC_SUCCESS;
}
/*****************************************************************************
* config variable callback
*****************************************************************************/
-BOOL WINAPI DirectXEnumCallback2( GUID* p_guid, LPTSTR psz_desc,
- LPTSTR psz_drivername, VOID* p_context,
- HMONITOR hmon )
+static BOOL WINAPI DirectXEnumCallback2(GUID *guid, LPTSTR desc,
+ LPTSTR drivername, VOID *context,
+ HMONITOR hmon)
{
- VLC_UNUSED( p_guid ); VLC_UNUSED( psz_desc ); VLC_UNUSED( hmon );
+ VLC_UNUSED(guid); VLC_UNUSED(desc); VLC_UNUSED(hmon);
- module_config_t *p_item = (module_config_t *)p_context;
+ module_config_t *item = context;
- p_item->ppsz_list =
- (char **)realloc( p_item->ppsz_list,
- (p_item->i_list+2) * sizeof(char *) );
- p_item->ppsz_list_text =
- (char **)realloc( p_item->ppsz_list_text,
- (p_item->i_list+2) * sizeof(char *) );
+ item->ppsz_list = xrealloc(item->ppsz_list,
+ (item->i_list+2) * sizeof(char *));
+ item->ppsz_list_text = xrealloc(item->ppsz_list_text,
+ (item->i_list+2) * sizeof(char *));
- p_item->ppsz_list[p_item->i_list] = strdup( psz_drivername );
- p_item->ppsz_list_text[p_item->i_list] = NULL;
- p_item->i_list++;
- p_item->ppsz_list[p_item->i_list] = NULL;
- p_item->ppsz_list_text[p_item->i_list] = NULL;
+ item->ppsz_list[item->i_list] = strdup(drivername);
+ item->ppsz_list_text[item->i_list] = NULL;
+ item->i_list++;
+ item->ppsz_list[item->i_list] = NULL;
+ item->ppsz_list_text[item->i_list] = NULL;
return TRUE; /* Keep enumerating */
}
-static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
- vlc_value_t newval, vlc_value_t oldval, void *d)
+static int FindDevicesCallback(vlc_object_t *object, char const *name,
+ vlc_value_t newval, vlc_value_t oldval, void *data)
{
- VLC_UNUSED( newval ); VLC_UNUSED( oldval ); VLC_UNUSED( d );
+ VLC_UNUSED(newval); VLC_UNUSED(oldval); VLC_UNUSED(data);
- HRESULT (WINAPI *OurDirectDrawEnumerateEx)( LPDDENUMCALLBACKEXA, LPVOID,
- DWORD );
- HINSTANCE hddraw_dll;
-
- module_config_t *p_item;
- int i;
-
- p_item = config_FindConfig( p_this, psz_name );
- if( !p_item ) return VLC_SUCCESS;
+ module_config_t *item = config_FindConfig(object, name);
+ if (!item)
+ return VLC_SUCCESS;
/* Clear-up the current list */
- if( p_item->i_list )
- {
+ if (item->i_list > 0) {
+ int i;
/* Keep the first entry */
- for( i = 1; i < p_item->i_list; i++ )
- {
- free( p_item->ppsz_list[i] );
- free( p_item->ppsz_list_text[i] );
+ for (i = 1; i < item->i_list; i++) {
+ free(item->ppsz_list[i]);
+ free(item->ppsz_list_text[i]);
}
/* TODO: Remove when no more needed */
- p_item->ppsz_list[i] = NULL;
- p_item->ppsz_list_text[i] = NULL;
+ item->ppsz_list[i] = NULL;
+ item->ppsz_list_text[i] = NULL;
}
- p_item->i_list = 1;
+ item->i_list = 1;
/* Load direct draw DLL */
- hddraw_dll = LoadLibrary(_T("DDRAW.DLL"));
- if( hddraw_dll == NULL ) return VLC_SUCCESS;
-
- OurDirectDrawEnumerateEx =
-#ifndef UNICODE
- (void *)GetProcAddress( hddraw_dll, "DirectDrawEnumerateExA" );
-#else
- (void *)GetProcAddress( hddraw_dll, _T("DirectDrawEnumerateExW") );
-#endif
+ HINSTANCE hddraw_dll = LoadLibrary(_T("DDRAW.DLL"));
+ if (!hddraw_dll)
+ return VLC_SUCCESS;
- if( OurDirectDrawEnumerateEx )
- {
- /* Enumerate displays */
- OurDirectDrawEnumerateEx( DirectXEnumCallback2, p_item,
- DDENUM_ATTACHEDSECONDARYDEVICES );
- }
+ /* Enumerate displays */
+ HRESULT (WINAPI *OurDirectDrawEnumerateEx)(LPDDENUMCALLBACKEXA,
+ LPVOID, DWORD) =
+ (void *)GetProcAddress(hddraw_dll, _T("DirectDrawEnumerateExA"));
+ if (OurDirectDrawEnumerateEx)
+ OurDirectDrawEnumerateEx(DirectXEnumCallback2, item,
+ DDENUM_ATTACHEDSECONDARYDEVICES);
- FreeLibrary( hddraw_dll );
+ FreeLibrary(hddraw_dll);
/* Signal change to the interface */
- p_item->b_dirty = true;
+ item->b_dirty = true;
return VLC_SUCCESS;
}
-static int WallpaperCallback( vlc_object_t *p_this, char const *psz_cmd,
- vlc_value_t oldval, vlc_value_t newval,
- void *p_data )
-{
- VLC_UNUSED( psz_cmd ); VLC_UNUSED( oldval ); VLC_UNUSED( p_data );
- vout_thread_t *p_vout = (vout_thread_t *)p_this;
-
- if( (newval.b_bool && !p_vout->p_sys->b_wallpaper) ||
- (!newval.b_bool && p_vout->p_sys->b_wallpaper) )
- {
- playlist_t *p_playlist = pl_Hold( p_vout );
-
- if( p_playlist )
- {
- /* Modify playlist as well because the vout might have to be
- * restarted */
- var_Create( p_playlist, "directx-wallpaper", VLC_VAR_BOOL );
- var_Set( p_playlist, "directx-wallpaper", newval );
- pl_Release( p_vout );
- }
-
- p_vout->p_sys->i_changes |= DX_WALLPAPER_CHANGE;
- }
-
- return VLC_SUCCESS;
-}
-/*****************************************************************************
- * SetPalette: sets an 8 bpp palette
- *****************************************************************************/
-static void SetPalette( vout_thread_t *p_vout,
- uint16_t *red, uint16_t *green, uint16_t *blue )
-{
- VLC_UNUSED( red ); VLC_UNUSED( green );VLC_UNUSED( blue );
- msg_Err( p_vout, "FIXME: SetPalette unimplemented" );
-}