📄 directx.c
字号:
/* 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 ); UpdateRects( p_vout, 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 ) { *pp_surface_final = NULL; return VLC_EGENERIC; } } if( !b_overlay ) { bool b_rgb_surface = ( i_chroma == VLC_FOURCC('R','G','B','2') ) || ( i_chroma == VLC_FOURCC('R','V','1','5') ) || ( i_chroma == VLC_FOURCC('R','V','1','6') ) || ( i_chroma == VLC_FOURCC('R','V','2','4') ) || ( i_chroma == VLC_FOURCC('R','V','3','2') ); memset( &ddsd, 0, sizeof( DDSURFACEDESC ) ); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwHeight = p_vout->render.i_height; ddsd.dwWidth = p_vout->render.i_width; if( p_vout->p_sys->b_use_sysmem ) ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; else ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; if( !b_rgb_surface ) { ddsd.dwFlags |= DDSD_PIXELFORMAT; ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; ddsd.ddpfPixelFormat.dwFourCC = i_chroma; } dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject, &ddsd, &p_surface, NULL ); if( dxresult != DD_OK ) { *pp_surface_final = NULL; return VLC_EGENERIC; } } /* Now that the surface is created, try to get a newer DirectX interface */ dxresult = IDirectDrawSurface_QueryInterface( p_surface, &IID_IDirectDrawSurface2, (LPVOID *)pp_surface_final ); IDirectDrawSurface_Release( p_surface ); /* Release the old interface */ if ( dxresult != DD_OK ) { msg_Err( p_vout, "cannot query IDirectDrawSurface2 interface " "(error %li)", dxresult ); *pp_surface_final = NULL; return VLC_EGENERIC; } if( b_overlay ) { /* 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( DirectDrawUpdateOverlay( p_vout ) != VLC_SUCCESS ) { IDirectDrawSurface2_Release( *pp_surface_final ); *pp_surface_final = NULL; msg_Err( p_vout, "overlay unuseable (might already be in use)" ); return VLC_EGENERIC; } } return VLC_SUCCESS;}/***************************************************************************** * DirectDrawUpdateOverlay: Move or resize overlay surface on video display. ***************************************************************************** * This function is used to move or resize an overlay surface on the screen. * Ususally the overlay is moved by the user and thus, by a move or resize * event (in Manage). *****************************************************************************/int DirectDrawUpdateOverlay( vout_thread_t *p_vout ){ DDOVERLAYFX ddofx; DWORD dwFlags; HRESULT dxresult; RECT rect_src = p_vout->p_sys->rect_src_clipped; RECT rect_dest = p_vout->p_sys->rect_dest_clipped; 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 ) { vlc_mutex_unlock( &p_vout->p_sys->lock ); return VLC_EGENERIC; } /* The new window dimensions should already have been computed by the * caller of this function */ /* Position and show the overlay */ memset(&ddofx, 0, sizeof(DDOVERLAYFX)); ddofx.dwSize = sizeof(DDOVERLAYFX); ddofx.dckDestColorkey.dwColorSpaceLowValue = p_vout->p_sys->i_colorkey; ddofx.dckDestColorkey.dwColorSpaceHighValue = p_vout->p_sys->i_colorkey; dwFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE; dxresult = IDirectDrawSurface2_UpdateOverlay( p_vout->p_sys->p_current_surface, &rect_src, p_vout->p_sys->p_display, &rect_dest, dwFlags, &ddofx ); vlc_mutex_unlock( &p_vout->p_sys->lock ); if(dxresult != DD_OK) { msg_Warn( p_vout, "DirectDrawUpdateOverlay cannot move/resize overlay" ); return VLC_EGENERIC; } return VLC_SUCCESS;}/***************************************************************************** * DirectXCloseDDraw: Release the DDraw object allocated by DirectXInitDDraw ***************************************************************************** * This function returns all resources allocated by DirectXInitDDraw. *****************************************************************************/static void DirectXCloseDDraw( vout_thread_t *p_vout ){ msg_Dbg( p_vout, "DirectXCloseDDraw" ); if( p_vout->p_sys->p_ddobject != NULL ) { IDirectDraw2_Release(p_vout->p_sys->p_ddobject); p_vout->p_sys->p_ddobject = NULL; } if( p_vout->p_sys->hddraw_dll != NULL ) { FreeLibrary( p_vout->p_sys->hddraw_dll ); p_vout->p_sys->hddraw_dll = NULL; } free( p_vout->p_sys->p_display_driver ); p_vout->p_sys->p_display_driver = NULL; p_vout->p_sys->hmonitor = NULL;}/***************************************************************************** * DirectXCloseDisplay: close and reset the DirectX display device ***************************************************************************** * This function returns all resources allocated by DirectXCreateDisplay. *****************************************************************************/static void DirectXCloseDisplay( vout_thread_t *p_vout ){ msg_Dbg( p_vout, "DirectXCloseDisplay" ); if( p_vout->p_sys->p_clipper != NULL ) { msg_Dbg( p_vout, "DirectXCloseDisplay clipper" ); IDirectDrawClipper_Release( p_vout->p_sys->p_clipper ); p_vout->p_sys->p_clipper = NULL; } if( p_vout->p_sys->p_display != NULL ) { msg_Dbg( p_vout, "DirectXCloseDisplay display" ); IDirectDrawSurface2_Release( p_vout->p_sys->p_display ); p_vout->p_sys->p_display = NULL; }}/***************************************************************************** * DirectXCloseSurface: close the YUV overlay or RGB surface. ***************************************************************************** * This function returns all resources allocated for the surface. *****************************************************************************/static void DirectXCloseSurface( vout_thread_t *p_vout,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -