[vlc-devel] [PATCH 4/4] direct3d11: support decoding I420 directly into GPU memory

Steve Lhomme robux4 at videolabs.io
Fri Feb 10 15:12:21 CET 2017


We still need a GPU copy to be able to render it.
---
 modules/video_chroma/dxgi_fmt.c         |  13 +-
 modules/video_chroma/dxgi_fmt.h         |   2 +-
 modules/video_output/win32/direct3d11.c | 333 +++++++++++++++++++++++++-------
 3 files changed, 270 insertions(+), 78 deletions(-)

diff --git a/modules/video_chroma/dxgi_fmt.c b/modules/video_chroma/dxgi_fmt.c
index 9fbf702..8154bef 100644
--- a/modules/video_chroma/dxgi_fmt.c
+++ b/modules/video_chroma/dxgi_fmt.c
@@ -66,10 +66,10 @@ static const dxgi_format_t dxgi_formats[] = {
 };
 
 static const d3d_format_t d3d_formats[] = {
-    { "NV12",     DXGI_FORMAT_NV12,           VLC_CODEC_NV12,              8, 2, 2, { DXGI_FORMAT_R8_UNORM,       DXGI_FORMAT_R8G8_UNORM } },
-    { "VA_NV12",  DXGI_FORMAT_NV12,           VLC_CODEC_D3D11_OPAQUE,      8, 2, 2, { DXGI_FORMAT_R8_UNORM,       DXGI_FORMAT_R8G8_UNORM } },
-    { "P010",     DXGI_FORMAT_P010,           VLC_CODEC_P010,             10, 2, 2, { DXGI_FORMAT_R16_UNORM,      DXGI_FORMAT_R16G16_UNORM } },
-    { "VA_P010",  DXGI_FORMAT_P010,           VLC_CODEC_D3D11_OPAQUE_10B, 10, 2, 2, { DXGI_FORMAT_R16_UNORM,      DXGI_FORMAT_R16G16_UNORM } },
+    { "NV12",     DXGI_FORMAT_NV12,           VLC_CODEC_NV12,              8, 2, 2, { DXGI_FORMAT_R8_UNORM,  DXGI_FORMAT_R8G8_UNORM } },
+    { "VA_NV12",  DXGI_FORMAT_NV12,           VLC_CODEC_D3D11_OPAQUE,      8, 2, 2, { DXGI_FORMAT_R8_UNORM,  DXGI_FORMAT_R8G8_UNORM } },
+    { "P010",     DXGI_FORMAT_P010,           VLC_CODEC_P010,             10, 2, 2, { DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16G16_UNORM } },
+    { "VA_P010",  DXGI_FORMAT_P010,           VLC_CODEC_D3D11_OPAQUE_10B, 10, 2, 2, { DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16G16_UNORM } },
     { "YUY2",     DXGI_FORMAT_YUY2,           VLC_CODEC_YUYV,              8, 2, 2, { DXGI_FORMAT_R8G8B8A8_UNORM } },
 #ifdef BROKEN_PIXEL
     { "AYUV",     DXGI_FORMAT_AYUV,           VLC_CODEC_YUVA,          8, 1, 1, { DXGI_FORMAT_R8G8B8A8_UNORM } },
@@ -78,8 +78,9 @@ static const d3d_format_t d3d_formats[] = {
 #ifdef UNTESTED
     { "Y210",     DXGI_FORMAT_Y210,           VLC_CODEC_I422_10L,     10, 2, 1, { DXGI_FORMAT_R16G16B16A16_UNORM } },
     { "Y410",     DXGI_FORMAT_Y410,           VLC_CODEC_I444,         10, 1, 1, { DXGI_FORMAT_R10G10B10A2_UNORM } },
-    { "NV11",     DXGI_FORMAT_NV11,           VLC_CODEC_I411,          8, 4, 1, { DXGI_FORMAT_R8_UNORM,           DXGI_FORMAT_R8G8_UNORM} },
+    { "NV11",     DXGI_FORMAT_NV11,           VLC_CODEC_I411,          8, 4, 1, { DXGI_FORMAT_R8_UNORM,      DXGI_FORMAT_R8G8_UNORM} },
 #endif
+    { "I420",     DXGI_FORMAT_UNKNOWN,        VLC_CODEC_I420,          8, 2, 2, { DXGI_FORMAT_R8_UNORM,      DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM } },
     { "R8G8B8A8", DXGI_FORMAT_R8G8B8A8_UNORM, VLC_CODEC_RGBA,          8, 1, 1, { DXGI_FORMAT_R8G8B8A8_UNORM } },
     { "VA_RGBA",  DXGI_FORMAT_R8G8B8A8_UNORM, VLC_CODEC_D3D11_OPAQUE,  8, 1, 1, { DXGI_FORMAT_R8G8B8A8_UNORM } },
     { "B8G8R8A8", DXGI_FORMAT_B8G8R8A8_UNORM, VLC_CODEC_BGRA,          8, 1, 1, { DXGI_FORMAT_B8G8R8A8_UNORM } },
@@ -87,7 +88,7 @@ static const d3d_format_t d3d_formats[] = {
     { "R8G8B8X8", DXGI_FORMAT_B8G8R8X8_UNORM, VLC_CODEC_RGB32,         8, 1, 1, { DXGI_FORMAT_B8G8R8X8_UNORM } },
     { "B5G6R5",   DXGI_FORMAT_B5G6R5_UNORM,   VLC_CODEC_RGB16,         5, 1, 1, { DXGI_FORMAT_B5G6R5_UNORM } },
 
-    { NULL, 0, 0, 0, 0, 0, {} }
+    { NULL, 0, 0, 0, 0, 0, {0} }
 };
 
 const char *DxgiFormatToStr(DXGI_FORMAT format)
diff --git a/modules/video_chroma/dxgi_fmt.h b/modules/video_chroma/dxgi_fmt.h
index dd4abfb..add06cb 100644
--- a/modules/video_chroma/dxgi_fmt.h
+++ b/modules/video_chroma/dxgi_fmt.h
@@ -29,7 +29,7 @@
 #include <vlc_common.h>
 #include <vlc_fourcc.h>
 
-#define D3D11_MAX_SHADER_VIEW  2
+#define D3D11_MAX_SHADER_VIEW  3
 
 typedef struct
 {
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index 9bab5a9..c0ddb43 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -100,6 +100,7 @@ typedef struct
     UINT                       PSConstantsCount;
     ID3D11PixelShader         *d3dpixelShader;
     D3D11_VIEWPORT            cropViewport;
+    const vlc_chroma_description_t *p_chroma_sampling;
     unsigned int              i_x_offset;
     unsigned int              i_y_offset;
     unsigned int              i_width;
@@ -391,28 +392,118 @@ static const char *globPixelShaderBiplanarYUYV_2RGB = "\
   }\
 ";
 
-static int Direct3D11MapPoolTexture(picture_t *picture)
+
+/* for triplanar 4:2:0 source */
+static const char *globPixelShaderTriplanarI420_2RGB = "\
+  cbuffer PS_CONSTANT_BUFFER : register(b0)\
+  {\
+    float Opacity;\
+    float opacityPadding[3];\
+  };\
+  cbuffer PS_COLOR_TRANSFORM : register(b1)\
+  {\
+    float WhitePointX;\
+    float WhitePointY;\
+    float WhitePointZ;\
+    float whitePadding;\
+    float4x4 Colorspace;\
+  };\
+  Texture2D%s shaderTexture[" STRINGIZE(D3D11_MAX_SHADER_VIEW) "];\
+  SamplerState SampleType;\
+  \
+  struct PS_INPUT\
+  {\
+    float4 Position   : SV_POSITION;\
+    float4 Texture    : TEXCOORD0;\
+  };\
+  \
+  float4 PS( PS_INPUT In ) : SV_TARGET\
+  {\
+    float4 yuv;\
+    float4 rgba;\
+    yuv.x = shaderTexture[0].Sample(SampleType, In.Texture).x;\
+    yuv.y = shaderTexture[1].Sample(SampleType, In.Texture).x;\
+    yuv.z = shaderTexture[2].Sample(SampleType, In.Texture).x;\
+    yuv.a  = Opacity;\
+    yuv.x  += WhitePointX;\
+    yuv.y  += WhitePointY;\
+    yuv.z  += WhitePointZ;\
+    rgba = saturate(mul(yuv, Colorspace));\
+    return rgba;\
+  }\
+";
+
+static int Direct3D11MapPoolTexture(picture_t *picture, D3D11_MAP map_mode)
 {
     picture_sys_t *p_sys = picture->p_sys;
     D3D11_MAPPED_SUBRESOURCE mappedResource;
     HRESULT hr;
-    hr = ID3D11DeviceContext_Map(p_sys->context, p_sys->resource[KNOWN_DXGI_INDEX], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
-    if( FAILED(hr) )
+
+    if ( p_sys->formatTexture == DXGI_FORMAT_UNKNOWN )
     {
-        return VLC_EGENERIC;
+        D3D11_TEXTURE2D_DESC texDesc;
+        int i;
+        uint8_t *planes[D3D11_MAX_SHADER_VIEW];
+        unsigned pitches[D3D11_MAX_SHADER_VIEW];
+        unsigned heights[D3D11_MAX_SHADER_VIEW];
+
+        for (i = 0; i < picture->i_planes; i++) {
+            hr = ID3D11DeviceContext_Map(p_sys->context, p_sys->resource[i],
+                    0, map_mode, 0, &mappedResource);
+            if( FAILED(hr) )
+            {
+                while (i-- >= 0)
+                    ID3D11DeviceContext_Unmap(p_sys->context, p_sys->resource[i+1], 0);
+                return VLC_EGENERIC;
+            }
+            ID3D11Texture2D_GetDesc(p_sys->texture[i], &texDesc);
+            planes[i]  = mappedResource.pData;
+            pitches[i] = mappedResource.RowPitch;
+            heights[i] = texDesc.Height;
+        }
+        for (; i < D3D11_MAX_SHADER_VIEW; i++) {
+            planes[i]  = NULL;
+            pitches[i] = 0;
+            heights[i] = 0;
+        }
+        p_sys->mapped = true;
+
+        picture_SetPlanes(picture, planes, pitches, heights);
+        return VLC_SUCCESS;
     }
 
+    hr = ID3D11DeviceContext_Map(p_sys->context, p_sys->resource[KNOWN_DXGI_INDEX],
+                                 0, map_mode, 0, &mappedResource);
+    if( FAILED(hr) )
+        return VLC_EGENERIC;
     p_sys->mapped = true;
 
     return CommonUpdatePicture(picture, NULL, mappedResource.pData, mappedResource.RowPitch);
 }
 
+/* map a texture to CPU that will also be used for drawing to the swapchain */
+static int Direct3D11LockTexture(picture_t *picture)
+{
+    return Direct3D11MapPoolTexture(picture, D3D11_MAP_WRITE_DISCARD);
+}
+
+static int Direct3D11LockDirectTexture(picture_t *picture)
+{
+    return Direct3D11MapPoolTexture(picture, D3D11_MAP_WRITE);
+}
+
 static void Direct3D11UnmapPoolTexture(picture_t *picture)
 {
     picture_sys_t *p_sys = picture->p_sys;
     if (p_sys->mapped) {
-        ID3D11DeviceContext_Unmap(p_sys->context, p_sys->resource[KNOWN_DXGI_INDEX], 0);
-        p_sys->mapped = true;
+        if ( p_sys->formatTexture == DXGI_FORMAT_UNKNOWN ) {
+            for (int i = 0; i < picture->i_planes; i++) {
+                ID3D11DeviceContext_Unmap(p_sys->context, p_sys->resource[i], 0);
+            }
+        } else {
+            ID3D11DeviceContext_Unmap(p_sys->context, p_sys->resource[KNOWN_DXGI_INDEX], 0);
+        }
+        p_sys->mapped = false;
     }
 }
 
@@ -608,8 +699,14 @@ static const d3d_format_t *GetOutputFormat(vout_display_t *vd, vlc_fourcc_t i_sr
         if (!b_allow_opaque && is_d3d11_opaque(output_format->fourcc))
             continue;
 
+        DXGI_FORMAT textureFormat;
+        if (output_format->formatTexture == DXGI_FORMAT_UNKNOWN)
+            textureFormat = output_format->resourceFormat[0];
+        else
+            textureFormat = output_format->formatTexture;
+
         if( SUCCEEDED( ID3D11Device_CheckFormatSupport(sys->d3ddevice,
-                                                       output_format->formatTexture,
+                                                       textureFormat,
                                                        &i_formatSupport)) &&
                 ( i_formatSupport & i_quadSupportFlags ) == i_quadSupportFlags )
         {
@@ -671,10 +768,11 @@ 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[], bool for_shader)
 {
     vout_display_sys_t *sys = vd->sys;
-    int plane;
+    plane_t           planes[PICTURE_PLANE_MAX];
+    int plane, plane_count;
     HRESULT hr;
     ID3D11Texture2D *slicedTexture = NULL;
     D3D11_TEXTURE2D_DESC texDesc;
@@ -682,42 +780,94 @@ 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 (is_d3d11_opaque(fmt->i_chroma)) {
-        texDesc.BindFlags |= D3D11_BIND_DECODER;
-        texDesc.Usage = D3D11_USAGE_DEFAULT;
-        texDesc.CPUAccessFlags = 0;
+
+    if (cfg->formatTexture == DXGI_FORMAT_UNKNOWN) {
+        if (for_shader) {
+            const vlc_chroma_description_t *p_chroma_desc = vlc_fourcc_GetChromaDescription( fmt->i_chroma );
+
+            const int i_width_aligned  = fmt->i_width;
+            const int i_height_aligned = fmt->i_height;
+            for( unsigned i = 0; i < p_chroma_desc->plane_count; i++ )
+            {
+                plane_t *p = &planes[i];
+
+                p->i_lines         = i_height_aligned * p_chroma_desc->p[i].h.num / p_chroma_desc->p[i].h.den;
+                p->i_visible_lines = fmt->i_visible_height * p_chroma_desc->p[i].h.num / p_chroma_desc->p[i].h.den;
+                p->i_pitch         = i_width_aligned * p_chroma_desc->p[i].w.num / p_chroma_desc->p[i].w.den * p_chroma_desc->pixel_size;
+                p->i_visible_pitch = fmt->i_visible_width * p_chroma_desc->p[i].w.num / p_chroma_desc->p[i].w.den * p_chroma_desc->pixel_size;
+                p->i_pixel_pitch   = p_chroma_desc->pixel_size;
+
+            }
+            plane_count = p_chroma_desc->plane_count;
+
+            texDesc.Usage = D3D11_USAGE_DEFAULT;
+            texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+            texDesc.CPUAccessFlags = 0;
+        } else {
+            if (plane_Setup(fmt->i_chroma, fmt, planes, &plane_count) ||
+                plane_count == 0)
+            {
+                msg_Dbg(vd, "failed to get the pixel format planes for %4.4s", (char *)&fmt->i_chroma);
+                return VLC_EGENERIC;
+            }
+            texDesc.Usage = D3D11_USAGE_STAGING;
+            texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+        }
+        assert(plane_count <= D3D11_MAX_SHADER_VIEW);
+
+        texDesc.ArraySize = 1;
+        texDesc.Format = cfg->resourceFormat[0];
+        assert(cfg->resourceFormat[1] == cfg->resourceFormat[0]);
+        assert(cfg->resourceFormat[2] == cfg->resourceFormat[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;
-    /* add an extra line if needed, it will be cropped on display */
-    if (cfg->formatTexture == DXGI_FORMAT_NV12 || cfg->formatTexture == DXGI_FORMAT_P010)
-    {
-        texDesc.Width  = (texDesc.Width + 1) & ~1;
-        texDesc.Height = (texDesc.Height + 1) & ~1;
-    }
-    /* this is the actual decoding size that will be used */
-    fmt->i_height = texDesc.Height;
-    fmt->i_width = texDesc.Width;
+        plane_count = 1;
+        texDesc.Format = cfg->formatTexture;
+        texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+        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;
+        /* add an extra line if needed, it will be cropped on display */
+        if (cfg->formatTexture == DXGI_FORMAT_NV12 || cfg->formatTexture == DXGI_FORMAT_P010)
+        {
+            texDesc.Width  = (texDesc.Width + 1) & ~1;
+            texDesc.Height = (texDesc.Height + 1) & ~1;
+            /* this is the actual decoding size that will be used */
+            fmt->i_height = texDesc.Height;
+            fmt->i_width = texDesc.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;
+        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;
+        }
     }
 
     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 < plane_count; plane++)
+        {
+            if (slicedTexture) {
+                textures[picture_count * D3D11_MAX_SHADER_VIEW + plane] = slicedTexture;
+                ID3D11Texture2D_AddRef(slicedTexture);
+            } else {
+                texDesc.Height = planes[plane].i_lines;
+                texDesc.Width = planes[plane].i_pitch;
+                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. (hr=0x%0lx)", pool_size, hr);
+                    goto error;
+                }
+            }
+        }
+        for (; plane < D3D11_MAX_SHADER_VIEW; plane++) {
             if (!cfg->resourceFormat[plane])
                 textures[picture_count * D3D11_MAX_SHADER_VIEW + plane] = NULL;
             else
@@ -728,7 +878,7 @@ static int AllocateTextures(vout_display_t *vd, const d3d_format_t *cfg,
         }
     }
 
-    if (!is_d3d11_opaque(fmt->i_chroma)) {
+    if (!is_d3d11_opaque(fmt->i_chroma) && cfg->formatTexture != DXGI_FORMAT_UNKNOWN) {
         D3D11_MAPPED_SUBRESOURCE mappedResource;
         const vlc_chroma_description_t *p_chroma_desc = vlc_fourcc_GetChromaDescription( fmt->i_chroma );
 
@@ -762,7 +912,7 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
     picture_t *picture;
     unsigned  plane;
     unsigned  picture_count = 0;
-    picture_pool_configuration_t pool_cfg = {};
+    picture_pool_configuration_t pool_cfg = {0};
 
     if (sys->sys.pool)
         return sys->sys.pool;
@@ -770,22 +920,13 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
     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,
+                         sys->picQuadConfig->formatTexture != DXGI_FORMAT_UNKNOWN && is_d3d11_opaque(vd->fmt.i_chroma) && !sys->legacy_shader))
         goto error;
 
-    if (vd->info.is_slow) {
-        picture_resource_t resource = {
-            .p_sys = &sys->picQuad.picSys,
-            .pf_destroy = DestroyDisplayPoolPicture,
-        };
-
-        picture = picture_NewFromResource(&vd->fmt, &resource);
-        if (likely(picture != NULL)) {
-            pool_cfg.picture       = &picture;
-            pool_cfg.lock          = Direct3D11MapPoolTexture;
-            //pool_cfg.unlock        = Direct3D11UnmapPoolTexture;
-        }
-    } else {
+    if (is_d3d11_opaque(vd->fmt.i_chroma) || sys->picQuadConfig->formatTexture == DXGI_FORMAT_UNKNOWN)
+    {
+        /* we are going to share the context with the decoder */
         HRESULT           hr;
         ID3D10Multithread *pMultithread;
         hr = ID3D11Device_QueryInterface( sys->d3ddevice, &IID_ID3D10Multithread, (void **)&pMultithread);
@@ -828,7 +969,6 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
         ID3D11DeviceContext_AddRef(picsys->context);
     }
 
-#ifdef HAVE_ID3D11VIDEODECODER
     if (!is_d3d11_opaque(vd->fmt.i_chroma) || sys->legacy_shader)
     {
         /* we need a staging texture */
@@ -836,7 +976,7 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
         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 (AllocateTextures(vd, sys->picQuadConfig, &staging_fmt, 1, textures))
+        if (AllocateTextures(vd, sys->picQuadConfig, &staging_fmt, 1, textures, true))
             goto error;
 
         sys->picQuad.i_x_offset = 0;
@@ -844,13 +984,15 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
         sys->picQuad.i_width    = staging_fmt.i_width;
         sys->picQuad.i_height   = staging_fmt.i_height;
 
+        sys->picQuad.p_chroma_sampling = vlc_fourcc_GetChromaDescription( staging_fmt.i_chroma );
+
         for (unsigned plane = 0; plane < D3D11_MAX_SHADER_VIEW; plane++)
             sys->stagingSys.texture[plane] = textures[plane];
 
         if (AllocateShaderView(vd, sys->picQuadConfig, 0, &sys->stagingSys))
             goto error;
-    } else
-#endif
+    }
+    else
     {
         sys->picQuad.i_x_offset = vd->fmt.i_x_offset;
         sys->picQuad.i_y_offset = vd->fmt.i_y_offset;
@@ -869,8 +1011,14 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
         return NULL;
     }
 
-    if (vd->info.is_slow) {
-        pool_cfg.lock          = Direct3D11MapPoolTexture;
+    if (sys->picQuadConfig->formatTexture == DXGI_FORMAT_UNKNOWN)
+    {
+        pool_cfg.lock = Direct3D11LockDirectTexture;
+        pool_cfg.unlock = Direct3D11UnmapPoolTexture;
+    }
+    else if (vd->info.is_slow)
+    {
+        pool_cfg.lock          = Direct3D11LockTexture;
         //pool_cfg.unlock        = Direct3D11UnmapPoolTexture;
     }
     pool_cfg.picture       = pictures;
@@ -1209,21 +1357,60 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
 {
     vout_display_sys_t *sys = vd->sys;
 
-    if (!is_d3d11_opaque(picture->format.i_chroma) || sys->legacy_shader) {
+    if (picture->p_sys->formatTexture == DXGI_FORMAT_UNKNOWN)
+    {
         picture_sys_t *p_sys = picture->p_sys;
-        D3D11_TEXTURE2D_DESC texDesc;
+
+        Direct3D11UnmapPoolTexture(picture);
+        for (int plane = 0; plane < D3D11_MAX_SHADER_VIEW; plane++)
+        {
+            if (!p_sys->resource[plane])
+                continue;
+
+            unsigned int width  = sys->picQuad.i_width;
+            unsigned int height = sys->picQuad.i_height;
+            unsigned int x_offset = picture->format.i_x_offset;
+            unsigned int y_offset = picture->format.i_y_offset;
+            x_offset = x_offset * sys->picQuad.p_chroma_sampling->p[plane].h.num / sys->picQuad.p_chroma_sampling->p[plane].h.den;
+            y_offset = y_offset * sys->picQuad.p_chroma_sampling->p[plane].w.num / sys->picQuad.p_chroma_sampling->p[plane].w.den;
+            width  = width * sys->picQuad.p_chroma_sampling->p[plane].h.num / sys->picQuad.p_chroma_sampling->p[plane].h.den;
+            height = height * sys->picQuad.p_chroma_sampling->p[plane].w.num / sys->picQuad.p_chroma_sampling->p[plane].w.den;
+
+            D3D11_BOX box = {
+                .top = y_offset,
+                .bottom = y_offset + height,
+                .left = x_offset,
+                .right = x_offset + width,
+                .back = 1,
+            };
+            ID3D11DeviceContext_CopySubresourceRegion(sys->d3dcontext,
+                                                      sys->stagingSys.resource[plane],
+                                                      0, 0, 0, 0,
+                                                      p_sys->resource[plane],
+                                                      0, &box);
+        }
+    }
+    else if (!is_d3d11_opaque(picture->format.i_chroma) || sys->legacy_shader)
+    {
+        picture_sys_t *p_sys = picture->p_sys;
+#ifdef HAVE_ID3D11VIDEODECODER
         if( sys->context_lock != INVALID_HANDLE_VALUE )
         {
             WaitForSingleObjectEx( sys->context_lock, INFINITE, FALSE );
         }
+#endif
         if (!is_d3d11_opaque(picture->format.i_chroma))
             Direct3D11UnmapPoolTexture(picture);
-        ID3D11Texture2D_GetDesc(sys->stagingSys.texture[0], &texDesc);
+        unsigned int width  = sys->picQuad.i_width;
+        unsigned int height = sys->picQuad.i_height;
+        unsigned int x_offset = picture->format.i_x_offset;
+        unsigned int y_offset = picture->format.i_y_offset;
+
         D3D11_BOX box = {
-            .top = picture->format.i_y_offset,
-            .bottom = picture->format.i_y_offset + texDesc.Height,
-            .left = picture->format.i_x_offset,
-            .right = picture->format.i_x_offset + texDesc.Width,
+            .top = y_offset,
+            .bottom = y_offset + height,
+            .left = x_offset,
+            .right = x_offset + width,
             .back = 1,
         };
         ID3D11DeviceContext_CopySubresourceRegion(sys->d3dcontext,
@@ -1231,8 +1418,10 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
                                                   0, 0, 0, 0,
                                                   p_sys->resource[KNOWN_DXGI_INDEX],
                                                   p_sys->slice_index, &box);
+#ifdef HAVE_ID3D11VIDEODECODER
         if ( sys->context_lock != INVALID_HANDLE_VALUE)
             ReleaseMutex( sys->context_lock );
+#endif
     }
 
     if (subpicture) {
@@ -1379,6 +1568,8 @@ static const char *GetFormatPixelShader(const d3d_format_t *format)
     case DXGI_FORMAT_B8G8R8A8_UNORM:
     case DXGI_FORMAT_B5G6R5_UNORM:
         return globPixelShaderDefault;
+    case DXGI_FORMAT_UNKNOWN:
+        return globPixelShaderTriplanarI420_2RGB;
     default:
         return NULL;
     }
@@ -1811,7 +2002,7 @@ static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
     }
 
     sys->legacy_shader = !CanUseTextureArray(vd);
-    vd->info.is_slow = !is_d3d11_opaque(fmt->i_chroma);
+    vd->info.is_slow = !is_d3d11_opaque(fmt->i_chroma) && sys->picQuadConfig->formatTexture != DXGI_FORMAT_UNKNOWN;
 
     hr = CompilePixelShader(vd, sys->d3dPxShader, &sys->picQuadPixelShader);
     if (FAILED(hr))
@@ -2423,7 +2614,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, true)) {
                 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.10.2



More information about the vlc-devel mailing list