X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fdirectx%2Fdirectx.c;h=5c345c579d73b5f67380ada45020577073fafad7;hb=b7e5d7c50f89f9c354627729901bd3b0630f6f47;hp=7386e5c119a4d94c8bb3ef0bdefc0affe3127285;hpb=595f0c8f34c9048208f41c8117fed964839f5392;p=vlc diff --git a/modules/video_output/directx/directx.c b/modules/video_output/directx/directx.c index 7386e5c119..5c345c579d 100644 --- a/modules/video_output/directx/directx.c +++ b/modules/video_output/directx/directx.c @@ -1,7 +1,7 @@ /***************************************************************************** * vout.c: Windows DirectX video output display method ***************************************************************************** - * Copyright (C) 2001-2004 VideoLAN + * Copyright (C) 2001-2004 the VideoLAN team * $Id$ * * Authors: Gildas Bazin @@ -44,8 +44,11 @@ #include #include +#include -#include +#ifndef UNDER_CE +# include +#endif #undef GetSystemMetrics #ifndef MONITOR_DEFAULTTONEAREST @@ -73,6 +76,7 @@ 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 SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * ); static int NewPictureVec ( vout_thread_t *, picture_t *, int ); static void FreePictureVec ( vout_thread_t *, picture_t *, int ); @@ -91,11 +95,15 @@ 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 ); +static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *i_color ); + +void SwitchWallpaperMode( vout_thread_t *, vlc_bool_t ); /* 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 * ); /***************************************************************************** * Module descriptor @@ -114,18 +122,28 @@ static int FindDevicesCallback( vlc_object_t *, char const *, #define TRIPLEBUF_TEXT N_("Use triple buffering for overlays") #define TRIPLEBUF_LONGTEXT N_( \ - "Try to use triple bufferring when using YUV overlays. That results in " \ + "Try to use triple buffering when using YUV overlays. That results in " \ "much better video quality (no flickering)." ) #define DEVICE_TEXT N_("Name of desired display device") -#define DEVICE_LONGTEXT N_("In a multimonitor 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 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 char *ppsz_dev[] = { "" }; static char *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, VLC_TRUE ); add_bool( "directx-use-sysmem", 0, NULL, SYSMEM_TEXT, SYSMEM_LONGTEXT, @@ -138,10 +156,16 @@ vlc_module_begin(); 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, + VLC_TRUE ); + set_description( _("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 */ @@ -184,8 +208,9 @@ static int OpenVideo( vlc_object_t *p_this ) 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 = 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_vout->p_sys->lock ); SetRectEmpty( &p_vout->p_sys->rect_display ); SetRectEmpty( &p_vout->p_sys->rect_parent ); @@ -195,12 +220,16 @@ static int OpenVideo( vlc_object_t *p_this ) p_vout->p_sys->p_display_driver = NULL; p_vout->p_sys->MonitorFromWindow = NULL; p_vout->p_sys->GetMonitorInfo = NULL; - if( (huser32 = GetModuleHandle( "USER32" ) ) ) + if( (huser32 = GetModuleHandle( _T("USER32") ) ) ) { - p_vout->p_sys->MonitorFromWindow = - GetProcAddress( huser32, "MonitorFromWindow" ); + 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 ); @@ -229,7 +258,7 @@ static int OpenVideo( vlc_object_t *p_this ) vlc_object_create( p_vout, sizeof(event_thread_t) ); p_vout->p_sys->p_event->p_vout = p_vout; if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread", - DirectXEventThread, 0, 1 ) ) + E_(DirectXEventThread), 0, 1 ) ) { msg_Err( p_vout, "cannot create DirectXEventThread" ); vlc_object_destroy( p_vout->p_sys->p_event ); @@ -266,6 +295,15 @@ static int OpenVideo( vlc_object_t *p_this ) var_Get( p_vout, "video-on-top", &val ); var_Set( p_vout, "video-on-top", val ); + /* 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_Get( p_vout, "directx-wallpaper", &val ); + var_Set( p_vout, "directx-wallpaper", val ); + return VLC_SUCCESS; error: @@ -318,6 +356,8 @@ static int Init( vout_thread_t *p_vout ) 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; + E_(DirectXUpdateRects)( p_vout, VLC_TRUE ); #define MAX_DIRECTBUFFERS 1 /* Right now we use only 1 directbuffer because we don't want the @@ -351,7 +391,7 @@ static int Init( vout_thread_t *p_vout ) if( !I_OUTPUTPICTURES ) { /* hmmm, it didn't work! Let's try commonly supported chromas */ - if( p_vout->output.i_chroma != VLC_FOURCC('Y','V','1','2') ) + if( p_vout->output.i_chroma != VLC_FOURCC('I','4','2','0') ) { p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2'); NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS ); @@ -375,6 +415,7 @@ static int Init( vout_thread_t *p_vout ) /* Change the window title bar text */ PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 ); + p_vout->fmt_out.i_chroma = p_vout->output.i_chroma; return VLC_SUCCESS; } @@ -425,6 +466,9 @@ static void CloseVideo( vlc_object_t *p_this ) vlc_mutex_destroy( &p_vout->p_sys->lock ); + /* Make sure the wallpaper is restored */ + SwitchWallpaperMode( p_vout, VLC_FALSE ); + if( p_vout->p_sys ) { free( p_vout->p_sys ); @@ -436,7 +480,7 @@ static void CloseVideo( vlc_object_t *p_this ) * Manage: handle Sys events ***************************************************************************** * This function should be called regularly by the video output thread. - * It returns a non null value if an error occured. + * It returns a non null value if an error occurred. *****************************************************************************/ static int Manage( vout_thread_t *p_vout ) { @@ -495,62 +539,117 @@ static int Manage( vout_thread_t *p_vout ) } } + /* 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; + E_(DirectXUpdateRects)( p_vout, VLC_TRUE ); + } + /* We used to call the Win32 PeekMessage function here to read the window * messages. But since window can stay blocked into this function for a * long time (for example when you move your window on the screen), I * decided to isolate PeekMessage in another thread. */ + if( 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; + E_(DirectXUpdateOverlay)( p_vout ); + } + /* * Fullscreen change */ if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE ) { - int i_style = 0; vlc_value_t val; + HWND hwnd = (p_vout->p_sys->hparent && p_vout->p_sys->hfswnd) ? + p_vout->p_sys->hfswnd : p_vout->p_sys->hwnd; p_vout->b_fullscreen = ! p_vout->b_fullscreen; /* We need to switch between Maximized and Normal sized window */ window_placement.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement( p_vout->p_sys->hwnd, &window_placement ); + GetWindowPlacement( hwnd, &window_placement ); if( p_vout->b_fullscreen ) { - if( p_vout->p_sys->hparent ) - { - SetParent( p_vout->p_sys->hwnd, GetDesktopWindow() ); - SetForegroundWindow( p_vout->p_sys->hwnd ); - } - - /* Maximized window */ - window_placement.showCmd = SW_SHOWMAXIMIZED; /* Change window style, no borders and no title bar */ - i_style = WS_CLIPCHILDREN; - } - else - { + int i_style = WS_CLIPCHILDREN | WS_VISIBLE; + SetWindowLong( hwnd, GWL_STYLE, i_style ); + if( p_vout->p_sys->hparent ) { - SetParent( p_vout->p_sys->hwnd, p_vout->p_sys->hparent ); - i_style = WS_CLIPCHILDREN | WS_VISIBLE | WS_CHILD; + /* Retrieve current window position so fullscreen will happen + * on the right screen */ + POINT point = {0,0}; + RECT rect; + ClientToScreen( p_vout->p_sys->hwnd, &point ); + GetClientRect( p_vout->p_sys->hwnd, &rect ); + SetWindowPos( hwnd, 0, point.x, point.y, + rect.right, rect.bottom, + SWP_NOZORDER|SWP_FRAMECHANGED ); + GetWindowPlacement( hwnd, &window_placement ); } - else + + /* Maximize window */ + window_placement.showCmd = SW_SHOWMAXIMIZED; + SetWindowPlacement( hwnd, &window_placement ); + SetWindowPos( hwnd, 0, 0, 0, 0, 0, + SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); + + if( p_vout->p_sys->hparent ) { - i_style = WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | - WS_SIZEBOX | WS_VISIBLE; + RECT rect; + GetClientRect( hwnd, &rect ); + SetParent( p_vout->p_sys->hwnd, hwnd ); + SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, + rect.right, rect.bottom, + SWP_NOZORDER|SWP_FRAMECHANGED ); } + SetForegroundWindow( hwnd ); + } + else + { + /* Change window style, no borders and no title bar */ + SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style ); + /* Normal window */ window_placement.showCmd = SW_SHOWNORMAL; + SetWindowPlacement( hwnd, &window_placement ); + SetWindowPos( hwnd, 0, 0, 0, 0, 0, + SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); + + if( p_vout->p_sys->hparent ) + { + RECT rect; + GetClientRect( p_vout->p_sys->hparent, &rect ); + SetParent( p_vout->p_sys->hwnd, p_vout->p_sys->hparent ); + SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, + rect.right, rect.bottom, + SWP_NOZORDER|SWP_FRAMECHANGED ); + + ShowWindow( hwnd, SW_HIDE ); + SetForegroundWindow( p_vout->p_sys->hparent ); + } /* Make sure the mouse cursor is displayed */ PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 ); } - /* Change window style, borders and title bar */ - SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE, i_style ); - SetWindowPlacement( p_vout->p_sys->hwnd, &window_placement ); - /* Update the object variable and trigger callback */ val.b_bool = p_vout->b_fullscreen; var_Set( p_vout, "fullscreen", val ); @@ -566,15 +665,12 @@ static int Manage( vout_thread_t *p_vout ) (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 ) { POINT point; - RECT rect; + HWND hwnd; /* Hide the cursor only if it is inside our window */ - GetClientRect( p_vout->p_sys->hwnd, &rect ); - point.x = point.y = 0; - ClientToScreen( p_vout->p_sys->hwnd, &point ); - OffsetRect( &rect, point.x, point.y ); GetCursorPos( &point ); - if( PtInRect( &rect, 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 ); } @@ -649,7 +745,7 @@ static void Display( vout_thread_t *p_vout, picture_t *p_pic ) { if( IDirectDrawSurface2_Restore( p_vout->p_sys->p_display ) == DD_OK && p_vout->p_sys->b_using_overlay ) - DirectXUpdateOverlay( p_vout ); + E_(DirectXUpdateOverlay)( p_vout ); } if( !p_vout->p_sys->b_using_overlay ) @@ -786,7 +882,7 @@ static int DirectXInitDDraw( vout_thread_t *p_vout ) msg_Dbg( p_vout, "DirectXInitDDraw" ); /* Load direct draw DLL */ - p_vout->p_sys->hddraw_dll = LoadLibrary("DDRAW.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" ); @@ -794,7 +890,8 @@ static int DirectXInitDDraw( vout_thread_t *p_vout ) } OurDirectDrawCreate = - (void *)GetProcAddress(p_vout->p_sys->hddraw_dll, "DirectDrawCreate"); + (void *)GetProcAddress( p_vout->p_sys->hddraw_dll, + _T("DirectDrawCreate") ); if( OurDirectDrawCreate == NULL ) { msg_Err( p_vout, "DirectXInitDDraw failed GetProcAddress" ); @@ -803,7 +900,11 @@ static int DirectXInitDDraw( vout_thread_t *p_vout ) OurDirectDrawEnumerateEx = (void *)GetProcAddress( p_vout->p_sys->hddraw_dll, +#ifndef UNICODE "DirectDrawEnumerateExA" ); +#else + _T("DirectDrawEnumerateExW") ); +#endif if( OurDirectDrawEnumerateEx && p_vout->p_sys->MonitorFromWindow ) { @@ -941,13 +1042,13 @@ static int DirectXCreateDisplay( vout_thread_t *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 ); + DirectXFindColorkey( p_vout, &p_vout->p_sys->i_colorkey ); /* Create the actual brush */ SetClassLong( p_vout->p_sys->hvideownd, GCL_HBRBACKGROUND, (LONG)CreateSolidBrush( p_vout->p_sys->i_rgb_colorkey ) ); InvalidateRect( p_vout->p_sys->hvideownd, NULL, TRUE ); - DirectXUpdateRects( p_vout, VLC_TRUE ); + E_(DirectXUpdateRects)( p_vout, VLC_TRUE ); return VLC_SUCCESS; } @@ -1115,7 +1216,7 @@ static int DirectXCreateSurface( vout_thread_t *p_vout, /* 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( DirectXUpdateOverlay( p_vout ) != VLC_SUCCESS ) + if( E_(DirectXUpdateOverlay)( p_vout ) != VLC_SUCCESS ) { IDirectDrawSurface2_Release( *pp_surface_final ); *pp_surface_final = NULL; @@ -1134,7 +1235,7 @@ static int DirectXCreateSurface( vout_thread_t *p_vout, * Ususally the overlay is moved by the user and thus, by a move or resize * event (in Manage). *****************************************************************************/ -int DirectXUpdateOverlay( vout_thread_t *p_vout ) +int E_(DirectXUpdateOverlay)( vout_thread_t *p_vout ) { DDOVERLAYFX ddofx; DWORD dwFlags; @@ -1144,6 +1245,25 @@ int DirectXUpdateOverlay( vout_thread_t *p_vout ) if( !p_vout->p_sys->b_using_overlay ) return VLC_EGENERIC; + if( p_vout->p_sys->b_wallpaper ) + { + int 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 ) { @@ -1329,7 +1449,7 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic, { int i,j; for( i = 0; i < front_pic.i_planes; i++ ) - for( j = 0; j < front_pic.p[i].i_lines; j++) + 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 ); @@ -1337,7 +1457,7 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic, DirectXUnlockSurface( p_vout, &front_pic ); } - DirectXUpdateOverlay( p_vout ); + E_(DirectXUpdateOverlay)( p_vout ); I_OUTPUTPICTURES = 1; msg_Dbg( p_vout, "YUV overlay created successfully" ); } @@ -1400,8 +1520,9 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic, { switch( ddpfPixelFormat.dwRGBBitCount ) { - case 8: /* FIXME: set the palette */ + case 8: p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); + p_vout->output.pf_setpalette = SetPalette; break; case 15: p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); @@ -1470,6 +1591,7 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic, { p_pic[i].i_status = DESTROYED_PICTURE; p_pic[i].i_type = DIRECT_PICTURE; + p_pic[i].b_slow = VLC_TRUE; p_pic[i].pf_lock = DirectXLockSurface; p_pic[i].pf_unlock = DirectXUnlockSurface; PP_OUTPUTPICTURE[i] = &p_pic[i]; @@ -1533,6 +1655,7 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic, case VLC_FOURCC('R','V','3','2'): 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 ) { @@ -1558,9 +1681,15 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic, break; case VLC_FOURCC('Y','V','1','2'): + case VLC_FOURCC('I','4','2','0'): + + /* U and V inverted compared to I420 + * Fixme: this should be handled by the vout core */ + p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0'); 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 * @@ -1569,6 +1698,7 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic, 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 * @@ -1577,6 +1707,7 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic, 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 * @@ -1589,6 +1720,7 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic, 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 * @@ -1597,6 +1729,7 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic, 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 * @@ -1605,6 +1738,7 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic, 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 * @@ -1613,10 +1747,12 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic, p_pic->i_planes = 3; break; + case VLC_FOURCC('U','Y','V','Y'): case VLC_FOURCC('Y','U','Y','2'): 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 * @@ -1759,8 +1895,10 @@ static int DirectXLockSurface( vout_thread_t *p_vout, picture_t *p_pic ) dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface, NULL, &p_pic->p_sys->ddsd, DDLOCK_WAIT, NULL); +#if 0 if( dxresult == DDERR_SURFACELOST ) msg_Dbg( p_vout, "DirectXLockSurface: DDERR_SURFACELOST" ); +#endif } if( dxresult != DD_OK ) { @@ -1795,7 +1933,7 @@ static int DirectXUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic ) /***************************************************************************** * DirectXFindColorkey: Finds out the 32bits RGB pixel value of the colorkey *****************************************************************************/ -static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t i_color ) +static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *pi_color ) { DDSURFACEDESC ddsd; HRESULT dxresult; @@ -1813,16 +1951,20 @@ static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t i_color ) switch( ddsd.ddpfPixelFormat.dwRGBBitCount ) { case 4: - *(uint8_t *)ddsd.lpSurface = 0x11; + *(uint8_t *)ddsd.lpSurface = *pi_color | (*pi_color << 4); break; case 8: - *(uint8_t *)ddsd.lpSurface = 0x01; + *(uint8_t *)ddsd.lpSurface = *pi_color; break; + case 15: case 16: - *(uint16_t *)ddsd.lpSurface = 0x01; + *(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 = 0x01; + *(uint32_t *)ddsd.lpSurface = *pi_color; break; } @@ -1846,6 +1988,48 @@ static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t i_color ) return i_rgb; } +/***************************************************************************** + * A few toolbox functions + *****************************************************************************/ +void SwitchWallpaperMode( vout_thread_t *p_vout, vlc_bool_t b_on ) +{ + HWND hwnd; + + if( p_vout->p_sys->b_wallpaper == b_on ) return; /* Nothing to do */ + + 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" ); + return; + } + + p_vout->p_sys->b_wallpaper = b_on; + + msg_Dbg( p_vout, "wallpaper mode %s", b_on ? "enabled" : "disabled" ); + + 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 ); + + 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 ); + } + + /* Update desktop */ + InvalidateRect( hwnd, NULL, TRUE ); + UpdateWindow( hwnd ); +} + /***************************************************************************** * config variable callback *****************************************************************************/ @@ -1900,11 +2084,15 @@ static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name, p_item->i_list = 1; /* Load direct draw DLL */ - hddraw_dll = LoadLibrary("DDRAW.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 if( OurDirectDrawEnumerateEx ) { @@ -1915,5 +2103,47 @@ static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name, FreeLibrary( hddraw_dll ); + /* Signal change to the interface */ + p_item->b_dirty = VLC_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 ) +{ + 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; + + p_playlist = + (playlist_t *)vlc_object_find( p_this, VLC_OBJECT_PLAYLIST, + FIND_PARENT ); + 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 ); + + vlc_object_release( p_playlist ); + } + + 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 ) +{ + msg_Err( p_vout, "FIXME: SetPalette unimplemented" ); +}