d3d11: Move transform matrix related method to utils

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5572>
This commit is contained in:
Seungha Yang 2023-10-28 20:15:34 +09:00
parent 3a2a31d18b
commit 1813b4e3d9
3 changed files with 161 additions and 127 deletions

View file

@ -30,11 +30,16 @@
#include "hlsl/gstd3d11plugin-hlsl.h"
/* Disable platform-specific intrinsics */
#define _XM_NO_INTRINSICS_
#include <DirectXMath.h>
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_plugin_utils_debug);
#define GST_CAT_DEFAULT gst_d3d11_plugin_utils_debug
/* *INDENT-OFF* */
using namespace Microsoft::WRL;
using namespace DirectX;
/* *INDENT-ON* */
/**
@ -941,3 +946,135 @@ gst_d3d11_get_vertex_shader_pos (GstD3D11Device * device,
g_VSMain_pos_str, sizeof (g_VSMain_pos_str), "VSMain_pos", &input_desc, 1,
vs, layout);
}
gboolean
gst_d3d11_need_transform (gfloat rotation_x, gfloat rotation_y,
gfloat rotation_z, gfloat scale_x, gfloat scale_y)
{
const gfloat min_diff = 0.00001f;
if (!XMScalarNearEqual (rotation_x, 0.0f, min_diff) ||
!XMScalarNearEqual (rotation_y, 0.0f, min_diff) ||
!XMScalarNearEqual (rotation_z, 0.0f, min_diff) ||
!XMScalarNearEqual (scale_x, 1.0f, min_diff) ||
!XMScalarNearEqual (scale_y, 1.0f, min_diff)) {
return TRUE;
}
return FALSE;
}
static const XMFLOAT4X4 g_matrix_90r = XMFLOAT4X4 (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 XMFLOAT4X4 g_matrix_180 = XMFLOAT4X4 (-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 XMFLOAT4X4 g_matrix_90l = XMFLOAT4X4 (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 XMFLOAT4X4 g_matrix_horiz = XMFLOAT4X4 (-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 XMFLOAT4X4 g_matrix_vert = XMFLOAT4X4 (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 XMFLOAT4X4 g_matrix_ul_lr = XMFLOAT4X4 (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 XMFLOAT4X4 g_matrix_ur_ll = XMFLOAT4X4 (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);
void
gst_d3d11_calculate_transform_matrix (GstVideoOrientationMethod method,
gfloat viewport_width, gfloat viewport_height, gfloat fov, gboolean ortho,
gfloat rotation_x, gfloat rotation_y, gfloat rotation_z,
gfloat scale_x, gfloat scale_y, gfloat transform_matrix[16])
{
gfloat aspect_ratio;
gboolean rotated = FALSE;
XMMATRIX rotate_matrix = XMMatrixIdentity ();
switch (method) {
case GST_VIDEO_ORIENTATION_IDENTITY:
case GST_VIDEO_ORIENTATION_AUTO:
case GST_VIDEO_ORIENTATION_CUSTOM:
default:
break;
case GST_VIDEO_ORIENTATION_90R:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_90r);
rotated = TRUE;
break;
case GST_VIDEO_ORIENTATION_180:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_180);
break;
case GST_VIDEO_ORIENTATION_90L:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_90l);
rotated = TRUE;
break;
case GST_VIDEO_ORIENTATION_HORIZ:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_horiz);
break;
case GST_VIDEO_ORIENTATION_VERT:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_vert);
break;
case GST_VIDEO_ORIENTATION_UL_LR:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_ul_lr);
rotated = TRUE;
break;
case GST_VIDEO_ORIENTATION_UR_LL:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_ur_ll);
rotated = TRUE;
break;
}
if (rotated)
aspect_ratio = viewport_height / viewport_width;
else
aspect_ratio = viewport_width / viewport_height;
/* Apply user specified transform matrix first, then rotate-method */
XMMATRIX scale = XMMatrixScaling (scale_x * aspect_ratio, scale_y, 1.0);
XMMATRIX rotate =
XMMatrixRotationX (XMConvertToRadians (rotation_x)) *
XMMatrixRotationY (XMConvertToRadians (-rotation_y)) *
XMMatrixRotationZ (XMConvertToRadians (-rotation_z));
XMMATRIX view = XMMatrixLookAtLH (XMVectorSet (0.0, 0.0, -1.0, 0.0),
XMVectorSet (0.0, 0.0, 0.0, 0.0), XMVectorSet (0.0, 1.0, 0.0, 0.0));
XMMATRIX proj;
if (ortho) {
proj = XMMatrixOrthographicOffCenterLH (-aspect_ratio,
aspect_ratio, -1.0, 1.0, 0.1, 100.0);
} else {
proj = XMMatrixPerspectiveFovLH (XMConvertToRadians (fov),
aspect_ratio, 0.1, 100.0);
}
XMMATRIX mvp = scale * rotate * view * proj * rotate_matrix;
XMFLOAT4X4 matrix;
XMStoreFloat4x4 (&matrix, mvp);
for (guint i = 0; i < 4; i++) {
for (guint j = 0; j < 4; j++) {
transform_matrix[i * 4 + j] = matrix.m[i][j];
}
}
}

View file

@ -148,6 +148,24 @@ HRESULT gst_d3d11_get_vertex_shader_pos (GstD3D11Device * device,
ID3D11VertexShader ** vs,
ID3D11InputLayout ** layout);
gboolean gst_d3d11_need_transform (gfloat rotation_x,
gfloat rotation_y,
gfloat rotation_z,
gfloat scale_x,
gfloat scale_y);
void gst_d3d11_calculate_transform_matrix (GstVideoOrientationMethod method,
gfloat viewport_width,
gfloat viewport_height,
gfloat fov,
gboolean ortho,
gfloat rotation_x,
gfloat rotation_y,
gfloat rotation_z,
gfloat scale_x,
gfloat scale_y,
gfloat transform_matrix[16]);
G_END_DECLS
#endif /* __GST_D3D11_PLUGIN_UTILS_H__ */

View file

@ -36,13 +36,8 @@
#include <wrl.h>
/* Disable platform-specific intrinsics */
#define _XM_NO_INTRINSICS_
#include <DirectXMath.h>
/* *INDENT-OFF* */
using namespace Microsoft::WRL;
using namespace DirectX;
/* *INDENT-ON* */
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_window_debug);
@ -912,120 +907,6 @@ gst_d3d11_window_set_title (GstD3D11Window * window, const gchar * title)
klass->set_title (window, title);
}
static const XMFLOAT4X4 g_matrix_90r = XMFLOAT4X4 (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 XMFLOAT4X4 g_matrix_180 = XMFLOAT4X4 (-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 XMFLOAT4X4 g_matrix_90l = XMFLOAT4X4 (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 XMFLOAT4X4 g_matrix_horiz = XMFLOAT4X4 (-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 XMFLOAT4X4 g_matrix_vert = XMFLOAT4X4 (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 XMFLOAT4X4 g_matrix_ul_lr = XMFLOAT4X4 (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 XMFLOAT4X4 g_matrix_ur_ll = XMFLOAT4X4 (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 void
gst_d3d11_window_calculate_matrix (GstD3D11Window * self,
gfloat viewport_width, gfloat viewport_height, gfloat transform_matrix[16])
{
gfloat aspect_ratio;
gboolean rotated = FALSE;
XMMATRIX rotate_matrix = XMMatrixIdentity ();
switch (self->method) {
case GST_VIDEO_ORIENTATION_IDENTITY:
case GST_VIDEO_ORIENTATION_AUTO:
case GST_VIDEO_ORIENTATION_CUSTOM:
default:
break;
case GST_VIDEO_ORIENTATION_90R:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_90r);
rotated = TRUE;
break;
case GST_VIDEO_ORIENTATION_180:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_180);
break;
case GST_VIDEO_ORIENTATION_90L:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_90l);
rotated = TRUE;
break;
case GST_VIDEO_ORIENTATION_HORIZ:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_horiz);
break;
case GST_VIDEO_ORIENTATION_VERT:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_vert);
break;
case GST_VIDEO_ORIENTATION_UL_LR:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_ul_lr);
rotated = TRUE;
break;
case GST_VIDEO_ORIENTATION_UR_LL:
rotate_matrix = XMLoadFloat4x4 (&g_matrix_ur_ll);
rotated = TRUE;
break;
}
if (rotated)
aspect_ratio = viewport_height / viewport_width;
else
aspect_ratio = viewport_width / viewport_height;
/* Apply user specified transform matrix first, then rotate-method */
XMMATRIX scale =
XMMatrixScaling (self->scale_x * aspect_ratio, self->scale_y, 1.0);
XMMATRIX rotate =
XMMatrixRotationX (XMConvertToRadians (self->rotation_x)) *
XMMatrixRotationY (XMConvertToRadians (-self->rotation_y)) *
XMMatrixRotationZ (XMConvertToRadians (-self->rotation_z));
XMMATRIX view = XMMatrixLookAtLH (XMVectorSet (0.0, 0.0, -1.0, 0.0),
XMVectorSet (0.0, 0.0, 0.0, 0.0), XMVectorSet (0.0, 1.0, 0.0, 0.0));
XMMATRIX proj;
if (self->ortho) {
proj = XMMatrixOrthographicOffCenterLH (-aspect_ratio,
aspect_ratio, -1.0, 1.0, 0.1, 100.0);
} else {
proj = XMMatrixPerspectiveFovLH (XMConvertToRadians (self->fov),
aspect_ratio, 0.1, 100.0);
}
XMMATRIX mvp = scale * rotate * view * proj * rotate_matrix;
XMFLOAT4X4 matrix;
XMStoreFloat4x4 (&matrix, mvp);
for (guint i = 0; i < 4; i++) {
for (guint j = 0; j < 4; j++) {
transform_matrix[i * 4 + j] = matrix.m[i][j];
}
}
}
static GstFlowReturn
gst_d3d11_window_present (GstD3D11Window * self, GstBuffer * buffer,
GstBuffer * backbuffer, GstBuffer * multisample)
@ -1098,7 +979,6 @@ gst_d3d11_window_present (GstD3D11Window * self, GstBuffer * buffer,
if (self->first_present) {
D3D11_VIEWPORT viewport;
const gfloat min_diff = 0.00001f;
viewport.TopLeftX = self->render_rect.left;
viewport.TopLeftY = self->render_rect.top;
@ -1114,19 +994,18 @@ gst_d3d11_window_present (GstD3D11Window * self, GstBuffer * buffer,
"dest-height",
(gint) (self->render_rect.bottom - self->render_rect.top), nullptr);
if (!XMScalarNearEqual (self->rotation_x, 0.0f, min_diff) &&
!XMScalarNearEqual (self->rotation_y, 0.0f, min_diff) &&
!XMScalarNearEqual (self->rotation_z, 0.0f, min_diff) &&
!XMScalarNearEqual (self->scale_x, 1.0f, min_diff) &&
!XMScalarNearEqual (self->scale_y, 1.0f, min_diff)) {
if (!gst_d3d11_need_transform (self->rotation_x, self->rotation_y,
self->rotation_z, self->scale_x, self->scale_y)) {
g_object_set (self->converter, "video-direction", self->method, nullptr);
} else {
gfloat transform_matrix[16];
GST_DEBUG_OBJECT (self, "Applying custom transform");
gst_d3d11_window_calculate_matrix (self,
viewport.Width, viewport.Height, transform_matrix);
gst_d3d11_calculate_transform_matrix (self->method,
viewport.Width, viewport.Height, self->fov, self->ortho,
self->rotation_x, self->rotation_y, self->rotation_z,
self->scale_x, self->scale_y, transform_matrix);
g_object_set (self->converter,
"video-direction", GST_VIDEO_ORIENTATION_CUSTOM, nullptr);
gst_d3d11_converter_set_transform_matrix (self->converter,