d3d11converter: Use transform matrix for rotation/flip

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5532>
This commit is contained in:
Seungha Yang 2023-10-17 20:05:12 +09:00 committed by GStreamer Marge Bot
parent 745a73eece
commit 769c6a62a4
2 changed files with 156 additions and 128 deletions

View file

@ -173,6 +173,62 @@ struct GammaLut
/* *INDENT-OFF* */
typedef std::shared_ptr<GammaLut> GammaLutPtr;
static const FLOAT g_matrix_identity[] = {
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, 0.0f, 1.0f,
};
static const FLOAT g_matrix_90r[] = {
0.0f, -1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
static const FLOAT g_matrix_180[] = {
-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, 0.0f, 1.0f,
};
static const FLOAT g_matrix_90l[] = {
0.0f, 1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
static const FLOAT g_matrix_horiz[] = {
-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, 0.0f, 1.0f,
};
static const FLOAT g_matrix_vert[] = {
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, 0.0f, 1.0f,
};
static const FLOAT g_matrix_ul_lr[] = {
0.0f, -1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
static const FLOAT g_matrix_ur_ll[] = {
0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
/* *INDENT-ON* */
enum
@ -233,10 +289,12 @@ struct _GstD3D11ConverterPrivate
ComPtr < ID3D11Buffer > vertex_buffer;
ComPtr < ID3D11Buffer > index_buffer;
ComPtr < ID3D11Buffer > const_buffer;
ComPtr < ID3D11Buffer > vs_const_buffer;
ComPtr < ID3D11VertexShader > vs;
ComPtr < ID3D11InputLayout > layout;
ComPtr < ID3D11SamplerState > sampler;
ComPtr < ID3D11SamplerState > linear_sampler;
ComPtr < ID3D11RasterizerState > rasterizer;
PixelShaderList ps;
D3D11_VIEWPORT viewport[GST_VIDEO_MAX_PLANES];
@ -700,6 +758,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self,
GstD3D11ConverterPrivate *priv = self->priv;
GstD3D11Device *device = self->device;
HRESULT hr;
D3D11_RASTERIZER_DESC rasterizer_desc;
D3D11_BUFFER_DESC buffer_desc;
VertexData vertex_data[4];
WORD indices[6];
@ -709,10 +768,13 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self,
ComPtr < ID3D11SamplerState > sampler;
ComPtr < ID3D11SamplerState > linear_sampler;
ComPtr < ID3D11Buffer > const_buffer;
ComPtr < ID3D11Buffer > vs_const_buffer;
ComPtr < ID3D11Buffer > vertex_buffer;
ComPtr < ID3D11Buffer > index_buffer;
ComPtr < ID3D11RasterizerState > rasterizer;
D3D11_SUBRESOURCE_DATA subresource;
memset (&rasterizer_desc, 0, sizeof (rasterizer_desc));
memset (&subresource, 0, sizeof (subresource));
memset (&buffer_desc, 0, sizeof (buffer_desc));
@ -744,7 +806,19 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self,
hr = gst_d3d11_get_converter_vertex_shader (device, &vs, &layout);
if (!gst_d3d11_result (hr, device)) {
GST_ERROR_OBJECT (self, "Couldn't vertex pixel shader");
GST_ERROR_OBJECT (self, "Couldn't create vertex shader");
return FALSE;
}
/* Everything is the same as default but use D3D11_CULL_NONE to render
* back-facing objects too */
rasterizer_desc.FillMode = D3D11_FILL_SOLID;
rasterizer_desc.CullMode = D3D11_CULL_NONE;
rasterizer_desc.DepthClipEnable = TRUE;
hr = device_handle->CreateRasterizerState (&rasterizer_desc, &rasterizer);
if (!gst_d3d11_result (hr, device)) {
GST_ERROR_OBJECT (self, "Couldn't create rasterizer state");
return FALSE;
}
@ -769,6 +843,23 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self,
}
}
G_STATIC_ASSERT (sizeof (g_matrix_identity) % 16 == 0);
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
buffer_desc.ByteWidth = sizeof (g_matrix_identity);
buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
subresource.pSysMem = g_matrix_identity;
subresource.SysMemPitch = sizeof (g_matrix_identity);
hr = device_handle->CreateBuffer (&buffer_desc, &subresource,
&vs_const_buffer);
if (!gst_d3d11_result (hr, device)) {
GST_ERROR_OBJECT (self,
"Couldn't create constant buffer, hr: 0x%x", (guint) hr);
return FALSE;
}
/* bottom left */
vertex_data[0].position.x = -1.0f;
vertex_data[0].position.y = -1.0f;
@ -839,11 +930,13 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self,
priv->vertex_buffer = vertex_buffer;
priv->index_buffer = index_buffer;
priv->const_buffer = const_buffer;
priv->vs_const_buffer = vs_const_buffer;
priv->vs = vs;
priv->layout = layout;
priv->sampler = sampler;
priv->linear_sampler = linear_sampler;
priv->ps = ps_list;
priv->rasterizer = rasterizer;
priv->input_texture_width = GST_VIDEO_INFO_WIDTH (in_info);
priv->input_texture_height = GST_VIDEO_INFO_HEIGHT (in_info);
@ -863,152 +956,57 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self,
return TRUE;
}
static void
gst_d3d11_converter_apply_orientation (GstD3D11Converter * self,
VertexData * vertex_data, gfloat l, gfloat r, gfloat t, gfloat b)
static gboolean
gst_d3d11_converter_apply_orientation (GstD3D11Converter * self)
{
GstD3D11ConverterPrivate *priv = self->priv;
gfloat u[4], v[4];
/*
* 1 (l, t) -- 2 (r, t)
* | |
* 0 (l, b) -- 3 (r, b)
*/
u[0] = l;
u[1] = l;
u[2] = r;
u[3] = r;
v[0] = b;
v[1] = t;
v[2] = t;
v[3] = b;
ID3D11DeviceContext *context_handle;
const FLOAT *matrix = nullptr;
D3D11_MAPPED_SUBRESOURCE map;
HRESULT hr;
switch (priv->video_direction) {
case GST_VIDEO_ORIENTATION_IDENTITY:
case GST_VIDEO_ORIENTATION_AUTO:
case GST_VIDEO_ORIENTATION_CUSTOM:
default:
matrix = g_matrix_identity;
break;
case GST_VIDEO_ORIENTATION_90R:
/*
* 1 (l, t) -- 2 (r, t) 1 (l, b) -- 2 (l, t)
* | | -> | |
* 0 (l, b) -- 3 (r, b) 0 (r, b) -- 3 (r, t)
*/
u[0] = r;
u[1] = l;
u[2] = l;
u[3] = r;
v[0] = b;
v[1] = b;
v[2] = t;
v[3] = t;
matrix = g_matrix_90r;
break;
case GST_VIDEO_ORIENTATION_180:
/*
* 1 (l, t) -- 2 (r, t) 1 (r, b) -- 2 (l, b)
* | | -> | |
* 0 (l, b) -- 3 (r, b) 0 (r, t) -- 3 (l, t)
*/
u[0] = r;
u[1] = r;
u[2] = l;
u[3] = l;
v[0] = t;
v[1] = b;
v[2] = b;
v[3] = t;
matrix = g_matrix_180;
break;
case GST_VIDEO_ORIENTATION_90L:
/*
* 1 (l, t) -- 2 (r, t) 1 (r, t) -- 2 (r, b)
* | | -> | |
* 0 (l, b) -- 3 (r, b) 0 (l, t) -- 3 (l, b)
*/
u[0] = l;
u[1] = r;
u[2] = r;
u[3] = l;
v[0] = t;
v[1] = t;
v[2] = b;
v[3] = b;
matrix = g_matrix_90l;
break;
case GST_VIDEO_ORIENTATION_HORIZ:
/*
* 1 (l, t) -- 2 (r, t) 1 (r, t) -- 2 (l, t)
* | | -> | |
* 0 (l, b) -- 3 (r, b) 0 (r, b) -- 3 (l, b)
*/
u[0] = r;
u[1] = r;
u[2] = l;
u[3] = l;
v[0] = b;
v[1] = t;
v[2] = t;
v[3] = b;
matrix = g_matrix_horiz;
break;
case GST_VIDEO_ORIENTATION_VERT:
/*
* 1 (l, t) -- 2 (r, t) 1 (l, b) -- 2 (r, b)
* | | -> | |
* 0 (l, b) -- 3 (r, b) 0 (l, t) -- 3 (r, t)
*/
u[0] = l;
u[1] = l;
u[2] = r;
u[3] = r;
v[0] = t;
v[1] = b;
v[2] = b;
v[3] = t;
matrix = g_matrix_vert;
break;
case GST_VIDEO_ORIENTATION_UL_LR:
/*
* 1 (l, t) -- 2 (r, t) 1 (l, t) -- 2 (l, b)
* | | -> | |
* 0 (l, b) -- 3 (r, b) 0 (r, t) -- 3 (r, b)
*/
u[0] = r;
u[1] = l;
u[2] = l;
u[3] = r;
v[0] = t;
v[1] = t;
v[2] = b;
v[3] = b;
matrix = g_matrix_ul_lr;
break;
case GST_VIDEO_ORIENTATION_UR_LL:
/*
* 1 (l, t) -- 2 (r, t) 1 (r, b) -- 2 (r, t)
* | | -> | |
* 0 (l, b) -- 3 (r, b) 0 (l, b) -- 3 (l, t)
*/
u[0] = l;
u[1] = r;
u[2] = r;
u[3] = l;
v[0] = b;
v[1] = b;
v[2] = t;
v[3] = t;
matrix = g_matrix_ur_ll;
break;
}
for (guint i = 0; i < 4; i++) {
vertex_data[i].texture.u = u[i];
vertex_data[i].texture.v = v[i];
}
context_handle = gst_d3d11_device_get_device_context_handle (self->device);
hr = context_handle->Map (priv->vs_const_buffer.Get (), 0,
D3D11_MAP_WRITE_DISCARD, 0, &map);
if (!gst_d3d11_result (hr, self->device))
return FALSE;
memcpy (map.pData, matrix, sizeof (FLOAT) * 16);
context_handle->Unmap (priv->vs_const_buffer.Get (), 0);
return TRUE;
}
static gboolean
@ -1144,27 +1142,33 @@ gst_d3d11_converter_update_src_rect (GstD3D11Converter * self)
vertex_data[0].position.x = -1.0f;
vertex_data[0].position.y = -1.0f;
vertex_data[0].position.z = 0.0f;
vertex_data[0].texture.u = u0;
vertex_data[0].texture.v = v1;
/* top left */
vertex_data[1].position.x = -1.0f;
vertex_data[1].position.y = 1.0f;
vertex_data[1].position.z = 0.0f;
vertex_data[1].texture.u = u0;
vertex_data[1].texture.v = v0;
/* top right */
vertex_data[2].position.x = 1.0f;
vertex_data[2].position.y = 1.0f;
vertex_data[2].position.z = 0.0f;
vertex_data[2].texture.u = u1;
vertex_data[2].texture.v = v0;
/* bottom right */
vertex_data[3].position.x = 1.0f;
vertex_data[3].position.y = -1.0f;
vertex_data[3].position.z = 0.0f;
gst_d3d11_converter_apply_orientation (self, vertex_data, u0, u1, v0, v1);
vertex_data[3].texture.u = u1;
vertex_data[3].texture.v = v1;
context_handle->Unmap (priv->vertex_buffer.Get (), 0);
return TRUE;
return gst_d3d11_converter_apply_orientation (self);
}
static gboolean
@ -2190,7 +2194,6 @@ gst_d3d11_converter_convert_internal (GstD3D11Converter * self,
context->IASetPrimitiveTopology (D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D11Buffer *vertex[] = { priv->vertex_buffer.Get () };
context->IASetInputLayout (priv->layout.Get ());
context->IASetVertexBuffers (0, 1, vertex, &vertex_stride, &offsets);
context->IASetIndexBuffer (priv->index_buffer.Get (),
DXGI_FORMAT_R16_UINT, 0);
@ -2199,7 +2202,11 @@ gst_d3d11_converter_convert_internal (GstD3D11Converter * self,
priv->linear_sampler.Get ()
};
context->PSSetSamplers (0, 2, samplers);
ID3D11Buffer *vs_const_buffer[] = { priv->vs_const_buffer.Get () };
context->IASetInputLayout (priv->layout.Get ());
context->VSSetShader (priv->vs.Get (), nullptr, 0);
context->VSSetConstantBuffers (0, 1, vs_const_buffer);
if (priv->const_buffer) {
ID3D11Buffer *const_buffer[] = { priv->const_buffer.Get () };
@ -2217,6 +2224,7 @@ gst_d3d11_converter_convert_internal (GstD3D11Converter * self,
auto ps = priv->ps[0];
context->PSSetShader (ps->shader.Get (), nullptr, 0);
context->RSSetViewports (ps->num_rtv, priv->viewport);
context->RSSetState (priv->rasterizer.Get ());
context->OMSetRenderTargets (ps->num_rtv, rtv, nullptr);
if (priv->blend) {
context->OMSetBlendState (priv->blend.Get (),

View file

@ -18,6 +18,11 @@
*/
#ifdef BUILDING_HLSL
cbuffer VsConstBuffer : register(b0)
{
matrix Transform;
};
struct VS_INPUT
{
float4 Position : POSITION;
@ -32,10 +37,20 @@ struct VS_OUTPUT
VS_OUTPUT VSMain_converter (VS_INPUT input)
{
return input;
VS_OUTPUT output;
output.Position = mul (Transform, input.Position);
output.Texture = input.Texture;
return output;
}
#else
static const char g_VSMain_converter_str[] =
"cbuffer VsConstBuffer : register(b0)\n"
"{\n"
" matrix Transform;\n"
"};\n"
"\n"
"struct VS_INPUT\n"
"{\n"
" float4 Position : POSITION;\n"
@ -50,6 +65,11 @@ static const char g_VSMain_converter_str[] =
"\n"
"VS_OUTPUT VSMain_converter (VS_INPUT input)\n"
"{\n"
" return input;\n"
" VS_OUTPUT output;\n"
"\n"
" output.Position = mul (Transform, input.Position);\n"
" output.Texture = input.Texture;\n"
"\n"
" return output;\n"
"}\n";
#endif