[vlc-devel] [PATCH 7/7] direct3d11: add 3d playback

Mohammed (Shaan) Huzaifa Danish shaan3 at gmail.com
Thu Jul 13 11:11:28 CEST 2017


From: Mohammed Danish <shaan3 at gmail.com>

This adds code for core stereo 3d files playback
---
 modules/video_output/win32/direct3d11.c | 316 ++++++++++++++++++++++++++++----
 1 file changed, 282 insertions(+), 34 deletions(-)

diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index bcc414b2ba..942eb5218b 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -98,7 +98,7 @@ typedef struct
     ID3D11Buffer              *pPixelShaderConstants[2];
     UINT                       PSConstantsCount;
     ID3D11PixelShader         *d3dpixelShader;
-    D3D11_VIEWPORT            cropViewport;
+    D3D11_VIEWPORT            cropViewport[2];
     unsigned int              i_x_offset;
     unsigned int              i_y_offset;
     unsigned int              i_width;
@@ -153,7 +153,7 @@ struct vout_display_sys_t
     DXGI_FORMAT              decoderFormat;
     picture_sys_t            stagingSys;
 
-    ID3D11RenderTargetView   *d3drenderTargetView;
+    ID3D11RenderTargetView   *d3drenderTargetView[2];
     ID3D11DepthStencilView   *d3ddepthStencilView;
 
     ID3D11VertexShader        *flatVSShader;
@@ -162,6 +162,9 @@ struct vout_display_sys_t
     /* copy from the decoder pool into picSquad before display
      * Uses a Texture2D with slices rather than a Texture2DArray for the decoder */
     bool                     legacy_shader;
+    bool                     multiview_3d;
+    bool                     device_3d_capable;
+    video_multiview_mode_t   source_3d_format;
 
     // SPU
     vlc_fourcc_t             pSubpictureChromas[2];
@@ -207,6 +210,10 @@ typedef struct {
 #define RECTWidth(r)   (int)((r).right - (r).left)
 #define RECTHeight(r)  (int)((r).bottom - (r).top)
 
+#define MONO_EYE 0
+#define LEFT_EYE MONO_EYE
+#define RIGHT_EYE 1
+
 static picture_pool_t *Pool(vout_display_t *vd, unsigned count);
 
 static void Prepare(vout_display_t *, picture_t *, subpicture_t *subpicture);
@@ -820,6 +827,75 @@ static void DestroyDisplayPoolPicture(picture_t *picture)
     free(picture);
 }
 
+static int UpdateSwapChain(vout_display_t *vd, bool switch_to_3d)
+{
+    vout_display_sys_t *sys = vd->sys;
+    IDXGIFactory2 *dxgifactory;
+    HRESULT hr = S_OK;
+
+    DXGI_SWAP_CHAIN_DESC1 scd;
+    ZeroMemory(&scd, sizeof(scd));
+    scd.BufferCount = 2;
+    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+    scd.SampleDesc.Count = 1;
+    scd.SampleDesc.Quality = 0;
+    scd.Width = vd->source.i_visible_width;
+    scd.Height = vd->source.i_visible_height;
+    scd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; /* TODO: use DXGI_FORMAT_NV12 */
+    scd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;    
+    scd.Stereo = switch_to_3d ? TRUE : FALSE;
+    scd.Scaling = DXGI_SCALING_NONE;
+    scd.Flags = 0;
+
+    IDXGIAdapter *dxgiadapter = D3D11DeviceAdapter(sys->d3ddevice);
+    if (FAILED(hr)) {
+       msg_Err(vd, "Could not get the DXGI Adapter");
+       return VLC_EGENERIC;
+    }
+
+    hr = IDXGIAdapter_GetParent(dxgiadapter, &IID_IDXGIFactory2, (void **)&dxgifactory);
+    IDXGIAdapter_Release(dxgiadapter);
+    if (FAILED(hr)) {
+       msg_Err(vd, "Could not get the DXGI Factory. (hr=0x%lX)", hr);
+       return VLC_EGENERIC;
+    }
+
+    //Release references to recreate the swapchain
+    if (sys->d3dcontext)
+    {
+        ID3D11DeviceContext_Flush(sys->d3dcontext);
+    }
+    if (sys->dxgiswapChain4)
+    {
+        IDXGISwapChain4_Release(sys->dxgiswapChain4);
+        sys->dxgiswapChain4 = NULL;
+    }
+    if (sys->dxgiswapChain)
+    {
+        IDXGISwapChain_Release(sys->dxgiswapChain);
+        sys->dxgiswapChain = NULL;
+    }
+    if (sys->d3drenderTargetView[LEFT_EYE])
+    {
+        ID3D11RenderTargetView_Release(sys->d3drenderTargetView[LEFT_EYE]);
+        sys->d3drenderTargetView[LEFT_EYE] = NULL;
+    }
+    if (sys->d3drenderTargetView[RIGHT_EYE])
+    {
+        ID3D11RenderTargetView_Release(sys->d3drenderTargetView[RIGHT_EYE]);
+        sys->d3drenderTargetView[RIGHT_EYE] = NULL;
+    }
+
+    hr = IDXGIFactory2_CreateSwapChainForHwnd(dxgifactory, (IUnknown *)sys->d3ddevice,
+                                 sys->sys.hvideownd, &scd, NULL, NULL, &sys->dxgiswapChain);
+    IDXGIFactory2_Release(dxgifactory);
+    if (FAILED(hr)) {
+       msg_Err(vd, "Could not recreate the SwapChain. (hr=0x%lX)", hr);
+       return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
 static HRESULT UpdateBackBuffer(vout_display_t *vd)
 {
     vout_display_sys_t *sys = vd->sys;
@@ -834,9 +910,13 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
     uint32_t i_width = RECTWidth(rect);
     uint32_t i_height = RECTHeight(rect);
 
-    if (sys->d3drenderTargetView) {
-        ID3D11RenderTargetView_Release(sys->d3drenderTargetView);
-        sys->d3drenderTargetView = NULL;
+    if (sys->d3drenderTargetView[LEFT_EYE]) {
+        ID3D11RenderTargetView_Release(sys->d3drenderTargetView[LEFT_EYE]);
+        sys->d3drenderTargetView[LEFT_EYE] = NULL;
+    }
+    if (sys->d3drenderTargetView[RIGHT_EYE]) {
+        ID3D11RenderTargetView_Release(sys->d3drenderTargetView[RIGHT_EYE]);
+        sys->d3drenderTargetView[RIGHT_EYE] = NULL;
     }
     if (sys->d3ddepthStencilView) {
         ID3D11DepthStencilView_Release(sys->d3ddepthStencilView);
@@ -844,8 +924,12 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
     }
 
     /* TODO detect is the size is the same as the output and switch to fullscreen mode */
-    hr = IDXGISwapChain_ResizeBuffers(sys->dxgiswapChain, 0, i_width, i_height,
-        DXGI_FORMAT_UNKNOWN, 0);
+    if (sys->multiview_3d)
+        hr = IDXGISwapChain_ResizeBuffers(sys->dxgiswapChain, 4, i_width, i_height,
+                                      DXGI_FORMAT_UNKNOWN, 0);
+    else
+        hr = IDXGISwapChain_ResizeBuffers(sys->dxgiswapChain, 2, i_width, i_height,
+                                      DXGI_FORMAT_UNKNOWN, 0);
     if (FAILED(hr)) {
        msg_Err(vd, "Failed to resize the backbuffer. (hr=0x%lX)", hr);
        return hr;
@@ -857,7 +941,24 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
        return hr;
     }
 
-    hr = ID3D11Device_CreateRenderTargetView(sys->d3ddevice, (ID3D11Resource *)pBackBuffer, NULL, &sys->d3drenderTargetView);
+    D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
+    ZeroMemory(&renderTargetViewDesc, sizeof(D3D11_RENDER_TARGET_VIEW_DESC));
+    renderTargetViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;    
+    renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+    renderTargetViewDesc.Texture2DArray.MipSlice = 0;
+    renderTargetViewDesc.Texture2DArray.FirstArraySlice = 0;
+    renderTargetViewDesc.Texture2DArray.ArraySize = 1;
+
+    hr = ID3D11Device_CreateRenderTargetView(sys->d3ddevice, (ID3D11Resource *)pBackBuffer,
+                                     &renderTargetViewDesc, &sys->d3drenderTargetView[LEFT_EYE]);
+
+    if (sys->multiview_3d)
+    {
+        renderTargetViewDesc.Texture2DArray.FirstArraySlice = 1;
+        hr = ID3D11Device_CreateRenderTargetView(sys->d3ddevice, (ID3D11Resource *)pBackBuffer,
+                                         &renderTargetViewDesc, &sys->d3drenderTargetView[RIGHT_EYE]);
+    }
+
     ID3D11Texture2D_Release(pBackBuffer);
     if (FAILED(hr)) {
         msg_Err(vd, "Failed to create the target view. (hr=0x%lX)", hr);
@@ -1090,6 +1191,30 @@ static int Control(vout_display_t *vd, int query, va_list args)
             res = VLC_SUCCESS;
         }
     }
+    else if (query == VOUT_DISPLAY_CHANGE_MULTIVIEW)
+    {
+        const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t*);
+        //Disable Stereoscopic 3D if 2D output is selected
+        if ((cfg->multiview_format == VIDEO_STEREO_OUTPUT_RIGHT_ONLY || cfg->multiview_format == VIDEO_STEREO_OUTPUT_LEFT_ONLY) ||
+            (cfg->multiview_format == VIDEO_STEREO_OUTPUT_AUTO && sys->source_3d_format == MULTIVIEW_UNKNOWN))
+        {
+            if (sys->multiview_3d)
+            {                
+                sys->multiview_3d = false;
+                res = UpdateSwapChain(vd, false);
+            }            
+        }
+        else if ((cfg->multiview_format == VIDEO_STEREO_OUTPUT_AUTO && !sys->multiview_3d) ||
+                (cfg->multiview_format == VIDEO_STEREO_OUTPUT_STEREO))
+        {
+            sys->multiview_3d = sys->device_3d_capable;
+            res = UpdateSwapChain(vd, sys->multiview_3d);
+        }
+
+        UpdateBackBuffer(vd);
+        UpdatePicQuadPosition(vd);
+        res = VLC_SUCCESS;
+    }
 
     if (RECTWidth(size_before)  != RECTWidth(sys->sys.rect_dest_clipped) ||
         RECTHeight(size_before) != RECTHeight(sys->sys.rect_dest_clipped))
@@ -1153,6 +1278,20 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
         }
     }
 
+    if (sys->source_3d_format != picture->format.multiview_mode && picture->format.multiview_mode != MULTIVIEW_UNKNOWN)
+    {
+        int video_stereo_output = var_InheritInteger (vd, "video-stereo-mode");
+        sys->source_3d_format = picture->format.multiview_mode;
+        if ((sys->source_3d_format == MULTIVIEW_STEREO_SBS || sys->source_3d_format == MULTIVIEW_STEREO_TB) &&
+                (video_stereo_output == VIDEO_STEREO_OUTPUT_AUTO))
+        {
+            sys->multiview_3d = sys->device_3d_capable;
+            UpdateSwapChain(vd, sys->multiview_3d);
+            UpdateBackBuffer(vd);
+            UpdatePicQuadPosition(vd);
+        }
+    }
+
     if (subpicture) {
         int subpicture_region_count    = 0;
         picture_t **subpicture_regions = NULL;
@@ -1169,11 +1308,14 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
 #endif
 }
 
-static void DisplayD3DPicture(vout_display_sys_t *sys, d3d_quad_t *quad, ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW])
+static void DisplayD3DPicture(vout_display_sys_t *sys, d3d_quad_t *quad, ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW], int eyeIndex)
 {
     UINT stride = sizeof(d3d_vertex_t);
     UINT offset = 0;
 
+    ID3D11DeviceContext_OMSetRenderTargets(sys->d3dcontext, 1,
+                                           &sys->d3drenderTargetView[eyeIndex], sys->d3ddepthStencilView);
+
     /* Render the quad */
     /* vertex shader */
     ID3D11DeviceContext_IASetVertexBuffers(sys->d3dcontext, 0, 1, &quad->pVertexBuffer, &stride, &offset);
@@ -1189,11 +1331,33 @@ static void DisplayD3DPicture(vout_display_sys_t *sys, d3d_quad_t *quad, ID3D11S
     ID3D11DeviceContext_PSSetConstantBuffers(sys->d3dcontext, 0, quad->PSConstantsCount, quad->pPixelShaderConstants);
     ID3D11DeviceContext_PSSetShaderResources(sys->d3dcontext, 0, D3D11_MAX_SHADER_VIEW, resourceView);
 
-    ID3D11DeviceContext_RSSetViewports(sys->d3dcontext, 1, &quad->cropViewport);
+    if (eyeIndex == LEFT_EYE)
+        ID3D11DeviceContext_RSSetViewports(sys->d3dcontext, 1, &quad->cropViewport[LEFT_EYE]);
+    else
+        ID3D11DeviceContext_RSSetViewports(sys->d3dcontext, 1, &quad->cropViewport[RIGHT_EYE]);
 
     ID3D11DeviceContext_DrawIndexed(sys->d3dcontext, quad->indexCount, 0, 0);
 }
 
+static void DisplayPicture(vout_display_t *vd, ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW],
+                           d3d_quad_t *quad, bool is_subpicture)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    if (is_subpicture)
+    {
+        DisplayD3DPicture(sys, quad, resourceView, MONO_EYE);
+    }
+    else
+    {
+        DisplayD3DPicture(sys, &sys->picQuad, resourceView, MONO_EYE);
+        if (sys->multiview_3d)
+        {
+            DisplayD3DPicture(sys, &sys->picQuad, resourceView, RIGHT_EYE);
+        }
+    }
+}
+
 static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
 {
     vout_display_sys_t *sys = vd->sys;
@@ -1205,20 +1369,18 @@ static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
 #endif
 
     FLOAT blackRGBA[4] = {0.0f, 0.0f, 0.0f, 1.0f};
-    ID3D11DeviceContext_ClearRenderTargetView(sys->d3dcontext, sys->d3drenderTargetView, blackRGBA);
-
-    /* no ID3D11Device operations should come here */
+    ID3D11DeviceContext_ClearRenderTargetView(sys->d3dcontext, sys->d3drenderTargetView[MONO_EYE], blackRGBA);
 
-    ID3D11DeviceContext_OMSetRenderTargets(sys->d3dcontext, 1, &sys->d3drenderTargetView, sys->d3ddepthStencilView);
+    /* no ID3D11Device operations should come here */    
 
     ID3D11DeviceContext_ClearDepthStencilView(sys->d3dcontext, sys->d3ddepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
 
     /* Render the quad */
     if (!is_d3d11_opaque(picture->format.i_chroma) || sys->legacy_shader)
-        DisplayD3DPicture(sys, &sys->picQuad, sys->stagingSys.resourceView);
+        DisplayPicture(vd, sys->stagingSys.resourceView, NULL, false);
     else {
         picture_sys_t *p_sys = ActivePictureSys(picture);
-        DisplayD3DPicture(sys, &sys->picQuad, p_sys->resourceView);
+        DisplayPicture(vd, p_sys->resourceView, NULL, false);
     }
 
     if (subpicture) {
@@ -1227,7 +1389,7 @@ static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
             if (sys->d3dregions[i])
             {
                 d3d_quad_t *quad = (d3d_quad_t *) sys->d3dregions[i]->p_sys;
-                DisplayD3DPicture(sys, quad, quad->picSys.resourceView);
+                DisplayPicture(vd, quad->picSys.resourceView, quad, true);
             }
         }
     }
@@ -1464,6 +1626,7 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
 {
     vout_display_sys_t *sys = vd->sys;
     IDXGIFactory2 *dxgifactory;
+    D3D_FEATURE_LEVEL i_feature_level;
 
     *fmt = vd->source;
 
@@ -1491,6 +1654,9 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
     scd.SampleDesc.Quality = 0;
     scd.Width = fmt->i_visible_width;
     scd.Height = fmt->i_visible_height;
+    scd.Scaling = DXGI_SCALING_NONE;
+    scd.Flags = 0;
+
     switch(fmt->i_chroma)
     {
     case VLC_CODEC_D3D11_OPAQUE_10B:
@@ -1512,7 +1678,6 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
     };
 
     for (UINT driver = 0; driver < ARRAYSIZE(driverAttempts); driver++) {
-        D3D_FEATURE_LEVEL i_feature_level;
         hr = D3D11CreateDevice(NULL, driverAttempts[driver], NULL, creationFlags,
                     NULL, 0, D3D11_SDK_VERSION,
                     &sys->d3ddevice, &i_feature_level, &sys->d3dcontext);
@@ -1531,6 +1696,10 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
        return VLC_EGENERIC;
     }
 
+    if (i_feature_level < D3D_FEATURE_LEVEL_10_0) {
+        msg_Dbg(vd, "Could not create the D3D11 device for Stereoscopic 3D. 3D won't work.");
+    }
+
     IDXGIAdapter *dxgiadapter = D3D11DeviceAdapter(sys->d3ddevice);
     if (unlikely(dxgiadapter==NULL)) {
        msg_Err(vd, "Could not get the DXGI Adapter");
@@ -1544,6 +1713,15 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
        return VLC_EGENERIC;
     }
 
+    //Disable 3D if not supported by the system   
+    sys->device_3d_capable = i_feature_level >= D3D_FEATURE_LEVEL_10_0 &&
+            IDXGIFactory2_IsWindowedStereoEnabled(dxgifactory);
+    sys->multiview_3d = sys->device_3d_capable;
+    sys->source_3d_format = fmt->multiview_mode;
+    if (fmt->multiview_mode == MULTIVIEW_UNKNOWN || fmt->multiview_mode == MULTIVIEW_2D)
+        sys->multiview_3d = false;
+    scd.Stereo = sys->multiview_3d;
+
     hr = IDXGIFactory2_CreateSwapChainForHwnd(dxgifactory, (IUnknown *)sys->d3ddevice,
                                               sys->sys.hvideownd, &scd, NULL, NULL, &sys->dxgiswapChain);
     IDXGIFactory2_Release(dxgifactory);
@@ -1679,19 +1857,84 @@ static void Direct3D11Close(vout_display_t *vd)
 static void UpdatePicQuadPosition(vout_display_t *vd)
 {
     vout_display_sys_t *sys = vd->sys;
+    int video_stereo_output = var_InheritInteger (vd, "video-stereo-mode");
 
-    sys->picQuad.cropViewport.Width    = RECTWidth(sys->sys.rect_dest_clipped);
-    sys->picQuad.cropViewport.Height   = RECTHeight(sys->sys.rect_dest_clipped);
-    sys->picQuad.cropViewport.TopLeftX = sys->sys.rect_dest_clipped.left;
-    sys->picQuad.cropViewport.TopLeftY = sys->sys.rect_dest_clipped.top;
+    //Default 2D mode selection
+    if (!sys->multiview_3d)
+    {
+        sys->picQuad.cropViewport[MONO_EYE].Width    = RECTWidth(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[MONO_EYE].Height   = RECTHeight(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[MONO_EYE].TopLeftX = sys->sys.rect_dest_clipped.left;
+        sys->picQuad.cropViewport[MONO_EYE].TopLeftY = sys->sys.rect_dest_clipped.top;
+    }
+    //For stereoscopic side by side left-right format
+    else if ((video_stereo_output == VIDEO_STEREO_OUTPUT_AUTO || video_stereo_output == VIDEO_STEREO_OUTPUT_STEREO) &&
+              (sys->source_3d_format == MULTIVIEW_STEREO_SBS) && (sys->multiview_3d))
+    {
+        sys->picQuad.cropViewport[LEFT_EYE].Width    = RECTWidth(sys->sys.rect_dest_clipped) * 2;
+        sys->picQuad.cropViewport[LEFT_EYE].Height   = RECTHeight(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[LEFT_EYE].TopLeftX = sys->sys.rect_dest_clipped.left;
+        sys->picQuad.cropViewport[LEFT_EYE].TopLeftY = sys->sys.rect_dest_clipped.top;
+
+        sys->picQuad.cropViewport[RIGHT_EYE].Width    = RECTWidth(sys->sys.rect_dest_clipped) * 2;
+        sys->picQuad.cropViewport[RIGHT_EYE].Height   = RECTHeight(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[RIGHT_EYE].TopLeftX = sys->sys.rect_dest_clipped.left - RECTWidth(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[RIGHT_EYE].TopLeftY = sys->sys.rect_dest_clipped.top;
+        sys->picQuad.cropViewport[RIGHT_EYE].MinDepth = 0.0f;
+        sys->picQuad.cropViewport[RIGHT_EYE].MaxDepth = 1.0f;
+    }
+    //For stereoscopic side by side top-bottom format
+    else if (sys->source_3d_format == MULTIVIEW_STEREO_TB && sys->multiview_3d)
+    {
+        sys->picQuad.cropViewport[LEFT_EYE].Width    = RECTWidth(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[LEFT_EYE].Height   = RECTHeight(sys->sys.rect_dest_clipped) * 2;
+        sys->picQuad.cropViewport[LEFT_EYE].TopLeftX = sys->sys.rect_dest_clipped.left;
+        sys->picQuad.cropViewport[LEFT_EYE].TopLeftY = sys->sys.rect_dest_clipped.top;
+
+        sys->picQuad.cropViewport[RIGHT_EYE].Width    = RECTWidth(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[RIGHT_EYE].Height   = RECTHeight(sys->sys.rect_dest_clipped) * 2;
+        sys->picQuad.cropViewport[RIGHT_EYE].TopLeftX = sys->sys.rect_dest_clipped.left;
+        sys->picQuad.cropViewport[RIGHT_EYE].TopLeftY = sys->sys.rect_dest_clipped.top - RECTHeight(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[RIGHT_EYE].MinDepth = 0.0f;
+        sys->picQuad.cropViewport[RIGHT_EYE].MaxDepth = 1.0f;
+    }
+    else if ( video_stereo_output == VIDEO_STEREO_OUTPUT_STEREO && (sys->source_3d_format == MULTIVIEW_2D ||
+                                                                    sys->source_3d_format == MULTIVIEW_UNKNOWN))
+    {
+        sys->picQuad.cropViewport[LEFT_EYE].Width    = sys->picQuad.cropViewport[RIGHT_EYE].Width =
+                RECTWidth(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[LEFT_EYE].Height   = sys->picQuad.cropViewport[RIGHT_EYE].Height =
+                RECTHeight(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[LEFT_EYE].TopLeftX = sys->picQuad.cropViewport[RIGHT_EYE].TopLeftX =
+                sys->sys.rect_dest_clipped.left;
+        sys->picQuad.cropViewport[LEFT_EYE].TopLeftY = sys->picQuad.cropViewport[RIGHT_EYE].TopLeftY =
+                sys->sys.rect_dest_clipped.top;
+
+        sys->picQuad.cropViewport[RIGHT_EYE].MinDepth = 0.0f;
+        sys->picQuad.cropViewport[RIGHT_EYE].MaxDepth = 1.0f;
+    }
 
-    sys->picQuad.cropViewport.MinDepth = 0.0f;
-    sys->picQuad.cropViewport.MaxDepth = 1.0f;
+    if (video_stereo_output == VIDEO_STEREO_OUTPUT_LEFT_ONLY)
+    {
+        sys->picQuad.cropViewport[MONO_EYE].Width    = RECTWidth(sys->sys.rect_dest_clipped) * 2;
+        sys->picQuad.cropViewport[MONO_EYE].Height   = RECTHeight(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[MONO_EYE].TopLeftX = sys->sys.rect_dest_clipped.left;
+        sys->picQuad.cropViewport[MONO_EYE].TopLeftY = sys->sys.rect_dest_clipped.top;
+    }
+    else if (video_stereo_output == VIDEO_STEREO_OUTPUT_RIGHT_ONLY)
+    {
+        sys->picQuad.cropViewport[MONO_EYE].Width    = RECTWidth(sys->sys.rect_dest_clipped) * 2;
+        sys->picQuad.cropViewport[MONO_EYE].Height   = RECTHeight(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[MONO_EYE].TopLeftX = sys->sys.rect_dest_clipped.left - RECTWidth(sys->sys.rect_dest_clipped);
+        sys->picQuad.cropViewport[MONO_EYE].TopLeftY = sys->sys.rect_dest_clipped.top;
+    }
+    sys->picQuad.cropViewport[MONO_EYE].MinDepth = 0.0f;
+    sys->picQuad.cropViewport[MONO_EYE].MaxDepth = 1.0f;
 
     SetQuadVSProjection(vd, &sys->picQuad, &vd->cfg->viewpoint);
 
 #ifndef NDEBUG
-    msg_Dbg(vd, "picQuad position (%.02f,%.02f) %.02fx%.02f", sys->picQuad.cropViewport.TopLeftX, sys->picQuad.cropViewport.TopLeftY, sys->picQuad.cropViewport.Width, sys->picQuad.cropViewport.Height );
+    msg_Dbg(vd, "picQuad position (%.02f,%.02f) %.02fx%.02f", sys->picQuad.cropViewport[MONO_EYE].TopLeftX, sys->picQuad.cropViewport[MONO_EYE].TopLeftY, sys->picQuad.cropViewport[MONO_EYE].Width, sys->picQuad.cropViewport[MONO_EYE].Height );
 #endif
 }
 
@@ -2722,10 +2965,15 @@ static void Direct3D11DestroyResources(vout_display_t *vd)
         ID3D11VertexShader_Release(sys->projectionVSShader);
         sys->projectionVSShader = NULL;
     }
-    if (sys->d3drenderTargetView)
+    if (sys->d3drenderTargetView[LEFT_EYE])
+    {
+        ID3D11RenderTargetView_Release(sys->d3drenderTargetView[LEFT_EYE]);
+        sys->d3drenderTargetView[LEFT_EYE] = NULL;
+    }
+    if (sys->d3drenderTargetView[RIGHT_EYE])
     {
-        ID3D11RenderTargetView_Release(sys->d3drenderTargetView);
-        sys->d3drenderTargetView = NULL;
+        ID3D11RenderTargetView_Release(sys->d3drenderTargetView[RIGHT_EYE]);
+        sys->d3drenderTargetView[RIGHT_EYE] = NULL;
     }
     if (sys->d3ddepthStencilView)
     {
@@ -2899,12 +3147,12 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
 
         d3d_quad_t *quad = (d3d_quad_t *) quad_picture->p_sys;
 
-        quad->cropViewport.Width =  (FLOAT) r->fmt.i_visible_width  * RECTWidth(sys->sys.rect_dest)  / subpicture->i_original_picture_width;
-        quad->cropViewport.Height = (FLOAT) r->fmt.i_visible_height * RECTHeight(sys->sys.rect_dest) / subpicture->i_original_picture_height;
-        quad->cropViewport.MinDepth = 0.0f;
-        quad->cropViewport.MaxDepth = 1.0f;
-        quad->cropViewport.TopLeftX = sys->sys.rect_dest.left + (FLOAT) r->i_x * RECTWidth(sys->sys.rect_dest) / subpicture->i_original_picture_width;
-        quad->cropViewport.TopLeftY = sys->sys.rect_dest.top  + (FLOAT) r->i_y * RECTHeight(sys->sys.rect_dest) / subpicture->i_original_picture_height;
+        quad->cropViewport[MONO_EYE].Width =  (FLOAT) r->fmt.i_visible_width  * RECTWidth(sys->sys.rect_dest)  / subpicture->i_original_picture_width;
+        quad->cropViewport[MONO_EYE].Height = (FLOAT) r->fmt.i_visible_height * RECTHeight(sys->sys.rect_dest) / subpicture->i_original_picture_height;
+        quad->cropViewport[MONO_EYE].MinDepth = 0.0f;
+        quad->cropViewport[MONO_EYE].MaxDepth = 1.0f;
+        quad->cropViewport[MONO_EYE].TopLeftX = sys->sys.rect_dest.left + (FLOAT) r->i_x * RECTWidth(sys->sys.rect_dest) / subpicture->i_original_picture_width;
+        quad->cropViewport[MONO_EYE].TopLeftY = sys->sys.rect_dest.top  + (FLOAT) r->i_y * RECTHeight(sys->sys.rect_dest) / subpicture->i_original_picture_height;
 
         UpdateQuadOpacity(vd, quad, r->i_alpha / 255.0f );
     }
-- 
2.12.2.windows.2



More information about the vlc-devel mailing list