📄 directx.c
字号:
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 ); } /* Update the object variable and trigger callback */ val.b_bool = p_vout->b_fullscreen; var_Set( p_vout, "fullscreen", val ); p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE; } /* * Pointer change */ if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden && (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 ) { 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(); } } /* * "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 ); } p_vout->p_sys->b_on_top_change = VLC_FALSE; } /* Check if the event thread is still running */ if( p_vout->p_sys->p_event->b_die ) { return VLC_EGENERIC; /* exit */ } 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 ){ HRESULT dxresult; if( (p_vout->p_sys->p_display == NULL) ) { msg_Warn( p_vout, "no display!" ); return; } /* 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 ) E_(DirectXUpdateOverlay)( p_vout ); } if( !p_vout->p_sys->b_using_overlay ) { DDBLTFX ddbltfx; /* We ask for the "NOTEARING" option */ memset( &ddbltfx, 0, sizeof(DDBLTFX) ); ddbltfx.dwSize = sizeof(DDBLTFX); ddbltfx.dwDDFX = DDBLTFX_NOTEARING; /* 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; } else { /* if set, remove the black brush to avoid flickering in repaint operations */ if( 0UL != GetClassLong( p_vout->p_sys->hvideownd, GCL_HBRBACKGROUND) ) { SetClassLong(p_vout->p_sys->hvideownd, GCL_HBRBACKGROUND, (ULONG)0UL); } } } 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 ); } /* set currently displayed pic */ p_vout->p_sys->p_current_surface = p_pic->p_sys->p_front_surface; /* 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 ); }}/*** this function is only used once when the first picture is received** The overlay colorkey replaces black as the background color on the** video window; this will cause the overlay surface to be displayed*/static void OverlayDisplay( 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); /* set the colorkey as the backgound brush for the video window */ 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 ); /* use and restores proper display function for further pictures */ p_vout->pf_display = Display;}/* 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 ){ 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 ) { if( device.psz_string ) 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; if( device.psz_string ) free( device.psz_string ); } else { if( device.psz_string ) free( device.psz_string ); return TRUE; /* Keep enumerating */ } 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) ); } return TRUE; /* Keep enumerating */}/***************************************************************************** * 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; } OurDirectDrawCreate = (void *)GetProcAddress( p_vout->p_sys->hddraw_dll, _T("DirectDrawCreate") ); if( OurDirectDrawCreate == NULL ) { msg_Err( p_vout, "DirectXInitDDraw failed GetProcAddress" ); goto error; } 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; 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 ); } p_vout->p_sys->hmonitor = p_vout->p_sys->MonitorFromWindow( p_vout->p_sys->hwnd, MONITOR_DEFAULTTONEAREST ); /* Enumerate displays */ OurDirectDrawEnumerateEx( DirectXEnumCallback, p_vout,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -