[vlc-devel] [PATCH 3/5] direct3d11: handle separate pools for decoder/display/filters

Steve Lhomme robux4 at videolabs.io
Tue Mar 28 16:23:58 CEST 2017


---
 modules/video_output/win32/direct3d11.c | 164 ++++++++++++++++++++------------
 1 file changed, 102 insertions(+), 62 deletions(-)

diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index 0cac84e6ac..6b9b17ddc4 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -125,6 +125,8 @@ struct vout_display_sys_t
 {
     vout_display_sys_win32_t sys;
 
+    picture_pool_t *pools[VOUT_POOL_COUNT];
+
     struct { /* TODO may go in vout_display_info_t without DXGI */
         const dxgi_color_space   *colorspace;
         unsigned                 luminance_peak;
@@ -535,6 +537,8 @@ static int Open(vlc_object_t *object)
     video_format_Clean(&vd->fmt);
     video_format_Copy(&vd->fmt, &fmt);
 
+    vd->info.typed_pools          = true;
+    vd->info.can_display_decoder  = true;
     vd->info.has_double_click     = true;
     vd->info.has_hide_mouse       = false;
     vd->info.has_pictures_invalid = vd->info.is_slow;
@@ -658,7 +662,8 @@ static int AllocateShaderView(vout_display_t *vd, const d3d_format_t *format,
 
 static int AllocateTextures(vout_display_t *vd, const d3d_format_t *cfg,
                             video_format_t *fmt, unsigned pool_size,
-                            ID3D11Texture2D *textures[])
+                            ID3D11Texture2D *textures[],
+                            vout_display_pool_t pool_type)
 {
     vout_display_sys_t *sys = vd->sys;
     int plane;
@@ -669,33 +674,55 @@ static int AllocateTextures(vout_display_t *vd, const d3d_format_t *cfg,
     texDesc.MipLevels = 1;
     texDesc.SampleDesc.Count = 1;
     texDesc.MiscFlags = 0; //D3D11_RESOURCE_MISC_SHARED;
-    texDesc.Usage = D3D11_USAGE_DEFAULT;
-    texDesc.CPUAccessFlags = 0;
     texDesc.Format = cfg->formatTexture;
     texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+    if (pool_type == VOUT_POOL_DECODER) {
+        if (is_d3d11_opaque(fmt->i_chroma)) {
+            texDesc.BindFlags |= D3D11_BIND_DECODER;
+        }
+    } else if (is_d3d11_opaque(fmt->i_chroma)) {
+        texDesc.BindFlags |= D3D11_BIND_RENDER_TARGET;
+    }
     if (is_d3d11_opaque(fmt->i_chroma)) {
-        texDesc.BindFlags |= D3D11_BIND_DECODER;
         texDesc.Usage = D3D11_USAGE_DEFAULT;
         texDesc.CPUAccessFlags = 0;
     } else {
         texDesc.Usage = D3D11_USAGE_DYNAMIC;
         texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
     }
-    texDesc.ArraySize = pool_size;
     texDesc.Height = fmt->i_height;
     texDesc.Width = fmt->i_width;
 
-    hr = ID3D11Device_CreateTexture2D( sys->d3ddevice, &texDesc, NULL, &slicedTexture );
-    if (FAILED(hr)) {
-        msg_Err(vd, "CreateTexture2D failed for the %d pool. (hr=0x%0lx)", pool_size, hr);
-        goto error;
+    /* use only a sliced texture for the decoder pool, otherwise a texture
+     * per picture */
+    if (pool_type != VOUT_POOL_DECODER)
+        texDesc.ArraySize = 1;
+    else
+    {
+        texDesc.ArraySize = pool_size;
+        hr = ID3D11Device_CreateTexture2D( sys->d3ddevice, &texDesc, NULL, &slicedTexture );
+        if (FAILED(hr)) {
+            msg_Err(vd, "CreateTexture2D failed for the %d pool of %d textures. (hr=0x%0lx)", pool_type, pool_size, hr);
+            goto error;
+        }
     }
 
     for (unsigned picture_count = 0; picture_count < pool_size; picture_count++) {
-        textures[picture_count * D3D11_MAX_SHADER_VIEW] = slicedTexture;
-        ID3D11Texture2D_AddRef(slicedTexture);
-
-        for (plane = 1; plane < D3D11_MAX_SHADER_VIEW; plane++) {
+        for (plane = 0; plane < 1; plane++) {
+            if (!cfg->resourceFormat[plane])
+                textures[picture_count * D3D11_MAX_SHADER_VIEW + plane] = NULL;
+            else if (slicedTexture) {
+                textures[picture_count * D3D11_MAX_SHADER_VIEW + plane] = slicedTexture;
+                ID3D11Texture2D_AddRef(slicedTexture);
+            } else {
+                hr = ID3D11Device_CreateTexture2D( sys->d3ddevice, &texDesc, NULL, &textures[picture_count * D3D11_MAX_SHADER_VIEW + plane] );
+                if (FAILED(hr)) {
+                    msg_Err(vd, "CreateTexture2D failed for the %d pool of %d textures, plane %d. (hr=0x%0lx)", pool_type, pool_size, plane, hr);
+                    goto error;
+                }
+            }
+        }
+        for (; plane < D3D11_MAX_SHADER_VIEW; plane++) {
             if (!cfg->resourceFormat[plane])
                 textures[picture_count * D3D11_MAX_SHADER_VIEW + plane] = NULL;
             else
@@ -745,10 +772,14 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size, vout_display
     if (sys->sys.pool)
         return sys->sys.pool;
 
+    if (sys->pools[type] != NULL)
+        return sys->pools[type];
+
     if (vd->info.is_slow)
         pool_size = 1;
 
-    if (AllocateTextures(vd, sys->picQuadConfig, &vd->fmt, pool_size, textures))
+    if (AllocateTextures(vd, sys->picQuadConfig, &vd->fmt, pool_size, textures,
+                         type))
         goto error;
 
     if (vd->info.is_slow) {
@@ -785,7 +816,10 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size, vout_display
         for (plane = 0; plane < D3D11_MAX_SHADER_VIEW; plane++)
             picsys->texture[plane] = textures[picture_count * D3D11_MAX_SHADER_VIEW + plane];
 
-        picsys->slice_index = picture_count;
+        if (type == VOUT_POOL_DECODER)
+            picsys->slice_index = picture_count;
+        else
+            picsys->slice_index = 0;
         picsys->formatTexture = sys->picQuadConfig->formatTexture;
         picsys->context = sys->d3dcontext;
 
@@ -807,51 +841,55 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size, vout_display
     }
 
 #ifdef HAVE_ID3D11VIDEODECODER
-    if (!is_d3d11_opaque(vd->fmt.i_chroma) || sys->legacy_shader)
+    if (type == VOUT_POOL_DISPLAY)
     {
-        /* we need a staging texture */
-        video_format_t staging_fmt;
-        video_format_Copy(&staging_fmt, &vd->fmt);
-        staging_fmt.i_width = staging_fmt.i_visible_width;
-        staging_fmt.i_height = staging_fmt.i_visible_height;
-        if ( sys->picQuadConfig->formatTexture == DXGI_FORMAT_NV12 ||
-             sys->picQuadConfig->formatTexture == DXGI_FORMAT_P010 )
+        if (!is_d3d11_opaque(vd->fmt.i_chroma) || sys->legacy_shader)
         {
-            staging_fmt.i_width  = (staging_fmt.i_width  + 1) & ~1;
-            staging_fmt.i_height = (staging_fmt.i_height + 1) & ~1;
-        }
-        if (AllocateTextures(vd, sys->picQuadConfig, &staging_fmt, 1, textures))
-            goto error;
-
-        sys->picQuad.i_x_offset = 0;
-        sys->picQuad.i_y_offset = 0;
-        sys->picQuad.i_width    = staging_fmt.i_width;
-        sys->picQuad.i_height   = staging_fmt.i_height;
+            /* we need a staging texture */
+            video_format_t staging_fmt;
+            video_format_Copy(&staging_fmt, &vd->fmt);
+            staging_fmt.i_width  = staging_fmt.i_visible_width;
+            staging_fmt.i_height = staging_fmt.i_visible_height;
+            if ( sys->picQuadConfig->formatTexture == DXGI_FORMAT_NV12 ||
+                 sys->picQuadConfig->formatTexture == DXGI_FORMAT_P010 )
+            {
+                staging_fmt.i_width  = (staging_fmt.i_width  + 1) & ~1;
+                staging_fmt.i_height = (staging_fmt.i_height + 1) & ~1;
+            }
+            if (AllocateTextures(vd, sys->picQuadConfig, &staging_fmt, 1, textures, type))
+                goto error;
 
-        for (unsigned plane = 0; plane < D3D11_MAX_SHADER_VIEW; plane++)
-            sys->stagingSys.texture[plane] = textures[plane];
+            sys->picQuad.i_x_offset = 0;
+            sys->picQuad.i_y_offset = 0;
+            sys->picQuad.i_width    = staging_fmt.i_width;
+            sys->picQuad.i_height   = staging_fmt.i_height;
 
-        if (AllocateShaderView(vd, sys->picQuadConfig, 0, &sys->stagingSys))
-            goto error;
-    } else
-#endif
-    {
-        sys->picQuad.i_x_offset = vd->fmt.i_x_offset;
-        sys->picQuad.i_y_offset = vd->fmt.i_y_offset;
-        sys->picQuad.i_width    = vd->fmt.i_width;
-        sys->picQuad.i_height   = vd->fmt.i_height;
+            for (unsigned plane = 0; plane < D3D11_MAX_SHADER_VIEW; plane++)
+                sys->stagingSys.texture[plane] = textures[plane];
 
-        for (picture_count = 0; picture_count < pool_size; picture_count++) {
-            if (AllocateShaderView(vd, sys->picQuadConfig, picture_count, pictures[picture_count]->p_sys))
+            if (AllocateShaderView(vd, sys->picQuadConfig, 0, &sys->stagingSys))
                 goto error;
         }
-    }
+        else
+        {
+            sys->picQuad.i_x_offset = vd->fmt.i_x_offset;
+            sys->picQuad.i_y_offset = vd->fmt.i_y_offset;
+            sys->picQuad.i_width    = vd->fmt.i_width;
+            sys->picQuad.i_height   = vd->fmt.i_height;
+
+            for (picture_count = 0; picture_count < pool_size; picture_count++) {
+                if (AllocateShaderView(vd, sys->picQuadConfig, picture_count, pictures[picture_count]->p_sys))
+                    goto error;
+            }
+        }
 
-    if (SetupQuad( vd, &vd->fmt, &sys->picQuad, sys->picQuadConfig, sys->picQuadPixelShader,
-                   vd->fmt.projection_mode) != VLC_SUCCESS) {
-        msg_Err(vd, "Could not Create the main quad picture.");
-        return NULL;
+        if (SetupQuad( vd, &vd->fmt, &sys->picQuad, sys->picQuadConfig, sys->picQuadPixelShader,
+                       vd->fmt.projection_mode) != VLC_SUCCESS) {
+            msg_Err(vd, "Could not Create the main quad picture.");
+            return NULL;
+        }
     }
+#endif
 
     if (vd->info.is_slow) {
         pool_cfg.lock          = Direct3D11MapPoolTexture;
@@ -859,25 +897,21 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size, vout_display
     }
     pool_cfg.picture       = pictures;
     pool_cfg.picture_count = pool_size;
-    sys->sys.pool = picture_pool_NewExtended( &pool_cfg );
+    sys->pools[type] = picture_pool_NewExtended( &pool_cfg );
 
 error:
-    if (sys->sys.pool == NULL) {
+    if (sys->pools[type] == NULL) {
         if (pictures) {
             msg_Dbg(vd, "Failed to create the picture d3d11 pool");
             for (unsigned i=0;i<picture_count; ++i)
                 picture_Release(pictures[i]);
             free(pictures);
         }
-
-        /* create an empty pool to avoid crashing */
-        pool_cfg.picture_count = 0;
-        sys->sys.pool = picture_pool_NewExtended( &pool_cfg );
     } else {
-        msg_Dbg(vd, "ID3D11VideoDecoderOutputView succeed with %d surfaces (%dx%d) context 0x%p",
-                picture_count, vd->fmt.i_width, vd->fmt.i_height, sys->d3dcontext);
+        msg_Dbg(vd, "pool[%d] succeed with %d surfaces (%dx%d) context 0x%p",
+                type, picture_count, vd->fmt.i_width, vd->fmt.i_height, sys->d3dcontext);
     }
-    return sys->sys.pool;
+    return sys->pools[type];
 }
 
 static void ReleasePictureResources(picture_sys_t *p_sys)
@@ -2249,9 +2283,15 @@ static void Direct3D11DestroyPool(vout_display_t *vd)
 {
     vout_display_sys_t *sys = vd->sys;
 
+    if (sys->pools[VOUT_POOL_DISPLAY])
+        picture_pool_Release(sys->pools[VOUT_POOL_DISPLAY]);
+    for (int i=0;i<VOUT_POOL_COUNT; ++i)
+        sys->pools[i] = NULL;
     if (sys->sys.pool)
+    {
         picture_pool_Release(sys->sys.pool);
-    sys->sys.pool = NULL;
+        sys->sys.pool = NULL;
+    }
 }
 
 static void SetupQuadFlat(d3d_vertex_t *dst_data, const video_format_t *fmt, d3d_quad_t *quad, WORD *triangle_pos)
@@ -2767,7 +2807,7 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
             if (unlikely(d3dquad==NULL)) {
                 continue;
             }
-            if (AllocateTextures(vd, sys->d3dregion_format, &r->fmt, 1, textures)) {
+            if (AllocateTextures(vd, sys->d3dregion_format, &r->fmt, 1, textures, VOUT_POOL_DISPLAY)) {
                 msg_Err(vd, "Failed to allocate %dx%d texture for OSD",
                         r->fmt.i_visible_width, r->fmt.i_visible_height);
                 for (int i=0; i<D3D11_MAX_SHADER_VIEW; i++)
-- 
2.11.1



More information about the vlc-devel mailing list