X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fmsw%2Fdirect3d.c;h=4503e27165146c8c799d6fbdc9aa5291d39dbf39;hb=fd7f8f854a13f7b65cb2b8622755aa47ee932919;hp=6a9aa6a14b07e0d2906f1a9ed1e433d90c7edf5a;hpb=630076053112b47b2f6279b1e67a4031d2ca45b2;p=vlc diff --git a/modules/video_output/msw/direct3d.c b/modules/video_output/msw/direct3d.c index 6a9aa6a14b..4503e27165 100644 --- a/modules/video_output/msw/direct3d.c +++ b/modules/video_output/msw/direct3d.c @@ -1,7 +1,7 @@ /***************************************************************************** * direct3d.c: Windows Direct3D video output module ***************************************************************************** - * Copyright (C) 2006 the VideoLAN team + * Copyright (C) 2006-2009 the VideoLAN team *$Id$ * * Authors: Damien Fouilleul @@ -39,7 +39,7 @@ # include "config.h" #endif -#include +#include #include #include #include @@ -84,9 +84,7 @@ static void Direct3DVoutRenderScene ( vout_thread_t *, picture_t * ); * 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); @@ -96,27 +94,40 @@ static int get_capability_for_osversion(void) 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 ); +} + +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( _("DirectX 3D video output") ); - set_capability( "video output", get_capability_for_osversion() ); - add_shortcut( "direct3d" ); - set_callbacks( OpenVideo, CloseVideo ); +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 @@ -148,21 +159,18 @@ typedef struct 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 */ @@ -205,14 +213,18 @@ static int OpenVideo( vlc_object_t *p_this ) 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", - 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 ) { @@ -226,15 +238,13 @@ static int OpenVideo( vlc_object_t *p_this ) /* 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); @@ -254,7 +264,7 @@ static int OpenVideo( vlc_object_t *p_this ) } return VLC_SUCCESS; - error: +error: CloseVideo( VLC_OBJECT(p_vout) ); return VLC_EGENERIC; } @@ -270,6 +280,14 @@ static void CloseVideo( vlc_object_t *p_this ) 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 ); @@ -304,11 +322,8 @@ static void CloseVideo( vlc_object_t *p_this ) 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; } /***************************************************************************** @@ -317,10 +332,8 @@ static void CloseVideo( vlc_object_t *p_this ) 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 ) ) @@ -439,6 +452,28 @@ static int Manage( vout_thread_t *p_vout ) 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 ) @@ -531,7 +566,7 @@ static int Manage( vout_thread_t *p_vout ) } /* 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 */ } @@ -736,7 +771,7 @@ static void Direct3DVoutClose( vout_thread_t *p_vout ) IDirect3DDevice9_Release(p_vout->p_sys->p_d3ddev); p_vout->p_sys->p_d3ddev = NULL; } - + p_vout->p_sys->hmonitor = NULL; } @@ -848,17 +883,15 @@ static D3DFORMAT Direct3DVoutFindFormat(vout_thread_t *p_vout, int i_chroma, D3D /* 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 @@ -867,8 +900,7 @@ static D3DFORMAT Direct3DVoutFindFormat(vout_thread_t *p_vout, int i_chroma, D3D { 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 }; @@ -879,25 +911,25 @@ static D3DFORMAT Direct3DVoutFindFormat(vout_thread_t *p_vout, int i_chroma, D3D 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 }; @@ -945,32 +977,32 @@ static int Direct3DVoutSetOutputFormat(vout_thread_t *p_vout, D3DFORMAT format) 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; @@ -1034,7 +1066,7 @@ static int Direct3DVoutCreatePictures( vout_thread_t *p_vout, size_t i_num_pics /* 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; @@ -1042,7 +1074,7 @@ static int Direct3DVoutCreatePictures( vout_thread_t *p_vout, size_t i_num_pics * 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; @@ -1050,8 +1082,8 @@ static int Direct3DVoutCreatePictures( vout_thread_t *p_vout, size_t i_num_pics 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; @@ -1059,7 +1091,7 @@ static int Direct3DVoutCreatePictures( vout_thread_t *p_vout, size_t i_num_pics 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; @@ -1067,7 +1099,7 @@ static int Direct3DVoutCreatePictures( vout_thread_t *p_vout, size_t i_num_pics 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; @@ -1075,8 +1107,8 @@ static int Direct3DVoutCreatePictures( vout_thread_t *p_vout, size_t i_num_pics 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; @@ -1380,41 +1412,43 @@ static void Direct3DVoutRenderScene( vout_thread_t *p_vout, picture_t *p_pic ) } /* Setup vertices */ - f_width = (float)(p_vout->output.i_width) + 1; - f_height = (float)(p_vout->output.i_height) + 1; + 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) ) { @@ -1450,16 +1484,8 @@ static void Direct3DVoutRenderScene( vout_thread_t *p_vout, picture_t *p_pic ) 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) ) {