[vlc-devel] [PATCH 5/5] direct3d11: add a spherical projection

Steve Lhomme robux4 at videolabs.io
Mon Nov 21 17:55:14 CET 2016


Use a different vertex shader than the flat one.
The projection matrices are passed as constants to the Vertex shader.
---
 modules/video_output/win32/common.h     |   2 +
 modules/video_output/win32/direct3d11.c | 418 ++++++++++++++++++++++++++------
 2 files changed, 346 insertions(+), 74 deletions(-)

diff --git a/modules/video_output/win32/common.h b/modules/video_output/win32/common.h
index c499778..a8ce067 100644
--- a/modules/video_output/win32/common.h
+++ b/modules/video_output/win32/common.h
@@ -65,6 +65,7 @@ typedef struct
     ID3D11VertexShader        *d3dvertexShader;
     ID3D11Buffer              *pIndexBuffer;
     UINT                      indexCount;
+    ID3D11Buffer              *pVertexShaderConstants;
     ID3D11Texture2D           *pTexture;
     ID3D11Buffer              *pPixelShaderConstants;
     ID3D11ShaderResourceView  *d3dresViewY;
@@ -208,6 +209,7 @@ struct vout_display_sys_t
     const char               *d3dPxShader;
 
     ID3D11VertexShader        *flatVSShader;
+    ID3D11VertexShader        *projectionVSShader;
 
     // SPU
     vlc_fourcc_t             pSubpictureChromas[2];
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index 8be818c..a7ffc00 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -35,6 +35,7 @@
 #include <vlc_vout_display.h>
 
 #include <assert.h>
+#include <math.h>
 
 #define COBJMACROS
 #define INITGUID
@@ -124,6 +125,16 @@ typedef struct {
     FLOAT padding[3];
 } PS_CONSTANT_BUFFER;
 
+typedef struct {
+    FLOAT RotX[16];
+    FLOAT RotY[16];
+    FLOAT RotZ[16];
+    FLOAT View[16];
+    FLOAT Projection[16];
+} VS_CONSTANT_BUFFER;
+
+#define SPHERE_RADIUS 1.f
+
 #define RECTWidth(r)   (int)((r).right - (r).left)
 #define RECTHeight(r)  (int)((r).bottom - (r).top)
 
@@ -152,7 +163,8 @@ static void Direct3D11DeleteRegions(int, picture_t **);
 static int Direct3D11MapSubpicture(vout_display_t *, int *, picture_t ***, subpicture_t *);
 
 static int AllocQuad(vout_display_t *, const video_format_t *, d3d_quad_t *,
-                     d3d_quad_cfg_t *, ID3D11PixelShader *, bool b_visible);
+                     d3d_quad_cfg_t *, ID3D11PixelShader *, bool b_visible,
+                     video_projection_mode_t);
 static void ReleaseQuad(d3d_quad_t *);
 static void UpdatePicQuadPosition(vout_display_t *);
 static void UpdateQuadOpacity(vout_display_t *, const d3d_quad_t *, float);
@@ -184,8 +196,41 @@ static const char* globVertexShaderFlat = "\
   \
   VS_OUTPUT VS( VS_INPUT In )\
   {\
+    return In;\
+  }\
+";
+
+static const char* globVertexShaderProjection = "\
+  cbuffer VS_CONSTANT_BUFFER : register(b0)\
+  {\
+     float4x4 RotX;\
+     float4x4 RotY;\
+     float4x4 RotZ;\
+     float4x4 View;\
+     float4x4 Projection;\
+  };\
+  struct VS_INPUT\
+  {\
+    float4 Position   : POSITION;\
+    float2 Texture    : TEXCOORD0;\
+  };\
+  \
+  struct VS_OUTPUT\
+  {\
+    float4 Position   : SV_POSITION;\
+    float2 Texture    : TEXCOORD0;\
+  };\
+  \
+  VS_OUTPUT VS( VS_INPUT In )\
+  {\
     VS_OUTPUT Output;\
-    Output.Position = In.Position;\
+    float4 pos = In.Position;\
+    pos = mul(RotY, pos);\
+    pos = mul(RotX, pos);\
+    pos = mul(RotZ, pos);\
+    pos = mul(View, pos);\
+    pos = mul(Projection, pos);\
+    Output.Position = pos;\
     Output.Texture = In.Texture;\
     return Output;\
   }\
@@ -803,6 +848,120 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
     return S_OK;
 }
 
+/* rotation around the Z axis */
+static void getZRotMatrix(float theta, FLOAT matrix[static 16])
+{
+    float st, ct;
+
+    sincosf(theta, &st, &ct);
+
+    const FLOAT m[] = {
+    /*  x    y    z    w */
+        ct,  -st, 0.f, 0.f,
+        st,  ct,  0.f, 0.f,
+        0.f, 0.f, 1.f, 0.f,
+        0.f, 0.f, 0.f, 1.f
+    };
+
+    memcpy(matrix, m, sizeof(m));
+}
+
+/* rotation around the Y axis */
+static void getYRotMatrix(float theta, FLOAT matrix[static 16])
+{
+    float st, ct;
+
+    sincosf(theta, &st, &ct);
+
+    const FLOAT m[] = {
+    /*  x    y    z    w */
+        ct,  0.f, -st, 0.f,
+        0.f, 1.f, 0.f, 0.f,
+        st,  0.f, ct,  0.f,
+        0.f, 0.f, 0.f, 1.f
+    };
+
+    memcpy(matrix, m, sizeof(m));
+}
+
+/* rotation around the X axis */
+static void getXRotMatrix(float phi, FLOAT matrix[static 16])
+{
+    float sp, cp;
+
+    sincosf(phi, &sp, &cp);
+
+    const FLOAT m[] = {
+    /*  x    y    z    w */
+        1.f, 0.f, 0.f, 0.f,
+        0.f, cp,  sp,  0.f,
+        0.f, -sp, cp,  0.f,
+        0.f, 0.f, 0.f, 1.f
+    };
+
+    memcpy(matrix, m, sizeof(m));
+}
+
+static void getZoomMatrix(float zoom, FLOAT matrix[static 16]) {
+
+    const FLOAT m[] = {
+        /* x   y     z     w */
+        1.0f, 0.0f, 0.0f, 0.0f,
+        0.0f, 1.0f, 0.0f, 0.0f,
+        0.0f, 0.0f, 1.0f, 0.0f,
+        0.0f, 0.0f, zoom, 1.0f
+    };
+
+    memcpy(matrix, m, sizeof(m));
+}
+
+/* perspective matrix see https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml */
+static void getProjectionMatrix(float sar, float fovy, FLOAT matrix[static 16]) {
+
+    float zFar  = 1000;
+    float zNear = 0.01;
+
+    float f = 1.f / tanf(fovy / 2.f);
+
+    const FLOAT m[] = {
+        f / sar, 0.f,                   0.f,                0.f,
+        0.f,     f,                     0.f,                0.f,
+        0.f,     0.f,    -(zNear + zFar) / (zNear - zFar),  1.f,
+        0.f,     0.f, (2 * zNear * zFar) / (zNear - zFar),  0.f};
+
+     memcpy(matrix, m, sizeof(m));
+}
+
+static void SetQuadViewpoint(vout_display_t *vd, d3d_quad_t *quad, const vlc_viewpoint_t *p_vp, video_projection_mode_t projection)
+{
+    vout_display_sys_t *sys = vd->sys;
+    HRESULT hr;
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    hr = ID3D11DeviceContext_Map(sys->d3dcontext, (ID3D11Resource *)quad->pVertexShaderConstants, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    if (SUCCEEDED(hr)) {
+        VS_CONSTANT_BUFFER *dst_data = mappedResource.pData;
+        static_assert((sizeof(*dst_data)%16)==0,"Constant buffers require 16-byte alignment");
+
+#define RAD(d) ((float) ((d) * M_PI / 180.f))
+        if (projection == PROJECTION_MODE_RECTANGULAR)
+        {
+            quad->d3dvertexShader = sys->flatVSShader;
+        }
+        else
+        {
+            quad->d3dvertexShader = sys->projectionVSShader;
+            getXRotMatrix(-RAD(p_vp->pitch), dst_data->RotX);
+            getYRotMatrix(-RAD(p_vp->yaw),   dst_data->RotY);
+            getZRotMatrix(-RAD(p_vp->roll),  dst_data->RotZ);
+            getZoomMatrix(SPHERE_RADIUS * p_vp->zoom, dst_data->View);
+            float sar = (float) vd->cfg->display.width / vd->cfg->display.height;
+            getProjectionMatrix(sar, RAD(p_vp->fov), dst_data->Projection);
+        }
+#undef RAD
+    }
+    ID3D11DeviceContext_Unmap(sys->d3dcontext, (ID3D11Resource *)quad->pVertexShaderConstants, 0);
+}
+
 static void CropStagingFormat(vout_display_t *vd, video_format_t *backup_fmt)
 {
     if ( vd->sys->stagingQuad.pTexture == NULL )
@@ -828,6 +987,14 @@ static int Control(vout_display_t *vd, int query, va_list args)
     video_format_t core_source;
     CropStagingFormat( vd, &core_source );
     int res = CommonControl( vd, query, args );
+
+    if (query == VOUT_DISPLAY_CHANGE_VIEWPOINT)
+    {
+        const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t*);
+        SetQuadViewpoint( vd, &vd->sys->picQuad, &cfg->viewpoint, vd->fmt.projection_mode );
+        res = VLC_SUCCESS;
+    }
+
     UncropStagingFormat( vd, &core_source );
     return res;
 }
@@ -949,6 +1116,7 @@ static void DisplayD3DPicture(vout_display_sys_t *sys, d3d_quad_t *quad)
     /* vertex shader */
     ID3D11DeviceContext_IASetVertexBuffers(sys->d3dcontext, 0, 1, &quad->pVertexBuffer, &stride, &offset);
     ID3D11DeviceContext_IASetIndexBuffer(sys->d3dcontext, quad->pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
+    ID3D11DeviceContext_VSSetConstantBuffers(sys->d3dcontext, 0, 1, &quad->pVertexShaderConstants);
 
     ID3D11DeviceContext_VSSetShader(sys->d3dcontext, quad->d3dvertexShader, NULL, 0);
 
@@ -1364,7 +1532,7 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
     if ( fmt->i_height != fmt->i_visible_height || fmt->i_width != fmt->i_visible_width )
     {
         msg_Dbg( vd, "use a staging texture to crop to visible size" );
-        AllocQuad( vd, fmt, &sys->stagingQuad, &sys->picQuadConfig, NULL, false );
+        AllocQuad( vd, fmt, &sys->stagingQuad, &sys->picQuadConfig, NULL, false, PROJECTION_MODE_RECTANGULAR );
     }
 
     video_format_t core_source;
@@ -1555,6 +1723,24 @@ static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
     ID3D11DeviceContext_IASetInputLayout(sys->d3dcontext, pVertexLayout);
     ID3D11InputLayout_Release(pVertexLayout);
     
+    hr = D3DCompile(globVertexShaderProjection, strlen(globVertexShaderProjection),
+                    NULL, NULL, NULL, "VS", "vs_4_0_level_9_1", 0, 0, &pVSBlob, NULL);
+
+    if( FAILED(hr)) {
+      msg_Err(vd, "The projection Vertex Shader is invalid. (hr=0x%lX)", hr);
+      return VLC_EGENERIC;
+    }
+
+    hr = ID3D11Device_CreateVertexShader(sys->d3ddevice, (void *)ID3D10Blob_GetBufferPointer(pVSBlob),
+                                        ID3D10Blob_GetBufferSize(pVSBlob), NULL, &sys->projectionVSShader);
+
+    if(FAILED(hr)) {
+      ID3D11Device_Release(pVSBlob);
+      msg_Err(vd, "Failed to create the projection vertex shader. (hr=0x%lX)", hr);
+      return VLC_EGENERIC;
+    }
+    ID3D10Blob_Release(pVSBlob);
+
     ID3D11DeviceContext_IASetPrimitiveTopology(sys->d3dcontext, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
 
     ID3DBlob* pPSBlob = NULL;
@@ -1602,7 +1788,7 @@ static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
         }
     }
 
-    if (AllocQuad( vd, fmt, &sys->picQuad, &sys->picQuadConfig, pPicQuadShader, true) != VLC_SUCCESS) {
+    if (AllocQuad( vd, fmt, &sys->picQuad, &sys->picQuadConfig, pPicQuadShader, true, vd->fmt.projection_mode) != VLC_SUCCESS) {
         ID3D11PixelShader_Release(pPicQuadShader);
         msg_Err(vd, "Could not Create the main quad picture. (hr=0x%lX)", hr);
         return VLC_EGENERIC;
@@ -1700,39 +1886,29 @@ static void Direct3D11DestroyPool(vout_display_t *vd)
     sys->pool = NULL;
 }
 
+#define SPHERE_SLICES 128
+
 static int AllocQuad(vout_display_t *vd, const video_format_t *fmt, d3d_quad_t *quad,
-                     d3d_quad_cfg_t *cfg, ID3D11PixelShader *d3dpixelShader, bool b_visible)
+                     d3d_quad_cfg_t *cfg, ID3D11PixelShader *d3dpixelShader, bool b_visible,
+                     video_projection_mode_t projection)
 {
     vout_display_sys_t *sys = vd->sys;
     D3D11_MAPPED_SUBRESOURCE mappedResource;
     HRESULT hr;
-    quad->vertexCount = 4;
-    quad->indexCount = 2 * 3;
-
-    D3D11_BUFFER_DESC bd;
-    memset(&bd, 0, sizeof(bd));
-    bd.Usage = D3D11_USAGE_DYNAMIC;
-    bd.ByteWidth = sizeof(d3d_vertex_t) * quad->vertexCount;
-    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
-    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-
-    hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &bd, NULL, &quad->pVertexBuffer);
-    if(FAILED(hr)) {
-      msg_Err(vd, "Failed to create vertex buffer. (hr=%lX)", hr);
-      goto error;
-    }
+    const unsigned nbLatBands = SPHERE_SLICES;
+    const unsigned nbLonBands = SPHERE_SLICES;
 
     /* pixel shader constant buffer */
     PS_CONSTANT_BUFFER defaultConstants = {
       .Opacity = 1,
     };
-    static_assert((sizeof(defaultConstants)%16)==0,"Constant buffers require 16-byte alignment");
     D3D11_BUFFER_DESC constantDesc = {
         .Usage = D3D11_USAGE_DYNAMIC,
-        .ByteWidth = sizeof(defaultConstants),
+        .ByteWidth = sizeof(PS_CONSTANT_BUFFER),
         .BindFlags = D3D11_BIND_CONSTANT_BUFFER,
         .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE,
     };
+    static_assert((sizeof(PS_CONSTANT_BUFFER)%16)==0,"Constant buffers require 16-byte alignment");
     D3D11_SUBRESOURCE_DATA constantInit = { .pSysMem = &defaultConstants };
     hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &constantDesc, &constantInit, &quad->pPixelShaderConstants);
     if(FAILED(hr)) {
@@ -1740,21 +1916,15 @@ static int AllocQuad(vout_display_t *vd, const video_format_t *fmt, d3d_quad_t *
         goto error;
     }
 
-    /* create the index of the vertices */
-    D3D11_BUFFER_DESC quadDesc = {
-        .Usage = D3D11_USAGE_DYNAMIC,
-        .ByteWidth = sizeof(WORD) * quad->indexCount,
-        .BindFlags = D3D11_BIND_INDEX_BUFFER,
-        .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE,
-    };
-
-    quad->d3dvertexShader = sys->flatVSShader;
-
-    hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &quadDesc, NULL, &quad->pIndexBuffer);
+    /* vertex shader constant buffer */
+    constantDesc.ByteWidth = sizeof(VS_CONSTANT_BUFFER);
+    static_assert((sizeof(VS_CONSTANT_BUFFER)%16)==0,"Constant buffers require 16-byte alignment");
+    hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &constantDesc, NULL, &quad->pVertexShaderConstants);
     if(FAILED(hr)) {
-        msg_Err(vd, "Could not create the quad indices. (hr=0x%lX)", hr);
+        msg_Err(vd, "Could not create the vertex shader constant buffer. (hr=0x%lX)", hr);
         goto error;
     }
+    SetQuadViewpoint( vd, quad,&vd->cfg->viewpoint, projection );
 
     D3D11_TEXTURE2D_DESC texDesc;
     memset(&texDesc, 0, sizeof(texDesc));
@@ -1831,47 +2001,118 @@ static int AllocQuad(vout_display_t *vd, const video_format_t *fmt, d3d_quad_t *
         quad->d3dpixelShader = d3dpixelShader;
         ID3D11PixelShader_AddRef(quad->d3dpixelShader);
 
-        float right = 1.0f;
-        float left = -1.0f;
-        float top = 1.0f;
-        float bottom = -1.0f;
+        if (projection == PROJECTION_MODE_RECTANGULAR)
+        {
+            quad->vertexCount = 4;
+            quad->indexCount = 2 * 3;
+        }
+        else if (projection == PROJECTION_MODE_EQUIRECTANGULAR)
+        {
+            quad->vertexCount = (SPHERE_SLICES+1) * (SPHERE_SLICES+1);
+            quad->indexCount = nbLatBands * nbLonBands * 2 * 3;
+        }
+        else
+            goto error;
+
+        D3D11_BUFFER_DESC bd;
+        memset(&bd, 0, sizeof(bd));
+        bd.Usage = D3D11_USAGE_DYNAMIC;
+        bd.ByteWidth = sizeof(d3d_vertex_t) * quad->vertexCount;
+        bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+        bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+
+        hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &bd, NULL, &quad->pVertexBuffer);
+        if(FAILED(hr)) {
+          msg_Err(vd, "Failed to create vertex buffer. (hr=%lX)", hr);
+          goto error;
+        }
 
+        /* create the vertices */
         hr = ID3D11DeviceContext_Map(sys->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
         if (SUCCEEDED(hr)) {
             d3d_vertex_t *dst_data = mappedResource.pData;
 
-            // bottom left
-            dst_data[0].position.x = left;
-            dst_data[0].position.y = bottom;
-            dst_data[0].position.z = 0.0f;
-            dst_data[0].texture.x = 0.0f;
-            dst_data[0].texture.y = 1.0f;
-
-            // bottom right
-            dst_data[1].position.x = right;
-            dst_data[1].position.y = bottom;
-            dst_data[1].position.z = 0.0f;
-            dst_data[1].texture.x = 1.0f;
-            dst_data[1].texture.y = 1.0f;
-
-            // top right
-            dst_data[2].position.x = right;
-            dst_data[2].position.y = top;
-            dst_data[2].position.z = 0.0f;
-            dst_data[2].texture.x = 1.0f;
-            dst_data[2].texture.y = 0.0f;
-
-            // top left
-            dst_data[3].position.x = left;
-            dst_data[3].position.y = top;
-            dst_data[3].position.z = 0.0f;
-            dst_data[3].texture.x = 0.0f;
-            dst_data[3].texture.y = 0.0f;
+            if ( projection == PROJECTION_MODE_RECTANGULAR ) {
+                float right = 1.0f;
+                float left = -1.0f;
+                float top = 1.0f;
+                float bottom = -1.0f;
+
+                // bottom left
+                dst_data[0].position.x = left;
+                dst_data[0].position.y = bottom;
+                dst_data[0].position.z = 0.0f;
+                dst_data[0].texture.x = 0.0f;
+                dst_data[0].texture.y = 1.0f;
+
+                // bottom right
+                dst_data[1].position.x = right;
+                dst_data[1].position.y = bottom;
+                dst_data[1].position.z = 0.0f;
+                dst_data[1].texture.x = 1.0f;
+                dst_data[1].texture.y = 1.0f;
+
+                // top right
+                dst_data[2].position.x = right;
+                dst_data[2].position.y = top;
+                dst_data[2].position.z = 0.0f;
+                dst_data[2].texture.x = 1.0f;
+                dst_data[2].texture.y = 0.0f;
+
+                // top left
+                dst_data[3].position.x = left;
+                dst_data[3].position.y = top;
+                dst_data[3].position.z = 0.0f;
+                dst_data[3].texture.x = 0.0f;
+                dst_data[3].texture.y = 0.0f;
+            } else if (projection == PROJECTION_MODE_EQUIRECTANGULAR) {
+                const float radius = SPHERE_RADIUS;
+
+                for (unsigned lat = 0; lat <= nbLatBands; lat++) {
+                    float theta = lat * (float) M_PI / nbLatBands;
+                    float sinTheta, cosTheta;
+
+                    sincosf(theta, &sinTheta, &cosTheta);
+
+                    for (unsigned lon = 0; lon <= nbLonBands; lon++) {
+                        float phi = lon * 2 * (float) M_PI / nbLonBands;
+                        float sinPhi, cosPhi;
+
+                        sincosf(phi, &sinPhi, &cosPhi);
+
+                        float x = cosPhi * sinTheta;
+                        float y = cosTheta;
+                        float z = sinPhi * sinTheta;
+
+                        unsigned off1 = lat * (nbLonBands + 1) + lon;
+                        dst_data[off1].position.x = radius * x;
+                        dst_data[off1].position.y = radius * y;
+                        dst_data[off1].position.z = radius * z;
+
+                        dst_data[off1].texture.x = lon / (float) nbLonBands; // 0(left) to 1(right)
+                        dst_data[off1].texture.y = lat / (float) nbLatBands; // 0(top) to 1 (bottom)
+                    }
+                }
+            }
 
             ID3D11DeviceContext_Unmap(sys->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0);
         }
         else {
-            msg_Err(vd, "Failed to lock the subpicture vertex buffer (hr=0x%lX)", hr);
+            msg_Err(vd, "Failed to lock the vertex buffer (hr=0x%lX)", hr);
+        }
+
+        /* create the index of the vertices */
+        D3D11_BUFFER_DESC quadDesc = {
+            .Usage = D3D11_USAGE_DYNAMIC,
+            .ByteWidth = sizeof(WORD) * quad->indexCount,
+            .BindFlags = D3D11_BIND_INDEX_BUFFER,
+            .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE,
+        };
+
+        hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &quadDesc, NULL, &quad->pIndexBuffer);
+        if(FAILED(hr)) {
+            msg_Err(vd, "Could not create the quad indices. (hr=0x%lX)", hr);
+            goto error;
         }
 
         /* create the vertex indices */
@@ -1879,13 +2120,32 @@ static int AllocQuad(vout_display_t *vd, const video_format_t *fmt, d3d_quad_t *
         if (SUCCEEDED(hr)) {
             WORD *dst_data = mappedResource.pData;
 
-            dst_data[0] = 3;
-            dst_data[1] = 1;
-            dst_data[2] = 0;
-
-            dst_data[3] = 2;
-            dst_data[4] = 1;
-            dst_data[5] = 3;
+            if ( projection == PROJECTION_MODE_RECTANGULAR ) {
+                dst_data[0] = 3;
+                dst_data[1] = 1;
+                dst_data[2] = 0;
+
+                dst_data[3] = 2;
+                dst_data[4] = 1;
+                dst_data[5] = 3;
+            } else if (projection == PROJECTION_MODE_EQUIRECTANGULAR) {
+                for (unsigned lat = 0; lat < nbLatBands; lat++) {
+                    for (unsigned lon = 0; lon < nbLonBands; lon++) {
+                        unsigned first = (lat * (nbLonBands + 1)) + lon;
+                        unsigned second = first + nbLonBands + 1;
+
+                        unsigned off = (lat * nbLatBands + lon) * 3 * 2;
+
+                        dst_data[off] = first;
+                        dst_data[off + 1] = second;
+                        dst_data[off + 2] = first + 1;
+
+                        dst_data[off + 3] = second;
+                        dst_data[off + 4] = second + 1;
+                        dst_data[off + 5] = first + 1;
+                    }
+                }
+            }
 
             ID3D11DeviceContext_Unmap(sys->d3dcontext, (ID3D11Resource *)quad->pIndexBuffer, 0);
         }
@@ -1919,6 +2179,11 @@ static void ReleaseQuad(d3d_quad_t *quad)
         ID3D11Buffer_Release(quad->pIndexBuffer);
         quad->pIndexBuffer = NULL;
     }
+    if (quad->pVertexShaderConstants)
+    {
+        ID3D11Buffer_Release(quad->pVertexShaderConstants);
+        quad->pVertexShaderConstants = NULL;
+    }
     if (quad->pTexture)
     {
         ID3D11Texture2D_Release(quad->pTexture);
@@ -1958,6 +2223,11 @@ static void Direct3D11DestroyResources(vout_display_t *vd)
         ID3D11VertexShader_Release(sys->flatVSShader);
         sys->flatVSShader = NULL;
     }
+    if (sys->projectionVSShader)
+    {
+        ID3D11VertexShader_Release(sys->projectionVSShader);
+        sys->projectionVSShader = NULL;
+    }
     if (sys->d3drenderTargetView)
     {
         ID3D11RenderTargetView_Release(sys->d3drenderTargetView);
@@ -2086,7 +2356,7 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
                 .textureFormat      = sys->d3dregion_format,
                 .resourceFormatYRGB = sys->d3dregion_format,
             };
-            err = AllocQuad(vd, &r->fmt, d3dquad, &rgbaCfg, sys->pSPUPixelShader, false);
+            err = AllocQuad(vd, &r->fmt, d3dquad, &rgbaCfg, sys->pSPUPixelShader, false, PROJECTION_MODE_RECTANGULAR);
             if (err != VLC_SUCCESS) {
                 msg_Err(vd, "Failed to create %dx%d texture for OSD",
                         r->fmt.i_visible_width, r->fmt.i_visible_height);
-- 
2.10.1



More information about the vlc-devel mailing list