📄 directx.c
字号:
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 %d,%d", 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("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, "DirectDrawCreate"); if( OurDirectDrawCreate == NULL ) { msg_Err( p_vout, "DirectXInitDDraw failed GetProcAddress" ); goto error; } OurDirectDrawEnumerateEx = (void *)GetProcAddress( p_vout->p_sys->hddraw_dll, "DirectDrawEnumerateExA" ); 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, DDENUM_ATTACHEDSECONDARYDEVICES ); } /* Initialize DirectDraw now */ dxresult = OurDirectDrawCreate( p_vout->p_sys->p_display_driver, &p_ddobject, NULL ); if( dxresult != DD_OK ) { msg_Err( p_vout, "DirectXInitDDraw cannot initialize DDraw" ); goto error; } /* Get the IDirectDraw2 interface */ dxresult = IDirectDraw_QueryInterface( p_ddobject, &IID_IDirectDraw2, (LPVOID *)&p_vout->p_sys->p_ddobject ); /* Release the unused interface */ IDirectDraw_Release( p_ddobject ); if( dxresult != DD_OK ) { msg_Err( p_vout, "cannot get IDirectDraw2 interface" ); goto error; } /* Set DirectDraw Cooperative level, ie what control we want over Windows * display */ dxresult = IDirectDraw2_SetCooperativeLevel( p_vout->p_sys->p_ddobject, NULL, DDSCL_NORMAL ); if( dxresult != DD_OK ) { msg_Err( p_vout, "cannot set direct draw cooperative level" ); goto error; } /* Get the size of the current display device */ if( p_vout->p_sys->hmonitor && p_vout->p_sys->GetMonitorInfo ) { MONITORINFO monitor_info; monitor_info.cbSize = sizeof( MONITORINFO ); p_vout->p_sys->GetMonitorInfo( p_vout->p_sys->hmonitor, &monitor_info ); p_vout->p_sys->rect_display = monitor_info.rcMonitor; } else { p_vout->p_sys->rect_display.left = 0; p_vout->p_sys->rect_display.top = 0; p_vout->p_sys->rect_display.right = GetSystemMetrics(SM_CXSCREEN); p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN); } msg_Dbg( p_vout, "screen dimensions (%ix%i,%ix%i)", p_vout->p_sys->rect_display.left, p_vout->p_sys->rect_display.top, p_vout->p_sys->rect_display.right, p_vout->p_sys->rect_display.bottom ); /* Probe the capabilities of the hardware */ DirectXGetDDrawCaps( p_vout ); msg_Dbg( p_vout, "End DirectXInitDDraw" ); return VLC_SUCCESS; error: if( p_vout->p_sys->p_ddobject ) IDirectDraw2_Release( p_vout->p_sys->p_ddobject ); if( p_vout->p_sys->hddraw_dll ) FreeLibrary( p_vout->p_sys->hddraw_dll ); p_vout->p_sys->hddraw_dll = NULL; p_vout->p_sys->p_ddobject = NULL; return VLC_EGENERIC;}/***************************************************************************** * DirectXCreateDisplay: create the DirectDraw display. ***************************************************************************** * Create and initialize display according to preferences specified in the vout * thread fields. *****************************************************************************/static int DirectXCreateDisplay( vout_thread_t *p_vout ){ HRESULT dxresult; DDSURFACEDESC ddsd; LPDIRECTDRAWSURFACE p_display; msg_Dbg( p_vout, "DirectXCreateDisplay" ); /* Now get the primary surface. This surface is what you actually see * on your screen */ memset( &ddsd, 0, sizeof( DDSURFACEDESC )); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject, &ddsd, &p_display, NULL ); if( dxresult != DD_OK ) { msg_Err( p_vout, "cannot get primary surface (error %li)", dxresult ); return VLC_EGENERIC; } dxresult = IDirectDrawSurface_QueryInterface( p_display, &IID_IDirectDrawSurface2, (LPVOID *)&p_vout->p_sys->p_display ); /* Release the old interface */ IDirectDrawSurface_Release( p_display ); if ( dxresult != DD_OK ) { msg_Err( p_vout, "cannot query IDirectDrawSurface2 interface " "(error %li)", dxresult ); return VLC_EGENERIC; } /* The clipper will be used only in non-overlay mode */ DirectXCreateClipper( 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 ); /* 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 ); return VLC_SUCCESS;}/***************************************************************************** * DirectXCreateClipper: Create a clipper that will be used when blitting the * RGB surface to the main display. ***************************************************************************** * This clipper prevents us to modify by mistake anything on the screen * which doesn't belong to our window. For example when a part of our video * window is hidden by another window. *****************************************************************************/static int DirectXCreateClipper( vout_thread_t *p_vout ){ HRESULT dxresult; msg_Dbg( p_vout, "DirectXCreateClipper" ); /* Create the clipper */ dxresult = IDirectDraw2_CreateClipper( p_vout->p_sys->p_ddobject, 0, &p_vout->p_sys->p_clipper, NULL ); if( dxresult != DD_OK ) { msg_Warn( p_vout, "cannot create clipper (error %li)", dxresult ); goto error; } /* Associate the clipper to the window */ dxresult = IDirectDrawClipper_SetHWnd( p_vout->p_sys->p_clipper, 0, p_vout->p_sys->hvideownd ); if( dxresult != DD_OK ) { msg_Warn( p_vout, "cannot attach clipper to window (error %li)", dxresult ); goto error; } /* associate the clipper with the surface */ dxresult = IDirectDrawSurface_SetClipper(p_vout->p_sys->p_display, p_vout->p_sys->p_clipper); if( dxresult != DD_OK ) { msg_Warn( p_vout, "cannot attach clipper to surface (error %li)", dxresult ); goto error; } return VLC_SUCCESS; error: if( p_vout->p_sys->p_clipper ) { IDirectDrawClipper_Release( p_vout->p_sys->p_clipper ); } p_vout->p_sys->p_clipper = NULL; return VLC_EGENERIC;}/***************************************************************************** * DirectXCreateSurface: create an YUV overlay or RGB surface for the video. ***************************************************************************** * The best method of display is with an YUV overlay because the YUV->RGB * conversion is done in hardware. * You can also create a plain RGB surface. * ( Maybe we could also try an RGB overlay surface, which could have hardware * scaling and which would also be faster in window mode because you don't * need to do any blitting to the main display...) *****************************************************************************/static int DirectXCreateSurface( vout_thread_t *p_vout, LPDIRECTDRAWSURFACE2 *pp_surface_final, int i_chroma, int b_overlay, int i_backbuffers ){ HRESULT dxresult; LPDIRECTDRAWSURFACE p_surface; DDSURFACEDESC ddsd; /* Create the video surface */ if( b_overlay ) { /* Now try to create the YUV overlay surface. * This overlay will be displayed on top of the primary surface. * A color key is used to determine whether or not the overlay will be * displayed, ie the overlay will be displayed in place of the primary * surface wherever the primary surface will have this color. * The video window has been created with a background of this color so * the overlay will be only displayed on top of this window */ memset( &ddsd, 0, sizeof( DDSURFACEDESC )); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; ddsd.ddpfPixelFormat.dwFourCC = i_chroma; ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; ddsd.dwFlags |= (i_backbuffers ? DDSD_BACKBUFFERCOUNT : 0); ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY; ddsd.ddsCaps.dwCaps |= (i_backbuffers ? DDSCAPS_COMPLEX | DDSCAPS_FLIP : 0 ); ddsd.dwHeight = p_vout->render.i_height; ddsd.dwWidth = p_vout->render.i_width; ddsd.dwBackBufferCount = i_backbuffers; dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject, &ddsd, &p_surface, NULL ); if( dxresult != DD_OK )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -