📄 direct3d.c
字号:
*****************************************************************************/static int Direct3DVoutResetDevice( vout_thread_t *p_vout ){ LPDIRECT3DDEVICE9 p_d3ddev = p_vout->p_sys->p_d3ddev; D3DPRESENT_PARAMETERS d3dpp; HRESULT hr; if( VLC_SUCCESS != Direct3DFillPresentationParameters(p_vout, &d3dpp) ) return VLC_EGENERIC; // release all D3D objects Direct3DVoutReleaseScene( p_vout ); Direct3DVoutReleasePictures( p_vout ); hr = IDirect3DDevice9_Reset(p_d3ddev, &d3dpp); if( SUCCEEDED(hr) ) { // re-create them if( (VLC_SUCCESS != Direct3DVoutCreatePictures(p_vout, 1)) || (VLC_SUCCESS != Direct3DVoutCreateScene(p_vout)) ) { msg_Dbg(p_vout, "%s failed !", __FUNCTION__); return VLC_EGENERIC; } } else { msg_Err(p_vout, "%s failed ! (hr=%08lX)", __FUNCTION__, hr); return VLC_EGENERIC; } return VLC_SUCCESS;}static D3DFORMAT Direct3DVoutSelectFormat( vout_thread_t *p_vout, D3DFORMAT target, const D3DFORMAT *formats, size_t count){ LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj; size_t c; for( c=0; c<count; ++c ) { HRESULT hr; D3DFORMAT format = formats[c]; /* test whether device can create a surface of that format */ hr = IDirect3D9_CheckDeviceFormat(p_d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, target, 0, D3DRTYPE_SURFACE, format); if( SUCCEEDED(hr) ) { /* test whether device can perform color-conversion ** from that format to target format */ hr = IDirect3D9_CheckDeviceFormatConversion(p_d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, format, target); } if( SUCCEEDED(hr) ) { // found a compatible format switch( format ) { case D3DFMT_UYVY: msg_Dbg( p_vout, "selected surface pixel format is UYVY"); break; case D3DFMT_YUY2: msg_Dbg( p_vout, "selected surface pixel format is YUY2"); break; case D3DFMT_X8R8G8B8: msg_Dbg( p_vout, "selected surface pixel format is X8R8G8B8"); break; case D3DFMT_A8R8G8B8: msg_Dbg( p_vout, "selected surface pixel format is A8R8G8B8"); break; case D3DFMT_R8G8B8: msg_Dbg( p_vout, "selected surface pixel format is R8G8B8"); break; case D3DFMT_R5G6B5: msg_Dbg( p_vout, "selected surface pixel format is R5G6B5"); break; case D3DFMT_X1R5G5B5: msg_Dbg( p_vout, "selected surface pixel format is X1R5G5B5"); break; default: msg_Dbg( p_vout, "selected surface pixel format is 0x%0X", format); break; } return format; } else if( D3DERR_NOTAVAILABLE != hr ) { msg_Err( p_vout, "Could not query adapter supported formats. (hr=0x%lX)", hr); break; } } return D3DFMT_UNKNOWN;}static D3DFORMAT Direct3DVoutFindFormat(vout_thread_t *p_vout, int i_chroma, D3DFORMAT target){ //if( p_vout->p_sys->b_hw_yuv && ! _got_vista_or_above ) if( p_vout->p_sys->b_hw_yuv ) { /* it sounds like vista does not support YUV surfaces at all */ switch( i_chroma ) { case VLC_FOURCC('U','Y','V','Y'): case VLC_FOURCC('U','Y','N','V'): case VLC_FOURCC('Y','4','2','2'): { static const D3DFORMAT formats[] = { D3DFMT_UYVY, D3DFMT_YUY2, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 }; return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT)); } case VLC_FOURCC('I','4','2','0'): case VLC_FOURCC('I','4','2','2'): case VLC_FOURCC('Y','V','1','2'): { /* typically 3D textures don't support planar format ** fallback to packed version and use CPU for the conversion */ static const D3DFORMAT formats[] = { D3DFMT_YUY2, D3DFMT_UYVY, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 }; return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT)); } case VLC_FOURCC('Y','U','Y','2'): case VLC_FOURCC('Y','U','N','V'): { static const D3DFORMAT formats[] = { D3DFMT_YUY2, D3DFMT_UYVY, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 }; return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT)); } } } switch( i_chroma ) { case VLC_FOURCC('R', 'V', '1', '5'): { static const D3DFORMAT formats[] = { D3DFMT_X1R5G5B5 }; return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT)); } case VLC_FOURCC('R', 'V', '1', '6'): { static const D3DFORMAT formats[] = { D3DFMT_R5G6B5 }; return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT)); } case VLC_FOURCC('R', 'V', '2', '4'): { static const D3DFORMAT formats[] = { D3DFMT_R8G8B8, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8 }; return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT)); } case VLC_FOURCC('R', 'V', '3', '2'): { static const D3DFORMAT formats[] = { D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }; return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT)); } default: { /* use display default format */ LPDIRECT3D9 p_d3dobj = p_vout->p_sys->p_d3dobj; D3DDISPLAYMODE d3ddm; HRESULT hr = IDirect3D9_GetAdapterDisplayMode(p_d3dobj, D3DADAPTER_DEFAULT, &d3ddm ); if( SUCCEEDED(hr)) { /* ** some professional cards could use some advanced pixel format as default, ** make sure we stick with chromas that we can handle internally */ switch( d3ddm.Format ) { case D3DFMT_R8G8B8: case D3DFMT_X8R8G8B8: case D3DFMT_A8R8G8B8: case D3DFMT_R5G6B5: case D3DFMT_X1R5G5B5: msg_Dbg( p_vout, "defaulting to adapter pixel format"); return Direct3DVoutSelectFormat(p_vout, target, &d3ddm.Format, 1); default: { /* if we fall here, that probably means that we need to render some YUV format */ static const D3DFORMAT formats[] = { D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5 }; msg_Dbg( p_vout, "defaulting to built-in pixel format"); return Direct3DVoutSelectFormat(p_vout, target, formats, sizeof(formats)/sizeof(D3DFORMAT)); } } } } } return D3DFMT_UNKNOWN;}static int Direct3DVoutSetOutputFormat(vout_thread_t *p_vout, D3DFORMAT format){ switch( format ) { case D3DFMT_YUY2: p_vout->output.i_chroma = VLC_FOURCC('Y', 'U', 'Y', '2'); break; case D3DFMT_UYVY: p_vout->output.i_chroma = VLC_FOURCC('U', 'Y', 'V', 'Y'); break; case D3DFMT_R8G8B8: p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '2', '4'); p_vout->output.i_rmask = 0xff0000; p_vout->output.i_gmask = 0x00ff00; p_vout->output.i_bmask = 0x0000ff; break; case D3DFMT_X8R8G8B8: case D3DFMT_A8R8G8B8: p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '3', '2'); p_vout->output.i_rmask = 0x00ff0000; p_vout->output.i_gmask = 0x0000ff00; p_vout->output.i_bmask = 0x000000ff; break; case D3DFMT_R5G6B5: p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '1', '6'); p_vout->output.i_rmask = (0x1fL)<<11; p_vout->output.i_gmask = (0x3fL)<<5; p_vout->output.i_bmask = (0x1fL)<<0; break; case D3DFMT_X1R5G5B5: p_vout->output.i_chroma = VLC_FOURCC('R', 'V', '1', '5'); p_vout->output.i_rmask = (0x1fL)<<10; p_vout->output.i_gmask = (0x1fL)<<5; p_vout->output.i_bmask = (0x1fL)<<0; break; default: return VLC_EGENERIC; } return VLC_SUCCESS;}/***************************************************************************** * Direct3DVoutCreatePictures: allocate a vector of identical pictures ***************************************************************************** * Each picture has an associated offscreen surface in video memory * depending on hardware capabilities the picture chroma will be as close * as possible to the orginal render chroma to reduce CPU conversion overhead * and delegate this work to video card GPU *****************************************************************************/static int Direct3DVoutCreatePictures( vout_thread_t *p_vout, size_t i_num_pics ){ LPDIRECT3DDEVICE9 p_d3ddev = p_vout->p_sys->p_d3ddev; D3DFORMAT format; HRESULT hr; size_t c; // if vout is already running, use current chroma, otherwise choose from upstream int i_chroma = p_vout->output.i_chroma ? : p_vout->render.i_chroma; I_OUTPUTPICTURES = 0; /* ** find the appropriate D3DFORMAT for the render chroma, the format will be the closest to ** the requested chroma which is usable by the hardware in an offscreen surface, as they ** typically support more formats than textures */ format = Direct3DVoutFindFormat(p_vout, i_chroma, p_vout->p_sys->bbFormat); if( VLC_SUCCESS != Direct3DVoutSetOutputFormat(p_vout, format) ) { msg_Err(p_vout, "surface pixel format is not supported."); return VLC_EGENERIC; } for( c=0; c<i_num_pics; ) { LPDIRECT3DSURFACE9 p_d3dsurf; picture_t *p_pic = p_vout->p_picture+c; hr = IDirect3DDevice9_CreateOffscreenPlainSurface(p_d3ddev, p_vout->render.i_width, p_vout->render.i_height, format, D3DPOOL_DEFAULT, &p_d3dsurf, NULL); if( FAILED(hr) ) { msg_Err(p_vout, "Failed to create picture surface. (hr=0x%lx)", hr); Direct3DVoutReleasePictures(p_vout); return VLC_EGENERIC; } /* fill surface with black color */ IDirect3DDevice9_ColorFill(p_d3ddev, p_d3dsurf, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0) ); /* assign surface to internal structure */ p_pic->p_sys = (void *)p_d3dsurf; /* Now that we've got our direct-buffer, we can finish filling in the * picture_t structures */ switch( p_vout->output.i_chroma ) { case VLC_FOURCC('R','G','B','2'): p_pic->p->i_lines = p_vout->output.i_height; p_pic->p->i_visible_lines = p_vout->output.i_height; p_pic->p->i_pixel_pitch = 1; p_pic->p->i_visible_pitch = p_vout->output.i_width * p_pic->p->i_pixel_pitch; p_pic->i_planes = 1; break; case VLC_FOURCC('R','V','1','5'): case VLC_FOURCC('R','V','1','6'): p_pic->p->i_lines = p_vout->output.i_height; p_pic->p->i_visible_lines = p_vout->output.i_height; p_pic->p->i_pixel_pitch = 2; p_pic->p->i_visible_pitch = p_vout->output.i_width * p_pic->p->i_pixel_pitch; p_pic->i_planes = 1; break; case VLC_FOURCC('R','V','2','4'): p_pic->p->i_lines = p_vout->output.i_height; p_pic->p->i_visible_lines = p_vout->output.i_height; p_pic->p->i_pixel_pitch = 3; p_pic->p->i_visible_pitch = p_vout->output.i_width * p_pic->p->i_pixel_pitch; p_pic->i_planes = 1; break; case VLC_FOURCC('R','V','3','2'): p_pic->p->i_lines = p_vout->output.i_height; p_pic->p->i_visible_lines = p_vout->output.i_height; p_pic->p->i_pixel_pitch = 4; p_pic->p->i_visible_pitch = p_vout->output.i_width * p_pic->p->i_pixel_pitch; p_pic->i_planes = 1; break; case VLC_FOURCC('U','Y','V','Y'): case VLC_FOURCC('Y','U','Y','2'): p_pic->p->i_lines = p_vout->output.i_height; p_pic->p->i_visible_lines = p_vout->output.i_height; p_pic->p->i_pixel_pitch = 2; p_pic->p->i_visible_pitch = p_vout->output.i_width * p_pic->p->i_pixel_pitch; p_pic->i_planes = 1; break; default: Direct3DVoutReleasePictures(p_vout); return VLC_EGENERIC; } p_pic->i_status = DESTROYED_PICTURE; p_pic->i_type = DIRECT_PICTURE; p_pic->b_slow = true; p_pic->pf_lock = Direct3DVoutLockSurface; p_pic->pf_unlock = Direct3DVoutUnlockSurface; PP_OUTPUTPICTURE[c] = p_pic; I_OUTPUTPICTURES = ++c; } msg_Dbg( p_vout, "%u Direct3D pictures created successfully", c ); return VLC_SUCCESS;}/***************************************************************************** * Direct3DVoutReleasePictures: destroy a picture vector ***************************************************************************** * release all video resources used for pictures *****************************************************************************/static void Direct3DVoutReleasePictures( vout_thread_t *p_vout){ size_t i_num_pics = I_OUTPUTPICTURES; size_t c; for( c=0; c<i_num_pics; ++c ) { picture_t *p_pic = p_vout->p_picture+c; if( p_pic->p_sys ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -