/*****************************************************************************
* direct3d.c: Windows Direct3D video output module
*****************************************************************************
- * Copyright (C) 2006 the VideoLAN team
+ * Copyright (C) 2006-2009 the VideoLAN team
*$Id$
*
* Authors: Damien Fouilleul <damienf@videolan.org>
# include "config.h"
#endif
-#include <vlc/vlc.h>
+#include <vlc_common.h>
+#include <vlc_plugin.h>
#include <vlc_interface.h>
#include <vlc_playlist.h>
#include <vlc_vout.h>
* Module descriptor
*****************************************************************************/
-static bool _got_vista_or_above;
-
-static int get_capability_for_osversion(void)
+static bool IsVistaOrAbove(void)
{
OSVERSIONINFO winVer;
winVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if( winVer.dwMajorVersion > 5 )
{
/* Windows Vista or above, make this module the default */
- _got_vista_or_above = true;
- return 150;
+ return true;
}
}
/* Windows XP or lower, make sure this module isn't the default */
- _got_vista_or_above = false;
- return 50;
+ return false;
+}
+
+static int OpenVideoXP( vlc_object_t *obj )
+{
+ return IsVistaOrAbove() ? VLC_EGENERIC : OpenVideo( obj );
}
-vlc_module_begin();
- set_shortname( "Direct3D" );
- set_category( CAT_VIDEO );
- set_subcategory( SUBCAT_VIDEO_VOUT );
- set_description( _("DirectX 3D video output") );
- set_capability( "video output", get_capability_for_osversion() );
- add_shortcut( "direct3d" );
- set_callbacks( OpenVideo, CloseVideo );
+static int OpenVideoVista( vlc_object_t *obj )
+{
+ return IsVistaOrAbove() ? OpenVideo( obj ) : VLC_EGENERIC;
+}
+
+vlc_module_begin ()
+ set_shortname( "Direct3D" )
+ set_category( CAT_VIDEO )
+ set_subcategory( SUBCAT_VIDEO_VOUT )
+ set_description( N_("DirectX 3D video output") )
+ set_capability( "video output", 50 )
+ add_shortcut( "direct3d" )
+ set_callbacks( OpenVideoXP, CloseVideo )
/* FIXME: Hack to avoid unregistering our window class */
- linked_with_a_crap_library_which_uses_atexit( );
-vlc_module_end();
+ linked_with_a_crap_library_which_uses_atexit ()
+
+ add_submodule()
+ set_capability( "video output", 150 )
+ add_shortcut( "direct3d" )
+ set_callbacks( OpenVideoVista, CloseVideo )
+vlc_module_end ()
#if 0 /* FIXME */
/* check if we registered a window class because we need to
static int OpenVideo( vlc_object_t *p_this )
{
vout_thread_t * p_vout = (vout_thread_t *)p_this;
- vlc_value_t val;
/* Allocate structure */
- p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ p_vout->p_sys = calloc( 1, sizeof( vout_sys_t ) );
if( p_vout->p_sys == NULL )
- {
- msg_Err( p_vout, "out of memory" );
return VLC_ENOMEM;
- }
- memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
if( VLC_SUCCESS != Direct3DVoutCreate( p_vout ) )
{
msg_Err( p_vout, "Direct3D could not be initialized !");
- goto error;
+ Direct3DVoutRelease( p_vout );
+ free( p_vout->p_sys );
+ return VLC_EGENERIC;
}
/* Initialisations */
p_vout->p_sys->p_event =
vlc_object_create( p_vout, sizeof(event_thread_t) );
p_vout->p_sys->p_event->p_vout = p_vout;
+ p_vout->p_sys->p_event->window_ready = CreateEvent( NULL, TRUE, FALSE, NULL );
if( vlc_thread_create( p_vout->p_sys->p_event, "Vout Events Thread",
- E_(EventThread), 0, 1 ) )
+ EventThread, 0 ) )
{
msg_Err( p_vout, "cannot create Vout EventThread" );
+ CloseHandle( p_vout->p_sys->p_event->window_ready );
vlc_object_release( p_vout->p_sys->p_event );
p_vout->p_sys->p_event = NULL;
goto error;
}
+ WaitForSingleObject( p_vout->p_sys->p_event->window_ready, INFINITE );
+ CloseHandle( p_vout->p_sys->p_event->window_ready );
if( p_vout->p_sys->p_event->b_error )
{
/* Variable to indicate if the window should be on top of others */
/* Trigger a callback right now */
- var_Get( p_vout, "video-on-top", &val );
- var_Set( p_vout, "video-on-top", val );
+ var_TriggerCallback( p_vout, "video-on-top" );
/* disable screensaver by temporarily changing system settings */
p_vout->p_sys->i_spi_lowpowertimeout = 0;
p_vout->p_sys->i_spi_powerofftimeout = 0;
p_vout->p_sys->i_spi_screensavetimeout = 0;
- var_Get( p_vout, "disable-screensaver", &val);
- if( val.b_bool ) {
+ if( var_GetBool( p_vout, "disable-screensaver" ) ) {
msg_Dbg(p_vout, "disabling screen saver");
SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT,
0, &(p_vout->p_sys->i_spi_lowpowertimeout), 0);
}
return VLC_SUCCESS;
- error:
+error:
CloseVideo( VLC_OBJECT(p_vout) );
return VLC_EGENERIC;
}
Direct3DVoutRelease( p_vout );
+ if( p_vout->b_fullscreen )
+ {
+ msg_Dbg( p_vout, "Quitting fullscreen" );
+ Win32ToggleFullscreen( p_vout );
+ /* Force fullscreen in the core for the next video */
+ var_SetBool( p_vout, "fullscreen", true );
+ }
+
if( p_vout->p_sys->p_event )
{
vlc_object_detach( p_vout->p_sys->p_event );
p_vout->p_sys->i_spi_screensavetimeout, NULL, 0);
}
- if( p_vout->p_sys )
- {
- free( p_vout->p_sys );
- p_vout->p_sys = NULL;
- }
+ free( p_vout->p_sys );
+ p_vout->p_sys = NULL;
}
/*****************************************************************************
static int Init( vout_thread_t *p_vout )
{
int i_ret;
- vlc_value_t val;
- var_Get( p_vout, "directx-hw-yuv", &val );
- p_vout->p_sys->b_hw_yuv = val.b_bool;
+ p_vout->p_sys->b_hw_yuv = var_GetBool( p_vout, "directx-hw-yuv" );
/* Initialise Direct3D */
if( VLC_SUCCESS != Direct3DVoutOpen( p_vout ) )
p_vout->output.i_height = p_vout->render.i_height;
p_vout->output.i_aspect = p_vout->render.i_aspect;
p_vout->fmt_out = p_vout->fmt_in;
- E_(UpdateRects)( p_vout, true );
+ UpdateRects( p_vout, true );
/* create picture pool */
p_vout->output.i_chroma = 0;
p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
}
+ /* autoscale toggle */
+ if( p_vout->i_changes & VOUT_SCALE_CHANGE )
+ {
+ p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
+
+ p_vout->b_autoscale = var_GetBool( p_vout, "autoscale" );
+ p_vout->i_zoom = (int) ZOOM_FP_FACTOR;
+
+ UpdateRects( p_vout, true );
+ }
+
+ /* scaling factor */
+ if( p_vout->i_changes & VOUT_ZOOM_CHANGE )
+ {
+ p_vout->i_changes &= ~VOUT_ZOOM_CHANGE;
+
+ p_vout->b_autoscale = false;
+ p_vout->i_zoom =
+ (int)( ZOOM_FP_FACTOR * var_GetFloat( p_vout, "scale" ) );
+ UpdateRects( p_vout, true );
+ }
+
/* Check for cropping / aspect changes */
if( p_vout->i_changes & VOUT_CROP_CHANGE ||
p_vout->i_changes & VOUT_ASPECT_CHANGE )
p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;
p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;
p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
- E_(UpdateRects)( p_vout, true );
+ UpdateRects( p_vout, true );
}
/* We used to call the Win32 PeekMessage function here to read the window
}
/* Check if the event thread is still running */
- if( p_vout->p_sys->p_event->b_die )
+ if( !vlc_object_alive (p_vout->p_sys->p_event) )
{
return VLC_EGENERIC; /* exit */
}
IDirect3DDevice9_Release(p_vout->p_sys->p_d3ddev);
p_vout->p_sys->p_d3ddev = NULL;
}
-
+
p_vout->p_sys->hmonitor = NULL;
}
/* it sounds like vista does not support YUV surfaces at all */
switch( i_chroma )
{
- case VLC_FOURCC('U','Y','V','Y'):
- case VLC_FOURCC('U','Y','N','V'):
- case VLC_FOURCC('Y','4','2','2'):
+ case VLC_CODEC_UYVY:
{
static const D3DFORMAT formats[] =
{ D3DFMT_UYVY, D3DFMT_YUY2, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };
return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
}
- case VLC_FOURCC('I','4','2','0'):
- case VLC_FOURCC('I','4','2','2'):
- case VLC_FOURCC('Y','V','1','2'):
+ case VLC_CODEC_I420:
+ case VLC_CODEC_I422:
+ case VLC_CODEC_YV12:
{
/* typically 3D textures don't support planar format
** fallback to packed version and use CPU for the conversion
{ D3DFMT_YUY2, D3DFMT_UYVY, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };
return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
}
- case VLC_FOURCC('Y','U','Y','2'):
- case VLC_FOURCC('Y','U','N','V'):
+ case VLC_CODEC_YUYV:
{
static const D3DFORMAT formats[] =
{ D3DFMT_YUY2, D3DFMT_UYVY, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 };
switch( i_chroma )
{
- case VLC_FOURCC('R', 'V', '1', '5'):
+ case VLC_CODEC_RGB15:
{
static const D3DFORMAT formats[] =
{ D3DFMT_X1R5G5B5 };
return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
}
- case VLC_FOURCC('R', 'V', '1', '6'):
+ case VLC_CODEC_RGB16:
{
static const D3DFORMAT formats[] =
{ D3DFMT_R5G6B5 };
return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
}
- case VLC_FOURCC('R', 'V', '2', '4'):
+ case VLC_CODEC_RGB24:
{
static const D3DFORMAT formats[] =
{ D3DFMT_R8G8B8, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8 };
return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT));
}
- case VLC_FOURCC('R', 'V', '3', '2'):
+ case VLC_CODEC_RGB32:
{
static const D3DFORMAT formats[] =
{ D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 };
switch( format )
{
case D3DFMT_YUY2:
- p_vout->output.i_chroma = VLC_FOURCC('Y', 'U', 'Y', '2');
+ p_vout->output.i_chroma = VLC_CODEC_YUYV;
break;
case D3DFMT_UYVY:
- p_vout->output.i_chroma = VLC_FOURCC('U', 'Y', 'V', 'Y');
+ p_vout->output.i_chroma = VLC_CODEC_UYVY;
break;
case D3DFMT_R8G8B8:
- p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '2', '4');
+ p_vout->output.i_chroma = VLC_CODEC_RGB24;
p_vout->output.i_rmask = 0xff0000;
p_vout->output.i_gmask = 0x00ff00;
p_vout->output.i_bmask = 0x0000ff;
break;
case D3DFMT_X8R8G8B8:
case D3DFMT_A8R8G8B8:
- p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '3', '2');
+ p_vout->output.i_chroma = VLC_CODEC_RGB32;
p_vout->output.i_rmask = 0x00ff0000;
p_vout->output.i_gmask = 0x0000ff00;
p_vout->output.i_bmask = 0x000000ff;
break;
case D3DFMT_R5G6B5:
- p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '1', '6');
+ p_vout->output.i_chroma = VLC_CODEC_RGB16;
p_vout->output.i_rmask = (0x1fL)<<11;
p_vout->output.i_gmask = (0x3fL)<<5;
p_vout->output.i_bmask = (0x1fL)<<0;
break;
case D3DFMT_X1R5G5B5:
- p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '1', '5');
+ p_vout->output.i_chroma = VLC_CODEC_RGB15;
p_vout->output.i_rmask = (0x1fL)<<10;
p_vout->output.i_gmask = (0x1fL)<<5;
p_vout->output.i_bmask = (0x1fL)<<0;
/* fill surface with black color */
IDirect3DDevice9_ColorFill(p_d3ddev, p_d3dsurf, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0) );
-
+
/* assign surface to internal structure */
p_pic->p_sys = (void *)p_d3dsurf;
* picture_t structures */
switch( p_vout->output.i_chroma )
{
- case VLC_FOURCC('R','G','B','2'):
+ case VLC_CODEC_RGB8:
p_pic->p->i_lines = p_vout->output.i_height;
p_pic->p->i_visible_lines = p_vout->output.i_height;
p_pic->p->i_pixel_pitch = 1;
p_pic->p->i_pixel_pitch;
p_pic->i_planes = 1;
break;
- case VLC_FOURCC('R','V','1','5'):
- case VLC_FOURCC('R','V','1','6'):
+ case VLC_CODEC_RGB15:
+ case VLC_CODEC_RGB16:
p_pic->p->i_lines = p_vout->output.i_height;
p_pic->p->i_visible_lines = p_vout->output.i_height;
p_pic->p->i_pixel_pitch = 2;
p_pic->p->i_pixel_pitch;
p_pic->i_planes = 1;
break;
- case VLC_FOURCC('R','V','2','4'):
+ case VLC_CODEC_RGB24:
p_pic->p->i_lines = p_vout->output.i_height;
p_pic->p->i_visible_lines = p_vout->output.i_height;
p_pic->p->i_pixel_pitch = 3;
p_pic->p->i_pixel_pitch;
p_pic->i_planes = 1;
break;
- case VLC_FOURCC('R','V','3','2'):
+ case VLC_CODEC_RGB32:
p_pic->p->i_lines = p_vout->output.i_height;
p_pic->p->i_visible_lines = p_vout->output.i_height;
p_pic->p->i_pixel_pitch = 4;
p_pic->p->i_pixel_pitch;
p_pic->i_planes = 1;
break;
- case VLC_FOURCC('U','Y','V','Y'):
- case VLC_FOURCC('Y','U','Y','2'):
+ case VLC_CODEC_UYVY:
+ case VLC_CODEC_YUYV:
p_pic->p->i_lines = p_vout->output.i_height;
p_pic->p->i_visible_lines = p_vout->output.i_height;
p_pic->p->i_pixel_pitch = 2;
f_width = (float)(p_vout->output.i_width);
f_height = (float)(p_vout->output.i_height);
- p_vertices[0].x = 0.0f; // left
- p_vertices[0].y = 0.0f; // top
+ /* -0.5f is a "feature" of DirectX and it seems to apply to Direct3d also */
+ /* http://www.sjbrown.co.uk/2003/05/01/fix-directx-rasterisation/ */
+ p_vertices[0].x = -0.5f; // left
+ p_vertices[0].y = -0.5f; // top
p_vertices[0].z = 0.0f;
p_vertices[0].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
p_vertices[0].rhw = 1.0f;
p_vertices[0].tu = 0.0f;
p_vertices[0].tv = 0.0f;
-
- p_vertices[1].x = f_width; // right
- p_vertices[1].y = 0.0f; // top
+
+ p_vertices[1].x = f_width - 0.5f; // right
+ p_vertices[1].y = -0.5f; // top
p_vertices[1].z = 0.0f;
p_vertices[1].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
p_vertices[1].rhw = 1.0f;
p_vertices[1].tu = 1.0f;
p_vertices[1].tv = 0.0f;
-
- p_vertices[2].x = f_width; // right
- p_vertices[2].y = f_height; // bottom
+
+ p_vertices[2].x = f_width - 0.5f; // right
+ p_vertices[2].y = f_height - 0.5f; // bottom
p_vertices[2].z = 0.0f;
p_vertices[2].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
p_vertices[2].rhw = 1.0f;
p_vertices[2].tu = 1.0f;
p_vertices[2].tv = 1.0f;
-
- p_vertices[3].x = 0.0f; // left
- p_vertices[3].y = f_height; // bottom
+
+ p_vertices[3].x = -0.5f; // left
+ p_vertices[3].y = f_height - 0.5f; // bottom
p_vertices[3].z = 0.0f;
p_vertices[3].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
p_vertices[3].rhw = 1.0f;
p_vertices[3].tu = 0.0f;
p_vertices[3].tv = 1.0f;
-
+
hr= IDirect3DVertexBuffer9_Unlock(p_d3dvtc);
if( FAILED(hr) )
{
IDirect3DDevice9_EndScene(p_d3ddev);
return;
}
-
- // we use FVF instead of vertex shader
- hr = IDirect3DDevice9_SetVertexShader(p_d3ddev, NULL);
- if( FAILED(hr) )
- {
- msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
- IDirect3DDevice9_EndScene(p_d3ddev);
- return;
- }
+ // we use FVF instead of vertex shader
hr = IDirect3DDevice9_SetFVF(p_d3ddev, D3DFVF_CUSTOMVERTEX);
if( FAILED(hr) )
{