Tearing - possible solution for D3D video output
Posted: 11 Jun 2009 16:04
This is about a possible solution for the tearing problem in full screen on Windows XP with "DirectX 3D video output" selected. It applies only to Direct3D output.
The test video can be downloaded from the link below, it's been transcoded and cut from a DVD. Tearing starts to appear on my computer at second 28, when the camera starts panning.
http://www.4shared.com/file/110658515/b ... nline.html
The only way I can play this test video (and others) without tearing in fullscreen on my computer is with VLC 0.9.9a compiled with the changes described below, or with Media Player Classic Home Cinema with "Lock back-buffer" checked.
My comp: XP SP3, E8400 3.6GHz, 2GB, ATI Radeon HD 3870, Catalyst 9.4 (VSync enabled or not, no difference), 24 inch LCD, 1920 x 1200, 60Hz
I have tearing on this video with all official releases of VLC on my computer (0.9.9a, 1.0.0rc1 to rc3). Other players, based on DirectShow like GOM Player also show some tearing, although it seems to be less.
I've cross compiled VLC (0.9.9a sources) on Ubuntu with the changes described below. Only the direct3d.c file is changed, so only the libdirect3d_plugin.dll is changed.
If anyone else experiences tearing on Direct3D output and can make a build with the changes below, please post here if these changes helped or made anything worse. If anyone wants to try the custom build I've made, you can download it here:
http://www.4shared.com/file/111190410/7 ... uffer.html
It's a self extracting archive made with 7zip, scanned with AVG 8.5, perhaps you should scan it too after downloading. It's not a good "production" build, some features were stripped from the makefiles, the goal of this build is only to test the tearing with D3D video output.
Below are the changes I've made in the direct3d.c file.
The structure for creating the D3DDevice, in the Direct3DFillPresentationParameters function:
In Direct3DVoutRenderScene, before this line:
add the following lines:
This means that before obtaining the destination surface to paint the frame to (the p_d3ddest pointer), first make the backbuffer to be the render target. There should be only one backbuffer if the above settings were used in Direct3DFillPresentationParameters. I haven't yet tested with more backbuffers and I don't really know if more of them would do anything better (for 24 - 30 fps video, one backbuffer should be enough I suppose...)
At the end of the Direct3DVoutRenderScene function, right after the EndScene block, add:
(Not sure about memory leaks in this code, msdn says p_back_buffer obtained as above should be released at some point... Also, both GetBackBuffer and SetRenderTarget should be result-checked.)
All that these changes are doing are the same thing that Media Player Classic Home Cinema does on VMR9 renderless output, with 3D surfaces selected and the "Lock back-buffer" option checked. This applies to MPC-HC version 1.2.908.
I'd like to know if anyone else has the same tearing problem and if this solution solved it.
The test video can be downloaded from the link below, it's been transcoded and cut from a DVD. Tearing starts to appear on my computer at second 28, when the camera starts panning.
http://www.4shared.com/file/110658515/b ... nline.html
The only way I can play this test video (and others) without tearing in fullscreen on my computer is with VLC 0.9.9a compiled with the changes described below, or with Media Player Classic Home Cinema with "Lock back-buffer" checked.
My comp: XP SP3, E8400 3.6GHz, 2GB, ATI Radeon HD 3870, Catalyst 9.4 (VSync enabled or not, no difference), 24 inch LCD, 1920 x 1200, 60Hz
I have tearing on this video with all official releases of VLC on my computer (0.9.9a, 1.0.0rc1 to rc3). Other players, based on DirectShow like GOM Player also show some tearing, although it seems to be less.
I've cross compiled VLC (0.9.9a sources) on Ubuntu with the changes described below. Only the direct3d.c file is changed, so only the libdirect3d_plugin.dll is changed.
If anyone else experiences tearing on Direct3D output and can make a build with the changes below, please post here if these changes helped or made anything worse. If anyone wants to try the custom build I've made, you can download it here:
http://www.4shared.com/file/111190410/7 ... uffer.html
It's a self extracting archive made with 7zip, scanned with AVG 8.5, perhaps you should scan it too after downloading. It's not a good "production" build, some features were stripped from the makefiles, the goal of this build is only to test the tearing with D3D video output.
Below are the changes I've made in the direct3d.c file.
The structure for creating the D3DDevice, in the Direct3DFillPresentationParameters function:
Code: Select all
ZeroMemory( d3dpp, sizeof(D3DPRESENT_PARAMETERS) );
d3dpp->Flags = D3DPRESENTFLAG_VIDEO | D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; //needed for locking/unlocking the backbuffer at the end of Direct3DVoutRenderScene
d3dpp->Windowed = TRUE; //always windowed, it's never really a D3D fullscreen app
d3dpp->hDeviceWindow = p_vout->p_sys->hvideownd;
d3dpp->BackBufferWidth = d3ddm.Width; //the backbuffer will always be the size of the screen if set like this (any problems?)
d3dpp->BackBufferHeight = d3ddm.Height; //the backbuffer will always be the size of the screen if set like this (any problems?)
d3dpp->SwapEffect = D3DSWAPEFFECT_COPY; //always copy, never flip, since the device is always in windowed mode
d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
Code: Select all
hr = IDirect3DTexture9_GetSurfaceLevel(p_d3dtex, 0, &p_d3ddest);
Code: Select all
//set the back buffer surface to be the current render target
LPDIRECT3DSURFACE9 p_back_buffer;
IDirect3DDevice9_GetBackBuffer(p_d3ddev, 0, 0, D3DBACKBUFFER_TYPE_MONO, &p_back_buffer);
IDirect3DDevice9_SetRenderTarget(p_d3ddev, 0, p_back_buffer);
At the end of the Direct3DVoutRenderScene function, right after the EndScene block, add:
Code: Select all
D3DLOCKED_RECT locked_rect;
if(SUCCEEDED(IDirect3DSurface9_LockRect(p_back_buffer, &locked_rect, NULL, 0)))
IDirect3DSurface9_UnlockRect(p_back_buffer);
All that these changes are doing are the same thing that Media Player Classic Home Cinema does on VMR9 renderless output, with 3D surfaces selected and the "Lock back-buffer" option checked. This applies to MPC-HC version 1.2.908.
I'd like to know if anyone else has the same tearing problem and if this solution solved it.