From cf16b6f0e7b45856a80943050553935b6f4de943 Mon Sep 17 00:00:00 2001 From: Steve Lhomme <robux4@ycbcr.xyz> Date: Thu, 9 May 2019 14:13:59 +0200 Subject: [PATCH] libvlc: use a callback to select the plane to render to When rendering in Direct3D11 to NV12 we use 2 planes in the same texture. --- doc/libvlc/d3d11_player.cpp | 11 ++++++++++- doc/libvlc/d3d9_player.c | 2 +- include/vlc/libvlc_media_player.h | 20 ++++++++++++++++++++ lib/media_player.c | 3 +++ modules/video_output/win32/d3d11_quad.c | 9 ++++----- modules/video_output/win32/d3d11_quad.h | 4 +++- modules/video_output/win32/direct3d11.c | 25 +++++++++++++++++++++---- 7 files changed, 62 insertions(+), 12 deletions(-) diff --git a/doc/libvlc/d3d11_player.cpp b/doc/libvlc/d3d11_player.cpp index bf262fce72ac..a739730455a6 100644 --- a/doc/libvlc/d3d11_player.cpp +++ b/doc/libvlc/d3d11_player.cpp @@ -172,6 +172,15 @@ static bool StartRendering_cb( void *opaque, bool enter, const libvlc_video_dire return true; } +static bool SelectPlane_cb( void *opaque, size_t plane ) +{ + struct render_context *ctx = static_cast<struct render_context *>( opaque ); + if ( plane != 0 ) // we only support one packed RGBA plane (DXGI_FORMAT_R8G8B8A8_UNORM) + return false; + ctx->d3dctx->OMSetRenderTargets( 1, &ctx->textureRenderTarget, NULL ); + return true; +} + static bool Setup_cb( void **opaque, const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out ) { struct render_context *ctx = static_cast<struct render_context *>(*opaque); @@ -442,7 +451,7 @@ int WINAPI WinMain(HINSTANCE hInstance, /* Tell VLC to render into our D3D11 environment */ libvlc_video_direct3d_set_callbacks( p_mp, libvlc_video_direct3d_engine_d3d11, - Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, + Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, SelectPlane_cb, &Context ); libvlc_media_player_play( p_mp ); diff --git a/doc/libvlc/d3d9_player.c b/doc/libvlc/d3d9_player.c index de6d54d901f8..043fca777fb7 100644 --- a/doc/libvlc/d3d9_player.c +++ b/doc/libvlc/d3d9_player.c @@ -349,7 +349,7 @@ int WINAPI WinMain(HINSTANCE hInstance, /* Tell VLC to render into our D3D9 environment */ libvlc_video_direct3d_set_callbacks( p_mp, libvlc_video_direct3d_engine_d3d9, - Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, + Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, NULL, &Context ); libvlc_media_player_play( p_mp ); diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h index 18bb03e0b00e..f10fcf7a9623 100644 --- a/include/vlc/libvlc_media_player.h +++ b/include/vlc/libvlc_media_player.h @@ -742,6 +742,25 @@ typedef struct */ typedef bool( *libvlc_video_direct3d_start_end_rendering_cb )( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 ); +/** Tell the host the rendering for the given plane is about to start + * + * \param opaque private pointer set on the opaque parameter of @a libvlc_video_direct3d_device_setup_cb() [IN] + * \param plane number of the rendering plane to select + * \return true on success + * \version LibVLC 4.0.0 or later + * + * \note This is only used with \ref libvlc_video_direct3d_engine_d3d11. + * + * The host should call OMSetRenderTargets for Direct3D11. If this callback is + * not used (set to NULL in @a libvlc_video_direct3d_set_callbacks()) OMSetRenderTargets + * has to be set during the @a libvlc_video_direct3d_start_end_rendering_cb() + * entering call. + * + * The number of planes depend on the DXGI_FORMAT returned during the + * \ref LIBVLC_VIDEO_UPDATE_OUTPUT call. It's usually one plane except for + * semi-planar formats like DXGI_FORMAT_NV12 or DXGI_FORMAT_P010. + */ +typedef bool( *libvlc_video_direct3d_select_plane_cb )( void *opaque, size_t plane ); /** * Set callbacks and data to render decoded video to a custom Direct3D output @@ -770,6 +789,7 @@ int libvlc_video_direct3d_set_callbacks( libvlc_media_player_t *mp, libvlc_video_direct3d_update_output_cb update_output_cb, libvlc_video_swap_cb swap_cb, libvlc_video_direct3d_start_end_rendering_cb makeCurrent_cb, + libvlc_video_direct3d_select_plane_cb select_plane_cb, void* opaque ); /** diff --git a/lib/media_player.c b/lib/media_player.c index 1172055a1423..fb18da1893aa 100644 --- a/lib/media_player.c +++ b/lib/media_player.c @@ -646,6 +646,7 @@ libvlc_media_player_new( libvlc_instance_t *instance ) var_Create( mp, "vout-cb-swap", VLC_VAR_ADDRESS ); var_Create( mp, "vout-cb-get-proc-address", VLC_VAR_ADDRESS ); var_Create( mp, "vout-cb-make-current", VLC_VAR_ADDRESS ); + var_Create( mp, "vout-cb-select-plane", VLC_VAR_ADDRESS ); var_Create (mp, "avcodec-hw", VLC_VAR_STRING); var_Create (mp, "drawable-xid", VLC_VAR_INTEGER); @@ -1209,6 +1210,7 @@ int libvlc_video_direct3d_set_callbacks( libvlc_media_player_t *mp, libvlc_video_direct3d_update_output_cb update_output_cb, libvlc_video_swap_cb swap_cb, libvlc_video_direct3d_start_end_rendering_cb makeCurrent_cb, + libvlc_video_direct3d_select_plane_cb select_plane_cb, void* opaque ) { var_SetString( mp, "window", "wdummy"); @@ -1232,6 +1234,7 @@ int libvlc_video_direct3d_set_callbacks( libvlc_media_player_t *mp, var_SetAddress( mp, "vout-cb-update-output", update_output_cb ); var_SetAddress( mp, "vout-cb-swap", swap_cb ); var_SetAddress( mp, "vout-cb-make-current", makeCurrent_cb ); + var_SetAddress( mp, "vout-cb-select-plane", select_plane_cb ); return 1; } diff --git a/modules/video_output/win32/d3d11_quad.c b/modules/video_output/win32/d3d11_quad.c index d51781fc967f..9ee7661027a2 100644 --- a/modules/video_output/win32/d3d11_quad.c +++ b/modules/video_output/win32/d3d11_quad.c @@ -44,7 +44,7 @@ void D3D11_RenderQuad(d3d11_device_t *d3d_dev, d3d_quad_t *quad, d3d_vshader_t *vsshader, ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW], - ID3D11RenderTargetView *d3drenderTargetView[D3D11_MAX_RENDER_TARGET]) + d3d11_select_plane_t selectPlane, void *selectOpaque) { UINT offset = 0; @@ -73,14 +73,13 @@ void D3D11_RenderQuad(d3d11_device_t *d3d_dev, d3d_quad_t *quad, d3d_vshader_t * if (!quad->d3dpixelShader[i]) break; + if (unlikely(!selectPlane(selectOpaque, i))) + continue; + ID3D11DeviceContext_PSSetShader(d3d_dev->d3dcontext, quad->d3dpixelShader[i], NULL, 0); ID3D11DeviceContext_RSSetViewports(d3d_dev->d3dcontext, 1, &quad->cropViewport[i]); - if (d3drenderTargetView[0]) - /* TODO: handle outside selection of the render sub-target */ - ID3D11DeviceContext_OMSetRenderTargets(d3d_dev->d3dcontext, 1, &d3drenderTargetView[i], NULL); - ID3D11DeviceContext_DrawIndexed(d3d_dev->d3dcontext, quad->indexCount, 0, 0); } diff --git a/modules/video_output/win32/d3d11_quad.h b/modules/video_output/win32/d3d11_quad.h index 3e8e82b59a6a..b0d04aef7ec5 100644 --- a/modules/video_output/win32/d3d11_quad.h +++ b/modules/video_output/win32/d3d11_quad.h @@ -45,9 +45,11 @@ typedef struct d3d_vertex_t { } texture; } d3d_vertex_t; +typedef bool (*d3d11_select_plane_t)(void *opaque, size_t plane_index); + void D3D11_RenderQuad(d3d11_device_t *, d3d_quad_t *, d3d_vshader_t *, ID3D11ShaderResourceView *resourceViews[D3D11_MAX_SHADER_VIEW], - ID3D11RenderTargetView *renderTarget[D3D11_MAX_RENDER_TARGET]); + d3d11_select_plane_t selectPlane, void *selectOpaque); int D3D11_AllocateQuad(vlc_object_t *, d3d11_device_t *, video_projection_mode_t, d3d_quad_t *); #define D3D11_AllocateQuad(a,b,c,d) D3D11_AllocateQuad(VLC_OBJECT(a),b,c,d) diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c index bbe525d3e79b..d0bd833ab791 100644 --- a/modules/video_output/win32/direct3d11.c +++ b/modules/video_output/win32/direct3d11.c @@ -169,6 +169,7 @@ struct vout_display_sys_t libvlc_video_direct3d_update_output_cb updateOutputCb; libvlc_video_swap_cb swapCb; libvlc_video_direct3d_start_end_rendering_cb startEndRenderingCb; + libvlc_video_direct3d_select_plane_cb selectPlaneCb; }; static picture_pool_t *Pool(vout_display_t *, unsigned); @@ -636,6 +637,16 @@ static bool LocalSwapchainStartEndRendering( void *opaque, bool enter, const lib return true; } +static bool LocalSwapchainSelectPlane( void *opaque, size_t plane ) +{ + struct d3d11_local_swapchain *display = opaque; + if (!display->swapchainTargetView[plane]) + return false; + ID3D11DeviceContext_OMSetRenderTargets(display->d3d_dev.d3dcontext, 1, + &display->swapchainTargetView[plane], NULL); + return true; +} + static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg, video_format_t *fmtp, vlc_video_context *context) { @@ -668,6 +679,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg, sys->updateOutputCb = var_InheritAddress( vd, "vout-cb-update-output" ); sys->swapCb = var_InheritAddress( vd, "vout-cb-swap" ); sys->startEndRenderingCb = var_InheritAddress( vd, "vout-cb-make-current" ); + sys->selectPlaneCb = var_InheritAddress( vd, "vout-cb-select-plane" ); if ( sys->setupDeviceCb == NULL || sys->swapCb == NULL || sys->startEndRenderingCb == NULL || sys->updateOutputCb == NULL ) { @@ -680,6 +692,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg, sys->updateOutputCb = LocalSwapchainUpdateOutput; sys->swapCb = LocalSwapchainSwap; sys->startEndRenderingCb = LocalSwapchainStartEndRendering; + sys->selectPlaneCb = LocalSwapchainSelectPlane; #if VLC_WINSTORE_APP /* LEGACY, the d3dcontext and swapchain were given by the host app */ @@ -957,6 +970,12 @@ static int Control(vout_display_t *vd, int query, va_list args) return res; } +static bool SelectRenderPlane(void *opaque, size_t plane) +{ + vout_display_sys_t *sys = opaque; + return sys->selectPlaneCb(sys->outside_opaque, plane); +} + static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture) { vout_display_sys_t *sys = vd->sys; @@ -1069,8 +1088,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t } D3D11_RenderQuad(&sys->d3d_dev, &sys->picQuad, vd->source.projection_mode == PROJECTION_MODE_RECTANGULAR ? &sys->flatVShader : &sys->projectionVShader, - renderSrc, - sys->internal_swapchain.swapchainTargetView); /* NULL with external rendering */ + renderSrc, SelectRenderPlane, sys); if (subpicture) { // draw the additional vertices @@ -1079,8 +1097,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t { d3d_quad_t *quad = (d3d_quad_t *) sys->d3dregions[i]->p_sys; D3D11_RenderQuad(&sys->d3d_dev, quad, &sys->flatVShader, - quad->picSys.renderSrc, - sys->internal_swapchain.swapchainTargetView); /* NULL with external rendering */ + quad->picSys.renderSrc, SelectRenderPlane, sys); } } } -- GitLab