[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,
                                                       &copyBox);
             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