📄 direct3d.c
字号:
Direct3DVoutClose( p_vout );}/***************************************************************************** * Manage: handle Sys events ***************************************************************************** * This function should be called regularly by the video output thread. * It returns a non null value if an error occurred. *****************************************************************************/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 ); } /* * Position Change */ if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE ) {#if 0 /* need that when bicubic filter is available */ RECT rect; UINT width, height; GetClientRect(p_vout->p_sys->hvideownd, &rect); width = rect.right-rect.left; height = rect.bottom-rect.top; if( (width != p_vout->p_sys->d3dpp.BackBufferWidth) || (height != p_vout->p_sys->d3dpp.BackBufferHeight) ) { msg_Dbg(p_vout, "resizing device back buffers to (%lux%lu)", width, height); // need to reset D3D device to resize back buffer if( VLC_SUCCESS != Direct3DVoutResetDevice(p_vout, width, height) ) return VLC_EGENERIC; }#endif 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; 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 */ if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE ) { Win32ToggleFullscreen( p_vout ); 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) > p_vout->p_sys->i_mouse_hide_timeout ) { 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 = false; } /* Check if the event thread is still running */ if( !vlc_object_alive (p_vout->p_sys->p_event) ) { 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, &(p_vout->p_sys->rect_src_clipped), NULL, NULL, NULL); if( FAILED(hr) ) msg_Dbg( p_vout, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);}/*** this function is only used once when the first picture is received** this function will show the video window once a picture is ready*/static void FirstDisplay( vout_thread_t *p_vout, picture_t *p_pic ){ /* get initial picture presented through D3D */ Display(p_vout, p_pic); /* ** Video window is initially hidden, show it now since we got a ** picture to show. */ SetWindowPos( p_vout->p_sys->hvideownd, 0, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS| SWP_FRAMECHANGED| SWP_SHOWWINDOW| SWP_NOMOVE| SWP_NOSIZE| SWP_NOZORDER ); /* use and restores proper display function for further pictures */ p_vout->pf_display = Display;}/***************************************************************************** * 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_COPY; 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| D3DCREATE_MULTITHREADED, &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 ***************************************************************************** * All resources must be deallocated before the reset occur, they will be * realllocated once the reset has been performed successfully
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -