📄 direct3d.c
字号:
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, 0 ); } } else { vlc_mutex_unlock( &p_vout->p_sys->lock ); } /* * Position Change */ if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE ) { p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE; } /* 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. */ /* * Fullscreen change */ if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE ) { 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( hwnd, &window_placement ); if( p_vout->b_fullscreen ) { /* Change window style, no borders and no title bar */ int i_style = WS_CLIPCHILDREN | WS_VISIBLE; SetWindowLong( hwnd, GWL_STYLE, i_style ); if( p_vout->p_sys->hparent ) { /* 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 ); } /* 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 ) { 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 ); } /* 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 ){ 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, NULL, NULL, NULL, NULL); if( FAILED(hr) ) msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); /* 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, 0UL); /* ** According to virtual dub blog, Vista has problems rendering 3D child windows ** created by a different thread than its parent. Try the workaround in ** http://www.virtualdub.org/blog/pivot/entry.php?id=149 */ if( _got_vista_or_above ) { SetWindowPos( p_vout->p_sys->hvideownd, 0, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); } }}/***************************************************************************** * DirectD3DVoutCreate: Initialize and instance of Direct3D9 ***************************************************************************** * This function initialize Direct3D and analyze available resources from * default adapter. *****************************************************************************/static int Direct3DVoutCreate( vout_thread_t *p_vout ){ HRESULT hr; LPDIRECT3D9 p_d3dobj; D3DCAPS9 d3dCaps; LPDIRECT3D9 (WINAPI *OurDirect3DCreate9)(UINT SDKVersion); p_vout->p_sys->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL")); if( NULL == p_vout->p_sys->hd3d9_dll ) { msg_Warn( p_vout, "cannot load d3d9.dll, aborting" ); return VLC_EGENERIC; } OurDirect3DCreate9 = (void *)GetProcAddress( p_vout->p_sys->hd3d9_dll, TEXT("Direct3DCreate9") ); if( OurDirect3DCreate9 == NULL ) { msg_Err( p_vout, "Cannot locate reference to Direct3DCreate9 ABI in DLL" ); return VLC_EGENERIC; } /* Create the D3D object. */ p_d3dobj = OurDirect3DCreate9( D3D_SDK_VERSION ); if( NULL == p_d3dobj ) { msg_Err( p_vout, "Could not create Direct3D9 instance."); return VLC_EGENERIC; } p_vout->p_sys->p_d3dobj = p_d3dobj; /* ** Get device capabilities */ ZeroMemory(&d3dCaps, sizeof(d3dCaps)); hr = IDirect3D9_GetDeviceCaps(p_d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps); if( FAILED(hr) ) { msg_Err( p_vout, "Could not read adapter capabilities. (hr=0x%lX)", hr); return VLC_EGENERIC; } /* TODO: need to test device capabilities and select the right render function */ return VLC_SUCCESS;}/***************************************************************************** * DirectD3DVoutRelease: release an instance of Direct3D9 *****************************************************************************/static void Direct3DVoutRelease( vout_thread_t *p_vout ){ if( p_vout->p_sys->p_d3dobj ) { IDirect3D9_Release(p_vout->p_sys->p_d3dobj); p_vout->p_sys->p_d3dobj = NULL; } if( NULL != p_vout->p_sys->hd3d9_dll ) { FreeLibrary(p_vout->p_sys->hd3d9_dll); p_vout->p_sys->hd3d9_dll = NULL; }}static int Direct3DFillPresentationParameters(vout_thread_t *p_vout, D3DPRESENT_PARAMETERS *d3dpp){ LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj; D3DDISPLAYMODE d3ddm; HRESULT hr; /* ** Get the current desktop display mode, so we can set up a back ** buffer of the same format */ hr = IDirect3D9_GetAdapterDisplayMode(p_d3dobj, D3DADAPTER_DEFAULT, &d3ddm ); if( FAILED(hr)) { msg_Err( p_vout, "Could not read adapter display mode. (hr=0x%lX)", hr); return VLC_EGENERIC; } /* keep a copy of current desktop format */ p_vout->p_sys->bbFormat = d3ddm.Format; /* Set up the structure used to create the D3DDevice. */ ZeroMemory( d3dpp, sizeof(D3DPRESENT_PARAMETERS) ); d3dpp->Flags = D3DPRESENTFLAG_VIDEO; d3dpp->Windowed = TRUE; d3dpp->hDeviceWindow = p_vout->p_sys->hvideownd; d3dpp->BackBufferWidth = p_vout->output.i_width; d3dpp->BackBufferHeight = p_vout->output.i_height; d3dpp->SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp->MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; d3dpp->BackBufferFormat = d3ddm.Format; d3dpp->BackBufferCount = 1; d3dpp->EnableAutoDepthStencil = FALSE; return VLC_SUCCESS;}/***************************************************************************** * DirectD3DVoutOpen: Takes care of all the Direct3D9 initialisations ***************************************************************************** * This function creates Direct3D device * this must be called from the vout thread for performance reason, as * all Direct3D Device APIs are used in a non multithread safe environment *****************************************************************************/static int Direct3DVoutOpen( vout_thread_t *p_vout ){ LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj; LPDIRECT3DDEVICE9 p_d3ddev; D3DPRESENT_PARAMETERS d3dpp; HRESULT hr; if( VLC_SUCCESS != Direct3DFillPresentationParameters(p_vout, &d3dpp) ) return VLC_EGENERIC; // Create the D3DDevice hr = IDirect3D9_CreateDevice(p_d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, p_vout->p_sys->hvideownd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &p_d3ddev ); if( FAILED(hr) ) { msg_Err(p_vout, "Could not create the D3D device! (hr=0x%lX)", hr); return VLC_EGENERIC; } p_vout->p_sys->p_d3ddev = p_d3ddev; msg_Dbg( p_vout, "Direct3D device adapter successfully initialized" ); return VLC_SUCCESS;}/***************************************************************************** * DirectD3DClose: release the Direct3D9 device *****************************************************************************/static void Direct3DVoutClose( vout_thread_t *p_vout ){ if( p_vout->p_sys->p_d3ddev ) { IDirect3DDevice9_Release(p_vout->p_sys->p_d3ddev); p_vout->p_sys->p_d3ddev = NULL; } p_vout->p_sys->hmonitor = NULL;}/***************************************************************************** * DirectD3DClose: reset the Direct3D9 device
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -