direct3d9: factorize the code that is always common with local/host rendering

The clear/begin/end scene is always done on our local IDirect3DDevice9. No need
to force the host to do it a second time.
This commit is contained in:
Steve Lhomme 2019-06-11 15:39:58 +02:00
parent cfaa0bdfe6
commit 303cbe6c89
2 changed files with 43 additions and 98 deletions

View File

@ -45,48 +45,6 @@ struct CUSTOMVERTEX {FLOAT X, Y, Z, RHW; DWORD COLOR;
FLOAT tu, tv; /* texture relative coordinates */};
#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)
/**
* Callback called just before VLC starts drawing the video.
*
* Set the surface VLC will render to (could be the backbuffer if nothing else
* needs to be displayed). And then call BeginScene().
*
* This is called outside of the UI thread (in the VLC rendering thread).
*/
static bool StartRender(struct render_context *ctx)
{
HRESULT hr;
hr = IDirect3DDevice9_SetRenderTarget(ctx->libvlc_d3d, 0, ctx->sharedRenderSurface);
if (FAILED(hr)) return false;
/* clear the vlc destination texture to black alternatively */
hr = IDirect3DDevice9_Clear(ctx->libvlc_d3d, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
if (FAILED(hr)) return false;
hr = IDirect3DDevice9_BeginScene(ctx->libvlc_d3d);
if (hr == D3DERR_DEVICENOTRESET)
{
/* TODO reset the device, this may not work with hardware decoding */
return false;
}
if (FAILED(hr)) return false;
return true;
}
/**
* Callback called after VLC has finished drawing the video.
*
* This is called outside of the UI thread (in the VLC rendering thread).
*/
static void EndRender(struct render_context *ctx)
{
IDirect3DDevice9_EndScene(ctx->libvlc_d3d);
IDirect3DDevice9_Present(ctx->libvlc_d3d, NULL, NULL, NULL, NULL);
}
/**
* Callback called when it's time to display the video, in sync with the audio.
*
@ -173,6 +131,9 @@ static bool Resize(struct render_context *ctx, unsigned width, unsigned height,
if (FAILED(hr))
return false;
hr = IDirect3DDevice9_SetRenderTarget(ctx->libvlc_d3d, 0, ctx->sharedRenderSurface);
if (FAILED(hr)) return false;
out->surface_format = d3ddm.Format;
out->full_range = true;
out->colorspace = libvlc_video_colorspace_BT709;
@ -286,15 +247,27 @@ static void Swap_cb( void* opaque )
Swap( ctx );
}
/**
* Callback called just before VLC starts/finishes drawing the video.
*
* Set the surface VLC will render to (could be the backbuffer if nothing else
* needs to be displayed). And then call BeginScene().
*
* This is called outside of the UI thread (in the VLC rendering thread).
*/
static bool StartRendering_cb( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 )
{
struct render_context *ctx = opaque;
if ( enter )
{
return StartRender( ctx );
/* we already set the RenderTarget on the IDirect3DDevice9 */
return true;
}
EndRender( ctx );
/* VLC has finished preparing drawning on our surface, we need do the drawing now
so the surface is finished rendering when Swap() is called to do our own
rendering */
IDirect3DDevice9_Present(ctx->libvlc_d3d, NULL, NULL, NULL, NULL);
return true;
}

View File

@ -1167,44 +1167,6 @@ static int Direct3D9RenderRegion(vout_display_t *vd,
return 0;
}
static bool StartRendering(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
IDirect3DDevice9 *d3ddev = sys->d3d_dev.dev;
HRESULT hr;
if (sys->clear_scene) {
/* Clear the backbuffer and the zbuffer */
hr = IDirect3DDevice9_Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
if (FAILED(hr)) {
msg_Dbg(vd, "Failed Clear: 0x%lX", hr);
return false;
}
sys->clear_scene = false;
}
// Begin the scene
hr = IDirect3DDevice9_BeginScene(d3ddev);
if (FAILED(hr)) {
msg_Dbg(vd, "Failed BeginScene: 0x%lX", hr);
return false;
}
return true;
}
static void EndRendering(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
IDirect3DDevice9 *d3ddev = sys->d3d_dev.dev;
HRESULT hr;
// End the scene
hr = IDirect3DDevice9_EndScene(d3ddev);
if (FAILED(hr))
msg_Dbg(vd, "Failed EndScene: 0x%lX", hr);
}
/**
* It renders the scene.
*
@ -1218,10 +1180,28 @@ static void Direct3D9RenderScene(vout_display_t *vd,
{
vout_display_sys_t *sys = vd->sys;
IDirect3DDevice9 *d3ddev = sys->d3d_dev.dev;
HRESULT hr;
if (!sys->startEndRenderingCb( sys->outside_opaque, true, NULL ))
if (sys->startEndRenderingCb && !sys->startEndRenderingCb( sys->outside_opaque, true, NULL ))
return;
if (sys->clear_scene) {
/* Clear the backbuffer and the zbuffer */
hr = IDirect3DDevice9_Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
if (FAILED(hr)) {
msg_Dbg(vd, "Failed Clear: 0x%lX", hr);
return;
}
sys->clear_scene = false;
}
hr = IDirect3DDevice9_BeginScene(d3ddev);
if (FAILED(hr)) {
msg_Dbg(vd, "Failed BeginScene: 0x%lX", hr);
return;
}
Direct3D9RenderRegion(vd, picture, true);
if (subpicture_count)
@ -1235,7 +1215,12 @@ static void Direct3D9RenderScene(vout_display_t *vd,
IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHABLENDENABLE, FALSE);
}
sys->startEndRenderingCb( sys->outside_opaque, false, NULL );
hr = IDirect3DDevice9_EndScene(d3ddev);
if (FAILED(hr))
msg_Dbg(vd, "Failed EndScene: 0x%lX", hr);
if (sys->startEndRenderingCb)
sys->startEndRenderingCb( sys->outside_opaque, false, NULL );
}
static void Prepare(vout_display_t *vd, picture_t *picture,
@ -1648,19 +1633,6 @@ static void LocalSwapchainSwap( void *opaque )
Swap( vd );
}
static bool LocalSwapchainStartEndRendering( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *p_hdr10 )
{
VLC_UNUSED(p_hdr10);
vout_display_t *vd = opaque;
if ( enter )
{
return StartRendering( vd );
}
EndRendering( vd );
return true;
}
/**
* It creates a Direct3D vout display.
*/
@ -1711,7 +1683,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
sys->cleanupDeviceCb = LocalSwapchainCleanupDevice;
sys->updateOutputCb = LocalSwapchainUpdateOutput;
sys->swapCb = LocalSwapchainSwap;
sys->startEndRenderingCb = LocalSwapchainStartEndRendering;
sys->startEndRenderingCb = NULL;
}
libvlc_video_direct3d_device_cfg_t surface_cfg = {