X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fmsw%2Fdirect3d.c;h=c4384b2d2c071d487d6f2c272ccd6c37adeafd11;hb=e662143171fffb4dc18e4863500e9448390b8a41;hp=4503e27165146c8c799d6fbdc9aa5291d39dbf39;hpb=724461bdf250e856eb32f6c0b7c51b065e482982;p=vlc diff --git a/modules/video_output/msw/direct3d.c b/modules/video_output/msw/direct3d.c index 4503e27165..c4384b2d2c 100644 --- a/modules/video_output/msw/direct3d.c +++ b/modules/video_output/msw/direct3d.c @@ -80,6 +80,10 @@ static int Direct3DVoutCreateScene ( vout_thread_t * ); static void Direct3DVoutReleaseScene ( vout_thread_t * ); static void Direct3DVoutRenderScene ( vout_thread_t *, picture_t * ); +static int DesktopCallback( vlc_object_t *p_this, char const *psz_cmd, + vlc_value_t oldval, vlc_value_t newval, + void *p_data ); + /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -111,10 +115,18 @@ static int OpenVideoVista( vlc_object_t *obj ) return IsVistaOrAbove() ? OpenVideo( obj ) : VLC_EGENERIC; } +#define DESKTOP_TEXT N_("Enable desktop mode ") +#define DESKTOP_LONGTEXT N_( \ + "The desktop mode allows you to display the video on the desktop." ) + vlc_module_begin () set_shortname( "Direct3D" ) set_category( CAT_VIDEO ) set_subcategory( SUBCAT_VIDEO_VOUT ) + + add_bool( "direct3d-desktop", false, NULL, DESKTOP_TEXT, DESKTOP_LONGTEXT, + true ) + set_description( N_("DirectX 3D video output") ) set_capability( "video output", 50 ) add_shortcut( "direct3d" ) @@ -158,6 +170,7 @@ typedef struct *****************************************************************************/ static int OpenVideo( vlc_object_t *p_this ) { + vlc_value_t val; vout_thread_t * p_vout = (vout_thread_t *)p_this; /* Allocate structure */ @@ -179,89 +192,22 @@ static int OpenVideo( vlc_object_t *p_this ) p_vout->pf_manage = Manage; p_vout->pf_render = Direct3DVoutRenderScene; p_vout->pf_display = FirstDisplay; + p_vout->pf_control = Control; - 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; - vlc_mutex_init( &p_vout->p_sys->lock ); - SetRectEmpty( &p_vout->p_sys->rect_display ); - SetRectEmpty( &p_vout->p_sys->rect_parent ); + if( CommonInit( p_vout ) ) + goto error; + p_vout->p_sys->b_desktop = false; var_Create( p_vout, "directx-hw-yuv", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_vout, "directx-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - 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; - - var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); - - /* 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; - - /* Create the Vout EventThread, this thread is created by us to isolate - * the Win32 PeekMessage function calls. We want to do this because - * Windows can stay blocked inside this call for a long time, and when - * this happens it thus blocks vlc's video_output thread. - * Vout EventThread will take care of the creation of the video - * window (because PeekMessage has to be called from the same thread which - * created the window). */ - msg_Dbg( p_vout, "creating Vout EventThread" ); - 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 ) ) - { - 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 ) - { - msg_Err( p_vout, "Vout EventThread failed" ); - goto error; - } - - vlc_object_attach( p_vout->p_sys->p_event, p_vout ); - - msg_Dbg( p_vout, "Vout EventThread running" ); - - /* Variable to indicate if the window should be on top of others */ /* Trigger a callback right now */ - 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; - if( var_GetBool( p_vout, "disable-screensaver" ) ) { - msg_Dbg(p_vout, "disabling screen saver"); - SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT, - 0, &(p_vout->p_sys->i_spi_lowpowertimeout), 0); - if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) { - SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0); - } - SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0, - &(p_vout->p_sys->i_spi_powerofftimeout), 0); - if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) { - SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, 0, NULL, 0); - } - SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0, - &(p_vout->p_sys->i_spi_screensavetimeout), 0); - if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) { - SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 0, NULL, 0); - } - } + var_Create( p_vout, "direct3d-desktop", VLC_VAR_BOOL|VLC_VAR_DOINHERIT ); + val.psz_string = _("Desktop"); + var_Change( p_vout, "direct3d-desktop", VLC_VAR_SETTEXT, &val, NULL ); + var_AddCallback( p_vout, "direct3d-desktop", DesktopCallback, NULL ); + var_TriggerCallback( p_vout, "direct3d-desktop" ); + return VLC_SUCCESS; error: @@ -280,50 +226,9 @@ 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 ); - - /* Kill Vout EventThread */ - vlc_object_kill( p_vout->p_sys->p_event ); - - /* we need to be sure Vout EventThread won't stay stuck in - * GetMessage, so we send a fake message */ - if( p_vout->p_sys->hwnd ) - { - PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0); - } - - vlc_thread_join( p_vout->p_sys->p_event ); - vlc_object_release( p_vout->p_sys->p_event ); - } - - vlc_mutex_destroy( &p_vout->p_sys->lock ); - - /* restore screensaver system settings */ - if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) { - SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, - p_vout->p_sys->i_spi_lowpowertimeout, NULL, 0); - } - if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) { - SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, - p_vout->p_sys->i_spi_powerofftimeout, NULL, 0); - } - if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) { - SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, - p_vout->p_sys->i_spi_screensavetimeout, NULL, 0); - } + CommonClean( p_vout ); free( p_vout->p_sys ); - p_vout->p_sys = NULL; } /***************************************************************************** @@ -397,35 +302,7 @@ static void End( vout_thread_t *p_vout ) *****************************************************************************/ static int Manage( vout_thread_t *p_vout ) { - /* 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_mutex_unlock( &p_vout->p_sys->lock ); - - 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 ); - - if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) ) - { - p_vout->p_sys->rect_parent = rect_parent; - - SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, - rect_parent.right - rect_parent.left, - rect_parent.bottom - rect_parent.top, - SWP_NOZORDER ); - } - } - else - { - vlc_mutex_unlock( &p_vout->p_sys->lock ); - } + CommonManage( p_vout ); /* * Position Change @@ -452,123 +329,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 ) - { - p_vout->i_changes &= ~VOUT_CROP_CHANGE; - p_vout->i_changes &= ~VOUT_ASPECT_CHANGE; - - p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset; - p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset; - p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width; - p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height; - p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect; - p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num; - p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den; - p_vout->output.i_aspect = p_vout->fmt_in.i_aspect; - UpdateRects( p_vout, true ); - } - - /* We used to call the Win32 PeekMessage function here to read the window - * messages. But since window can stay blocked into this function for a - * long time (for example when you move your window on the screen), I - * decided to isolate PeekMessage in another thread. */ - /* - * Fullscreen change + * Desktop mode change */ - if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE - || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE ) + if( p_vout->p_sys->i_changes & DX_DESKTOP_CHANGE ) { - Win32ToggleFullscreen( p_vout ); + /* Close the direct3d instance attached to the current output window. */ + End( p_vout ); - p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; - p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE; - } + ExitFullscreen( p_vout ); - /* - * 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; + EventThreadStop( p_vout->p_sys->p_event ); - /* 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(); - } - } + /* Open the direct3d output and attaches it to the new window */ + p_vout->p_sys->b_desktop = !p_vout->p_sys->b_desktop; + p_vout->pf_display = FirstDisplay; - /* - * "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 ); + EventThreadStart( p_vout->p_sys->p_event ); - var_Get( p_vout, "video-on-top", &val ); + Init( p_vout ); - /* 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 ); - } - - p_vout->p_sys->b_on_top_change = false; - } - - /* Check if the event thread is still running */ - if( !vlc_object_alive (p_vout->p_sys->p_event) ) - { - return VLC_EGENERIC; /* exit */ + /* Reset the flag */ + p_vout->p_sys->i_changes &= ~DX_DESKTOP_CHANGE; } return VLC_SUCCESS; @@ -582,7 +364,10 @@ static int Manage( vout_thread_t *p_vout ) *****************************************************************************/ static void Display( vout_thread_t *p_vout, picture_t *p_pic ) { + VLC_UNUSED( p_pic ); + LPDIRECT3DDEVICE9 p_d3ddev = p_vout->p_sys->p_d3ddev; + // Present the back buffer contents to the display // stretching and filtering happens here HRESULT hr = IDirect3DDevice9_Present(p_d3ddev, @@ -1028,7 +813,8 @@ static int Direct3DVoutCreatePictures( vout_thread_t *p_vout, size_t i_num_pics HRESULT hr; size_t c; // if vout is already running, use current chroma, otherwise choose from upstream - int i_chroma = p_vout->output.i_chroma ? : p_vout->render.i_chroma; + int i_chroma = p_vout->output.i_chroma ? p_vout->output.i_chroma + : p_vout->render.i_chroma; I_OUTPUTPICTURES = 0; @@ -1404,7 +1190,7 @@ static void Direct3DVoutRenderScene( vout_thread_t *p_vout, picture_t *p_pic ) } /* Update the vertex buffer */ - hr = IDirect3DVertexBuffer9_Lock(p_d3dvtc, 0, 0, (VOID **)(&p_vertices), D3DLOCK_DISCARD); + hr = IDirect3DVertexBuffer9_Lock(p_d3dvtc, 0, 0, (&p_vertices), D3DLOCK_DISCARD); if( FAILED(hr) ) { msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); @@ -1512,3 +1298,36 @@ static void Direct3DVoutRenderScene( vout_thread_t *p_vout, picture_t *p_pic ) } } + +/***************************************************************************** + * DesktopCallback: desktop mode variable callback + *****************************************************************************/ +static int DesktopCallback( 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_desktop) || + (!newval.b_bool && p_vout->p_sys->b_desktop) ) + { + 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, "direct3d-desktop", VLC_VAR_BOOL ); + var_Set( p_playlist, "direct3d-desktop", newval ); + pl_Release( p_vout ); + } + + p_vout->p_sys->i_changes |= DX_DESKTOP_CHANGE; + } + + return VLC_SUCCESS; +}