[vlc-devel] [PATCH 3/9] d3d11: allow more than one texture per picture
Steve Lhomme
robux4 at videolabs.io
Fri Feb 10 14:08:30 CET 2017
This way we can have a custom I420 with a texture for each plane
---
modules/codec/avcodec/d3d11va.c | 26 +++++-----
modules/video_chroma/d3d11_fmt.h | 8 ++-
modules/video_chroma/d3d11_surface.c | 8 +--
modules/video_output/win32/direct3d11.c | 92 +++++++++++++++++++--------------
4 files changed, 76 insertions(+), 58 deletions(-)
diff --git a/modules/codec/avcodec/d3d11va.c b/modules/codec/avcodec/d3d11va.c
index c33f77c..414ad08 100644
--- a/modules/codec/avcodec/d3d11va.c
+++ b/modules/codec/avcodec/d3d11va.c
@@ -252,7 +252,7 @@ static int Extract(vlc_va_t *va, picture_t *output, uint8_t *data)
{
picture_sys_t *p_sys_out = output->p_sys;
- assert(p_sys_out->texture != NULL);
+ assert(p_sys_out->texture[KNOWN_DXGI_INDEX] != NULL);
#ifdef ID3D11VideoContext_VideoProcessorBlt
if (sys->videoProcessor)
@@ -272,7 +272,7 @@ static int Extract(vlc_va_t *va, picture_t *output, uint8_t *data)
};
HRESULT hr = ID3D11VideoDevice_CreateVideoProcessorOutputView((ID3D11VideoDevice*) sys->dx_sys.d3ddec,
- p_sys_out->resource,
+ p_sys_out->resource[KNOWN_DXGI_INDEX],
sys->procEnumerator,
&outDesc,
(ID3D11VideoProcessorOutputView**) &p_sys_out->decoder);
@@ -319,15 +319,15 @@ done:
ID3D11VideoDecoderOutputView_GetDesc( src, &viewDesc );
D3D11_TEXTURE2D_DESC dstDesc;
- ID3D11Texture2D_GetDesc( p_sys_out->texture, &dstDesc);
+ ID3D11Texture2D_GetDesc( p_sys_out->texture[KNOWN_DXGI_INDEX], &dstDesc);
/* copy decoder slice to surface */
D3D11_BOX copyBox = {
.right = dstDesc.Width, .bottom = dstDesc.Height, .back = 1,
};
- ID3D11DeviceContext_CopySubresourceRegion(sys->d3dctx, p_sys_out->resource,
+ ID3D11DeviceContext_CopySubresourceRegion(sys->d3dctx, p_sys_out->resource[KNOWN_DXGI_INDEX],
p_sys_out->slice_index, 0, 0, 0,
- p_sys_in->resource,
+ p_sys_in->resource[KNOWN_DXGI_INDEX],
viewDesc.Texture2D.ArraySlice,
©Box);
if( sys->context_mutex != INVALID_HANDLE_VALUE ) {
@@ -386,7 +386,7 @@ static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
viewDesc.Texture2D.ArraySlice = p_sys->slice_index;
hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( (ID3D11VideoDevice*) dx_sys->d3ddec,
- (ID3D11Resource*) p_sys->texture,
+ p_sys->resource[KNOWN_DXGI_INDEX],
&viewDesc,
&p_sys->decoder );
if (FAILED(hr)) {
@@ -494,9 +494,9 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
sys->d3dvidctx = d3dvidctx;
sys->b_extern_pool = true;
- assert(p_sys->texture != NULL);
+ assert(p_sys->texture[KNOWN_DXGI_INDEX] != NULL);
D3D11_TEXTURE2D_DESC dstDesc;
- ID3D11Texture2D_GetDesc( p_sys->texture, &dstDesc);
+ ID3D11Texture2D_GetDesc( p_sys->texture[KNOWN_DXGI_INDEX], &dstDesc);
sys->render = dstDesc.Format;
}
}
@@ -1026,7 +1026,7 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma
}
D3D11_TEXTURE2D_DESC texDesc;
- ID3D11Texture2D_GetDesc(pic->p_sys->texture, &texDesc);
+ ID3D11Texture2D_GetDesc(pic->p_sys->texture[KNOWN_DXGI_INDEX], &texDesc);
if (texDesc.ArraySize < dx_sys->surface_count)
{
msg_Warn(va, "not enough decoding slices in the texture (%d/%d)",
@@ -1049,7 +1049,7 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma
viewDesc.Texture2D.ArraySlice = pic->p_sys->slice_index;
hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( (ID3D11VideoDevice*) dx_sys->d3ddec,
- pic->p_sys->resource,
+ pic->p_sys->resource[KNOWN_DXGI_INDEX],
&viewDesc,
&pic->p_sys->decoder );
if (FAILED(hr)) {
@@ -1208,7 +1208,7 @@ static void DxDestroySurfaces(vlc_va_t *va)
static void DestroyPicture(picture_t *picture)
{
picture_sys_t *p_sys = picture->p_sys;
- ID3D11Texture2D_Release( p_sys->texture );
+ ID3D11Texture2D_Release( p_sys->texture[KNOWN_DXGI_INDEX] );
if (p_sys->inputView)
ID3D11View_Release( (ID3D11View*) p_sys->inputView );
@@ -1229,7 +1229,7 @@ static picture_t *DxAllocPicture(vlc_va_t *va, const video_format_t *fmt, unsign
return NULL;
pic_sys->decoder = (ID3D11VideoDecoderOutputView*) sys->dx_sys.hw_surface[index];
- ID3D11VideoDecoderOutputView_GetResource(pic_sys->decoder, &pic_sys->resource);
+ ID3D11VideoDecoderOutputView_GetResource(pic_sys->decoder, &pic_sys->resource[KNOWN_DXGI_INDEX]);
pic_sys->context = sys->d3dctx;
if (sys->procEnumerator)
@@ -1242,7 +1242,7 @@ static picture_t *DxAllocPicture(vlc_va_t *va, const video_format_t *fmt, unsign
};
HRESULT hr = ID3D11VideoDevice_CreateVideoProcessorInputView((ID3D11VideoDevice*) sys->dx_sys.d3ddec,
- pic_sys->resource,
+ pic_sys->resource[KNOWN_DXGI_INDEX],
sys->procEnumerator,
&inDesc,
&pic_sys->inputView);
diff --git a/modules/video_chroma/d3d11_fmt.h b/modules/video_chroma/d3d11_fmt.h
index 7db8bc3..caea919 100644
--- a/modules/video_chroma/d3d11_fmt.h
+++ b/modules/video_chroma/d3d11_fmt.h
@@ -32,8 +32,8 @@ struct picture_sys_t
{
ID3D11VideoDecoderOutputView *decoder; /* may be NULL for pictures from the pool */
union {
- ID3D11Texture2D *texture;
- ID3D11Resource *resource;
+ ID3D11Texture2D *texture[D3D11_MAX_SHADER_VIEW];
+ ID3D11Resource *resource[D3D11_MAX_SHADER_VIEW];
};
ID3D11DeviceContext *context;
unsigned slice_index;
@@ -42,4 +42,8 @@ struct picture_sys_t
DXGI_FORMAT formatTexture;
};
+/* index to use for texture/resource that use a known DXGI format
+ * (ie not DXGI_FORMAT_UNKNWON) */
+#define KNOWN_DXGI_INDEX 0
+
#endif /* include-guard */
diff --git a/modules/video_chroma/d3d11_surface.c b/modules/video_chroma/d3d11_surface.c
index 65227a3..36974d8 100644
--- a/modules/video_chroma/d3d11_surface.c
+++ b/modules/video_chroma/d3d11_surface.c
@@ -70,7 +70,7 @@ static int assert_staging(filter_t *p_filter, picture_sys_t *p_sys)
goto ok;
D3D11_TEXTURE2D_DESC texDesc;
- ID3D11Texture2D_GetDesc( p_sys->texture, &texDesc);
+ ID3D11Texture2D_GetDesc( p_sys->texture[KNOWN_DXGI_INDEX], &texDesc);
texDesc.MipLevels = 1;
//texDesc.SampleDesc.Count = 1;
@@ -113,7 +113,8 @@ static void D3D11_YUY2(filter_t *p_filter, picture_t *src, picture_t *dst)
ID3D11DeviceContext_CopySubresourceRegion(p_sys->context, sys->staging_resource,
0, 0, 0, 0,
- p_sys->resource, viewDesc.Texture2D.ArraySlice,
+ p_sys->resource[KNOWN_DXGI_INDEX],
+ viewDesc.Texture2D.ArraySlice,
NULL);
HRESULT hr = ID3D11DeviceContext_Map(p_sys->context, sys->staging_resource,
@@ -194,7 +195,8 @@ static void D3D11_NV12(filter_t *p_filter, picture_t *src, picture_t *dst)
ID3D11DeviceContext_CopySubresourceRegion(p_sys->context, sys->staging_resource,
0, 0, 0, 0,
- p_sys->resource, viewDesc.Texture2D.ArraySlice,
+ p_sys->resource[KNOWN_DXGI_INDEX],
+ viewDesc.Texture2D.ArraySlice,
NULL);
HRESULT hr = ID3D11DeviceContext_Map(p_sys->context, sys->staging_resource,
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index 5b99416..69c5a81 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -633,9 +633,8 @@ static int AllocateShaderView(vout_display_t *vd, const d3d_format_t *format,
{
HRESULT hr;
vout_display_sys_t *sys = vd->sys;
- D3D11_SHADER_RESOURCE_VIEW_DESC resviewDesc = {
- .Format = format->resourceFormat[0],
- };
+ int i;
+ D3D11_SHADER_RESOURCE_VIEW_DESC resviewDesc = { 0 };
if (sys->legacy_shader)
{
@@ -649,31 +648,33 @@ static int AllocateShaderView(vout_display_t *vd, const d3d_format_t *format,
resviewDesc.Texture2DArray.ArraySize = 1;
resviewDesc.Texture2DArray.FirstArraySlice = slice_index;
}
- hr = ID3D11Device_CreateShaderResourceView(sys->d3ddevice, picsys->resource, &resviewDesc, &picsys->resourceView[0]);
- if (FAILED(hr)) {
- msg_Err(vd, "Could not Create the Y/RGB Texture ResourceView slice %d. (hr=0x%lX)", slice_index, hr);
- goto error;
+ for (i=0; i<D3D11_MAX_SHADER_VIEW; i++)
+ {
+ if (!picsys->texture[i])
+ picsys->resourceView[i] = NULL;
+ else
+ {
+ resviewDesc.Format = format->resourceFormat[i];
+ hr = ID3D11Device_CreateShaderResourceView(sys->d3ddevice, picsys->resource[i], &resviewDesc, &picsys->resourceView[i]);
+ if (FAILED(hr)) {
+ msg_Err(vd, "Could not Create the Texture ResourceView %d slice %d. (hr=0x%lX)", i, slice_index, hr);
+ break;
+ }
+ }
}
- picsys->resourceView[1] = NULL;
- if( format->resourceFormat[1] )
+ if (i != D3D11_MAX_SHADER_VIEW)
{
- resviewDesc.Format = format->resourceFormat[1];
- hr = ID3D11Device_CreateShaderResourceView(sys->d3ddevice, picsys->resource, &resviewDesc, &picsys->resourceView[1]);
- if (FAILED(hr)) {
- msg_Err(vd, "Could not Create the UV Texture ResourceView slice %d. (hr=0x%lX)", slice_index, hr);
- goto error;
+ while (i >= 0)
+ {
+ ID3D11ShaderResourceView_Release(picsys->resourceView[i]);
+ picsys->resourceView[i] = NULL;
+ i--;
}
+ return VLC_EGENERIC;
}
return VLC_SUCCESS;
-error:
- if (picsys->resourceView[0]) {
- ID3D11ShaderResourceView_Release(picsys->resourceView[0]);
- picsys->resourceView[0] = NULL;
- }
- picsys->resourceView[1] = NULL;
- return VLC_EGENERIC;
}
static int AllocateTextures(vout_display_t *vd, const d3d_format_t *cfg,
@@ -743,6 +744,7 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
#ifdef HAVE_ID3D11VIDEODECODER
picture_t** pictures = NULL;
unsigned picture_count = 0;
+ unsigned plane;
ID3D11Texture2D *textures[pool_size * D3D11_MAX_SHADER_VIEW];
HRESULT hr;
@@ -765,7 +767,8 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
if (unlikely(picsys == NULL))
goto error;
- picsys->texture = textures[picture_count];
+ for (plane = 0; plane < D3D11_MAX_SHADER_VIEW; plane++)
+ picsys->texture[plane] = textures[picture_count * D3D11_MAX_SHADER_VIEW + plane];
if (AllocateShaderView(vd, sys->picQuadConfig, picture_count, picsys) != VLC_SUCCESS)
goto error;
@@ -827,9 +830,9 @@ static void DestroyDisplayPoolPicture(picture_t *picture)
for (int i=0; i<D3D11_MAX_SHADER_VIEW; i++) {
if (p_sys->resourceView[i])
ID3D11ShaderResourceView_Release(p_sys->resourceView[i]);
+ if (p_sys->texture[i])
+ ID3D11Texture2D_Release(p_sys->texture[i]);
}
- if (p_sys->texture)
- ID3D11Texture2D_Release(p_sys->texture);
if (p_sys->context)
ID3D11DeviceContext_Release(p_sys->context);
@@ -1138,7 +1141,7 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
picture_sys_pool_t *p_psys = (picture_sys_pool_t*)picture->p_sys;
Direct3D11UnmapPoolTexture(picture);
ID3D11DeviceContext_CopySubresourceRegion(sys->d3dcontext,
- sys->picQuad.picSys.resource,
+ sys->picQuad.picSys.resource[KNOWN_DXGI_INDEX],
0, 0, 0, 0,
(ID3D11Resource*) p_psys->texture,
0, NULL);
@@ -1152,9 +1155,9 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
WaitForSingleObjectEx( sys->context_lock, INFINITE, FALSE );
}
ID3D11DeviceContext_CopySubresourceRegion(sys->d3dcontext,
- sys->picQuad.picSys.resource,
+ sys->picQuad.picSys.resource[KNOWN_DXGI_INDEX],
0, 0, 0, 0,
- p_sys->resource,
+ p_sys->resource[KNOWN_DXGI_INDEX],
p_sys->slice_index, NULL);
if ( sys->context_lock != INVALID_HANDLE_VALUE)
ReleaseMutex( sys->context_lock );
@@ -1865,7 +1868,7 @@ static int Direct3D11CreatePool(vout_display_t *vd, video_format_t *fmt)
if (unlikely(poolsys == NULL)) {
return VLC_ENOMEM;
}
- poolsys->texture = sys->picQuad.picSys.texture;
+ poolsys->texture = sys->picQuad.picSys.texture[KNOWN_DXGI_INDEX];
poolsys->vd = vd;
picture_resource_t resource = {
@@ -2236,18 +2239,27 @@ static int AllocQuad(vout_display_t *vd, const video_format_t *fmt, d3d_quad_t *
texDesc.Height &= ~1;
}
- hr = ID3D11Device_CreateTexture2D(sys->d3ddevice, &texDesc, NULL, &quad->picSys.texture);
+ hr = ID3D11Device_CreateTexture2D(sys->d3ddevice, &texDesc, NULL, &quad->picSys.texture[KNOWN_DXGI_INDEX]);
if (FAILED(hr)) {
msg_Err(vd, "Could not Create the D3d11 Texture. (hr=0x%lX)", hr);
goto error;
}
+ for (int i=KNOWN_DXGI_INDEX+1; i<D3D11_MAX_SHADER_VIEW; i++) {
+ if (!cfg->resourceFormat[i])
+ quad->picSys.texture[i] = NULL;
+ else
+ {
+ quad->picSys.texture[i] = quad->picSys.texture[KNOWN_DXGI_INDEX];
+ ID3D11Texture2D_AddRef(quad->picSys.texture[i]);
+ }
+ }
- hr = ID3D11DeviceContext_Map(sys->d3dcontext, quad->picSys.resource, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ hr = ID3D11DeviceContext_Map(sys->d3dcontext, quad->picSys.resource[KNOWN_DXGI_INDEX], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( FAILED(hr) ) {
msg_Err(vd, "The texture cannot be mapped. (hr=0x%lX)", hr);
goto error;
}
- ID3D11DeviceContext_Unmap(sys->d3dcontext, quad->picSys.resource, 0);
+ ID3D11DeviceContext_Unmap(sys->d3dcontext, quad->picSys.resource[KNOWN_DXGI_INDEX], 0);
if (mappedResource.RowPitch < p_chroma_desc->pixel_size * texDesc.Width) {
msg_Err( vd, "The texture row pitch is too small (%d instead of %d)", mappedResource.RowPitch,
p_chroma_desc->pixel_size * texDesc.Width );
@@ -2308,12 +2320,12 @@ static void ReleaseQuad(d3d_quad_t *quad)
ID3D11Buffer_Release(quad->pVertexShaderConstants);
quad->pVertexShaderConstants = NULL;
}
- if (quad->picSys.texture)
- {
- ID3D11Texture2D_Release(quad->picSys.texture);
- quad->picSys.texture = NULL;
- }
for (int i=0; i<D3D11_MAX_SHADER_VIEW; i++) {
+ if (quad->picSys.texture[i])
+ {
+ ID3D11Texture2D_Release(quad->picSys.texture[i]);
+ quad->picSys.texture[i] = NULL;
+ }
if (quad->picSys.resourceView[i])
{
ID3D11ShaderResourceView_Release(quad->picSys.resourceView[i]);
@@ -2438,8 +2450,8 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
for (int j = 0; j < sys->d3dregion_count; j++) {
picture_t *cache = sys->d3dregions[j];
- if (cache != NULL && ((d3d_quad_t *) cache->p_sys)->picSys.texture) {
- ID3D11Texture2D_GetDesc( ((d3d_quad_t *) cache->p_sys)->picSys.texture, &texDesc );
+ if (cache != NULL && ((d3d_quad_t *) cache->p_sys)->picSys.texture[KNOWN_DXGI_INDEX]) {
+ ID3D11Texture2D_GetDesc( ((d3d_quad_t *) cache->p_sys)->picSys.texture[KNOWN_DXGI_INDEX], &texDesc );
if (texDesc.Format == sys->d3dregion_format->formatTexture &&
texDesc.Width == r->fmt.i_visible_width &&
texDesc.Height == r->fmt.i_visible_height) {
@@ -2478,7 +2490,7 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
quad_picture = (*region)[i];
}
- hr = ID3D11DeviceContext_Map(sys->d3dcontext, ((d3d_quad_t *) quad_picture->p_sys)->picSys.resource, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ hr = ID3D11DeviceContext_Map(sys->d3dcontext, ((d3d_quad_t *) quad_picture->p_sys)->picSys.resource[KNOWN_DXGI_INDEX], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) ) {
err = CommonUpdatePicture(quad_picture, NULL, mappedResource.pData, mappedResource.RowPitch);
if (err != VLC_SUCCESS) {
@@ -2489,7 +2501,7 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
picture_CopyPixels(quad_picture, r->p_picture);
- ID3D11DeviceContext_Unmap(sys->d3dcontext, ((d3d_quad_t *) quad_picture->p_sys)->picSys.resource, 0);
+ ID3D11DeviceContext_Unmap(sys->d3dcontext, ((d3d_quad_t *) quad_picture->p_sys)->picSys.resource[KNOWN_DXGI_INDEX], 0);
} else {
msg_Err(vd, "Failed to map the SPU texture (hr=0x%lX)", hr );
picture_Release(quad_picture);
--
2.10.2
More information about the vlc-devel
mailing list