diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11-private.h b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11-private.h index 24e44c7d8b..4006b5fec4 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11-private.h +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11-private.h @@ -160,6 +160,9 @@ typedef struct _GstD3D11ColorMatrix gdouble max[3]; } GstD3D11ColorMatrix; +GST_D3D11_API +void gst_d3d11_color_matrix_init (GstD3D11ColorMatrix * matrix); + GST_D3D11_API gchar * gst_d3d11_dump_color_matrix (GstD3D11ColorMatrix * matrix); diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converter.cpp b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converter.cpp index 781fb86e47..a51ce86f63 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converter.cpp +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converter.cpp @@ -24,12 +24,14 @@ #endif #include "gstd3d11-private.h" +#include "gstd3d11device-private.h" #include "gstd3d11converter.h" #include "gstd3d11device.h" #include "gstd3d11utils.h" #include "gstd3d11memory.h" #include "gstd3d11compile.h" #include "gstd3d11bufferpool.h" +#include "gstd3d11converterbuilder.h" #include #include #include @@ -127,8 +129,7 @@ using namespace Microsoft::WRL; /* D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_MIRROR */ #define PROCESSOR_FEATURE_CAPS_MIRROR (0x200) -/* *INDENT-OFF* */ -typedef struct +struct PSColorSpace { /* + 1 for 16bytes alignment */ FLOAT coeffX[4]; @@ -137,512 +138,32 @@ typedef struct FLOAT offset[4]; FLOAT min[4]; FLOAT max[4]; -} PSColorSpace; +}; -typedef struct +struct PSConstBuffer { - PSColorSpace to_rgb_buf; - PSColorSpace to_yuv_buf; - PSColorSpace XYZ_convert_buf; + PSColorSpace preCoeff; + PSColorSpace postCoeff; + PSColorSpace primariesCoeff; FLOAT alpha; - DWORD in_premul_alpha; - DWORD out_premul_alpha; - FLOAT padding; -} PSConstBuffer; + FLOAT padding[3]; +}; -typedef struct +struct VertexData { - struct { + struct + { FLOAT x; FLOAT y; FLOAT z; } position; - struct { + struct + { FLOAT u; FLOAT v; } texture; -} VertexData; - -/* output struct */ -static const gchar templ_OUTPUT_SINGLE_PLANE[] = - "struct PS_OUTPUT\n" - "{\n" - " float4 Plane_0: SV_TARGET0;\n" - "};"; - -static const gchar templ_OUTPUT_TWO_PLANES[] = - "struct PS_OUTPUT\n" - "{\n" - " float4 Plane_0: SV_TARGET0;\n" - " float4 Plane_1: SV_TARGET1;\n" - "};"; - -static const gchar templ_OUTPUT_THREE_PLANES[] = - "struct PS_OUTPUT\n" - "{\n" - " float4 Plane_0: SV_TARGET0;\n" - " float4 Plane_1: SV_TARGET1;\n" - " float4 Plane_2: SV_TARGET2;\n" - "};"; - -static const gchar templ_OUTPUT_FOUR_PLANES[] = - "struct PS_OUTPUT\n" - "{\n" - " float4 Plane_0: SV_TARGET0;\n" - " float4 Plane_1: SV_TARGET1;\n" - " float4 Plane_2: SV_TARGET2;\n" - " float4 Plane_3: SV_TARGET3;\n" - "};"; - -typedef struct -{ - const gchar *output_template; - guint num_rtv; -} PSOutputType; - -enum -{ - OUTPUT_SINGLE_PLANE = 0, - OUTPUT_TWO_PLANES, - OUTPUT_THREE_PLANES, - OUTPUT_FOUR_PLANES, }; -static const PSOutputType output_types[] = { - {templ_OUTPUT_SINGLE_PLANE, 1}, - {templ_OUTPUT_TWO_PLANES, 2}, - {templ_OUTPUT_THREE_PLANES, 3}, - {templ_OUTPUT_FOUR_PLANES, 4}, -}; - -/* colorspace conversion */ -static const gchar templ_COLOR_SPACE_IDENTITY[] = - "{\n" - " return sample;\n" - "}"; - -static const gchar templ_COLOR_SPACE_CONVERT[] = - "{\n" - " float3 out_space;\n" - " out_space.x = dot (coeff.CoeffX, sample);\n" - " out_space.y = dot (coeff.CoeffY, sample);\n" - " out_space.z = dot (coeff.CoeffZ, sample);\n" - " out_space += coeff.Offset;\n" - " return clamp (out_space, coeff.Min, coeff.Max);\n" - "}"; - -static const gchar templ_COLOR_SPACE_CONVERT_LUMA[] = - "{\n" - " float3 out_space;\n" - " out_space.x = dot (coeff.CoeffX, sample) + coeff.Offset.x;\n" - " out_space.x = clamp (out_space.x, coeff.Min.x, coeff.Max.x);\n" - " out_space.y = 0.5;\n" - " out_space.z = 0.5;\n" - " return out_space;\n" - "}"; - -static const gchar templ_COLOR_SPACE_CONVERT_CHROMA[] = - "{\n" - " float3 out_space;\n" - " out_space.x = 0.0;\n" - " out_space.y = dot (coeff.CoeffY, sample) + coeff.Offset.y;\n" - " out_space.z = dot (coeff.CoeffZ, sample) + coeff.Offset.z;\n" - " return clamp (out_space, coeff.Min, coeff.Max);\n" - "}"; - -static const gchar templ_COLOR_SPACE_GRAY_TO_RGB[] = - "{\n" - " return float3 (sample.x, sample.x, sample.x);\n" - "}"; - -static const gchar templ_COLOR_SPACE_GRAY_TO_RGB_RANGE_ADJUST[] = - "{\n" - " float gray;\n" - " gray = coeff.CoeffX.x * sample.x + coeff.Offset.x;\n" - " gray = clamp (gray, coeff.Min.x, coeff.Max.x);\n" - " return float3 (gray, gray, gray);\n" - "}"; - -/* sampling */ -static const gchar templ_SAMPLE_DEFAULT[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " return shaderTexture[0].Sample(samplerState, uv);\n" - "}"; - -static const gchar templ_SAMPLE_VUYA[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " return shaderTexture[0].Sample(samplerState, uv).%c%c%c%c;\n" - "}"; - -static const gchar templ_SAMPLE_YUV_LUMA[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " float4 sample;\n" - " sample.x = shaderTexture[0].Sample(samplerState, uv).x;\n" - " sample.y = 0.5;\n" - " sample.z = 0.5;\n" - " sample.a = 1.0;\n" - " return sample;\n" - "}"; - -static const gchar templ_SAMPLE_YUV_LUMA_SCALED[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " float4 sample;\n" - " sample.x = saturate (shaderTexture[0].Sample(samplerState, uv).x * %d);\n" - " sample.y = 0.5;\n" - " sample.z = 0.5;\n" - " sample.a = 1.0;\n" - " return sample;\n" - "}"; - -static const gchar templ_SAMPLE_SEMI_PLANAR[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " float4 sample;\n" - " sample.x = shaderTexture[0].Sample(samplerState, uv).x;\n" - " sample.yz = shaderTexture[1].Sample(samplerState, uv).%c%c;\n" - " sample.a = 1.0;\n" - " return sample;\n" - "}"; - -static const gchar templ_SAMPLE_SEMI_PLANAR_CHROMA[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " float4 sample;\n" - " sample.x = 0.0;\n" - " sample.yz = shaderTexture[1].Sample(samplerState, uv).%c%c;\n" - " sample.a = 1.0;\n" - " return sample;\n" - "}"; - -static const gchar templ_SAMPLE_PLANAR[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " float3 sample;\n" - " sample.%c = shaderTexture[0].Sample(samplerState, uv).x;\n" - " sample.%c = shaderTexture[1].Sample(samplerState, uv).x;\n" - " sample.%c = shaderTexture[2].Sample(samplerState, uv).x;\n" - " return float4 (saturate(sample * %d), 1.0);\n" - "}"; - -static const gchar templ_SAMPLE_PLANAR_4[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " float4 sample;\n" - " sample.%c = shaderTexture[0].Sample(samplerState, uv).x;\n" - " sample.%c = shaderTexture[1].Sample(samplerState, uv).x;\n" - " sample.%c = shaderTexture[2].Sample(samplerState, uv).x;\n" - " sample.%c = shaderTexture[3].Sample(samplerState, uv).x;\n" - " return saturate(sample * %d);\n" - "}"; - -static const gchar templ_SAMPLE_PLANAR_CHROMA[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " float3 sample;\n" - " sample.x = 0.0;\n" - " sample.%c = shaderTexture[1].Sample(samplerState, uv).x;\n" - " sample.%c = shaderTexture[2].Sample(samplerState, uv).x;\n" - " return float4 (saturate(sample * %d), 1.0);\n" - "}"; - -static const gchar templ_SAMPLE_YUV_PACKED[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " float4 sample;\n" - " sample.xyz = shaderTexture[0].Sample(samplerState, uv).%c%c%c;\n" - " sample.a = 1.0;\n" - " return sample;\n" - "}"; - -static const gchar templ_SAMPLE_GRAY[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " float4 sample;\n" - " sample.x = shaderTexture[0].Sample(samplerState, uv).x;\n" - " sample.y = 0.5;\n" - " sample.z = 0.5;\n" - " sample.a = 1.0;\n" - " return sample;\n" - "}"; - -static const gchar templ_SAMPLE_GRAY_CHROMA[] = - "float4 sample_texture (float2 uv)\n" - "{\n" - " return float4 (0.0, 0.5, 0.5, 1.0);\n" - "}"; - -/* building output */ -static const gchar templ_OUTPUT_DEFAULT[] = - "PS_OUTPUT build_output (float4 sample)\n" - "{\n" - " PS_OUTPUT output;\n" - " output.Plane_0 = sample;\n" - " return output;\n" - "}"; - -static const gchar templ_OUTPUT_VUYA[] = - "PS_OUTPUT build_output (float4 sample)\n" - "{\n" - " PS_OUTPUT output;\n" - " float4 vuya;\n" - " vuya.%c%c%c = sample.xyz;\n" - " vuya.%c = sample.a;\n" - " output.Plane_0 = vuya;\n" - " return output;\n" - "}"; - -static const gchar templ_OUTPUT_LUMA[] = - "PS_OUTPUT build_output (float4 sample)\n" - "{\n" - " PS_OUTPUT output;\n" - " output.Plane_0 = float4 (sample.x, 0.0, 0.0, 1.0);\n" - " return output;\n" - "}"; - -static const gchar templ_OUTPUT_CHROMA_SEMI_PLANAR[] = - "PS_OUTPUT build_output (float4 sample)\n" - "{\n" - " PS_OUTPUT output;\n" - " output.Plane_0 = float4 (sample.%c%c, 0.0, 1.0);\n" - " return output;\n" - "}"; - -static const gchar templ_OUTPUT_LUMA_SCALED[] = - "PS_OUTPUT build_output (float4 sample)\n" - "{\n" - " PS_OUTPUT output;\n" - " output.Plane_0 = float4 (sample.x / %d, 0.0, 0.0, 1.0);\n" - " return output;\n" - "}"; - -static const gchar templ_OUTPUT_CHROMA_PLANAR[] = - "PS_OUTPUT build_output (float4 sample)\n" - "{\n" - " PS_OUTPUT output;\n" - " output.Plane_0 = float4 (sample.%c, 0.0, 0.0, 1.0);\n" - " output.Plane_1 = float4 (sample.%c, 0.0, 0.0, 1.0);\n" - " return output;\n" - "}"; - -static const gchar templ_OUTPUT_CHROMA_PLANAR_SCALED[] = - "PS_OUTPUT build_output (float4 sample)\n" - "{\n" - " PS_OUTPUT output;\n" - " output.Plane_0 = float4 (sample.%c / %d, 0.0, 0.0, 1.0);\n" - " output.Plane_1 = float4 (sample.%c / %d, 0.0, 0.0, 1.0);\n" - " return output;\n" - "}"; - -static const gchar templ_OUTPUT_PLANAR[] = - "PS_OUTPUT build_output (float4 sample)\n" - "{\n" - " PS_OUTPUT output;\n" - " output.Plane_0 = float4 (sample.%c, 0.0, 0.0, 1.0);\n" - " output.Plane_1 = float4 (sample.%c, 0.0, 0.0, 1.0);\n" - " output.Plane_2 = float4 (sample.%c, 0.0, 0.0, 1.0);\n" - " return output;\n" - "}"; - -static const gchar templ_OUTPUT_PLANAR_SCALED[] = - "PS_OUTPUT build_output (float4 sample)\n" - "{\n" - " PS_OUTPUT output;\n" - " float3 scaled = sample.xyz / %d;\n" - " output.Plane_0 = float4 (scaled.%c, 0.0, 0.0, 1.0);\n" - " output.Plane_1 = float4 (scaled.%c, 0.0, 0.0, 1.0);\n" - " output.Plane_2 = float4 (scaled.%c, 0.0, 0.0, 1.0);\n" - " return output;\n" - "}"; - -static const gchar templ_OUTPUT_PLANAR_4[] = - "PS_OUTPUT build_output (float4 sample)\n" - "{\n" - " PS_OUTPUT output;\n" - " output.Plane_0 = float4 (sample.%c, 0.0, 0.0, 1.0);\n" - " output.Plane_1 = float4 (sample.%c, 0.0, 0.0, 1.0);\n" - " output.Plane_2 = float4 (sample.%c, 0.0, 0.0, 1.0);\n" - " output.Plane_3 = float4 (sample.%c, 0.0, 0.0, 1.0);\n" - " return output;\n" - "}"; - -static const gchar templ_OUTPUT_PLANAR_4_SCALED[] = - "PS_OUTPUT build_output (float4 sample)\n" - "{\n" - " PS_OUTPUT output;\n" - " float4 scaled = sample / %d;\n" - " output.Plane_0 = float4 (scaled.%c, 0.0, 0.0, 1.0);\n" - " output.Plane_1 = float4 (scaled.%c, 0.0, 0.0, 1.0);\n" - " output.Plane_2 = float4 (scaled.%c, 0.0, 0.0, 1.0);\n" - " output.Plane_3 = float4 (scaled.%c, 0.0, 0.0, 1.0);\n" - " return output;\n" - "}"; - -/* gamma and XYZ convert */ -static const gchar templ_GAMMA_DECODE_IDENTITY[] = - "float3 gamma_decode (float3 sample)\n" - "{\n" - " return sample;\n" - "}"; - -static const gchar templ_GAMMA_DECODE[] = - "float3 gamma_decode (float3 sample)\n" - "{\n" - " float3 dec;\n" - " dec.x = gammaDecLUT.Sample (samplerState, sample.x);\n" - " dec.y = gammaDecLUT.Sample (samplerState, sample.y);\n" - " dec.z = gammaDecLUT.Sample (samplerState, sample.z);\n" - " return dec;\n" - "}"; - -static const gchar templ_GAMMA_ENCODE_IDENTITY[] = - "float3 gamma_encode (float3 sample)\n" - "{\n" - " return sample;\n" - "}"; - -static const gchar templ_GAMMA_ENCODE[] = - "float3 gamma_encode (float3 sample)\n" - "{\n" - " float3 enc;\n" - " enc.x = gammaEncLUT.Sample (samplerState, sample.x);\n" - " enc.y = gammaEncLUT.Sample (samplerState, sample.y);\n" - " enc.z = gammaEncLUT.Sample (samplerState, sample.z);\n" - " return enc;\n" - "}"; - -static const gchar templ_XYZ_CONVERT_IDENTITY[] = - "float3 XYZ_convert (float3 sample)\n" - "{\n" - " return sample;\n" - "}"; - -static const gchar templ_XYZ_CONVERT[] = - "float3 XYZ_convert (float3 sample)\n" - "{\n" - " float3 out_space;\n" - " out_space.x = dot (primariesCoeff.CoeffX, sample);\n" - " out_space.y = dot (primariesCoeff.CoeffY, sample);\n" - " out_space.z = dot (primariesCoeff.CoeffZ, sample);\n" - " return saturate (out_space);\n" - "}"; - -static const gchar templ_pixel_shader[] = - "struct PSColorSpace\n" - "{\n" - " float3 CoeffX;\n" - " float3 CoeffY;\n" - " float3 CoeffZ;\n" - " float3 Offset;\n" - " float3 Min;\n" - " float3 Max;\n" - " float padding;\n" - "};\n" - "cbuffer PsConstBuffer : register(b0)\n" - "{\n" - /* RGB <-> YUV conversion */ - " PSColorSpace toRGBCoeff;\n" - " PSColorSpace toYUVCoeff;\n" - " PSColorSpace primariesCoeff;\n" - " float AlphaMul;\n" - " dword InPremulAlpha;\n" - " dword OutPremulAlpha;\n" - "};\n" - "Texture2D shaderTexture[4] : register(t0);\n" - "Texture1D gammaDecLUT: register(t4);\n" - "Texture1D gammaEncLUT: register(t5);\n" - "SamplerState samplerState : register(s0);\n" - "struct PS_INPUT\n" - "{\n" - " float4 Position: SV_POSITION;\n" - " float2 Texture: TEXCOORD;\n" - "};\n" - /* struct PS_OUTPUT */ - "%s\n" - /* sample_texture() function */ - "%s\n" - "float3 to_rgb (float3 sample, PSColorSpace coeff)\n" - "%s\n" - "float3 to_yuv (float3 sample, PSColorSpace coeff)\n" - "%s\n" - /* build_output() function */ - "%s\n" - /* gamma_decode() function */ - "%s\n" - /* gamma_encode() function */ - "%s\n" - /* XYZ_convert() function */ - "%s\n" - "float4 alpha_premul (float4 sample)\n" - "{\n" - " float4 premul_tex;\n" - " premul_tex.r = sample.r * sample.a;\n" - " premul_tex.g = sample.g * sample.a;\n" - " premul_tex.b = sample.b * sample.a;\n" - " premul_tex.a = sample.a;\n" - " return premul_tex;\n" - "}\n" - "float4 alpha_unpremul (float4 sample)\n" - "{\n" - " float4 unpremul_tex;\n" - " if (sample.a == 0 || sample.a == 1)\n" - " return sample;\n" - " unpremul_tex.r = saturate (sample.r / sample.a);\n" - " unpremul_tex.g = saturate (sample.g / sample.a);\n" - " unpremul_tex.b = saturate (sample.b / sample.a);\n" - " unpremul_tex.a = sample.a;\n" - " return unpremul_tex;\n" - "}\n" - "PS_OUTPUT main(PS_INPUT input)\n" - "{\n" - " float4 sample;\n" - " sample = sample_texture (input.Texture);\n" - " if (InPremulAlpha)\n" - " sample = alpha_unpremul (sample);\n" - " sample.a = saturate (sample.a * AlphaMul);\n" - " sample.xyz = to_rgb (sample.xyz, toRGBCoeff);\n" - " sample.xyz = gamma_decode (sample.xyz);\n" - " sample.xyz = XYZ_convert (sample.xyz);\n" - " sample.xyz = gamma_encode (sample.xyz);\n" - " sample.xyz = to_yuv (sample.xyz, toYUVCoeff);\n" - " if (OutPremulAlpha)\n" - " sample = alpha_premul (sample);\n" - " return build_output (sample);\n" - "}\n"; - -static const gchar templ_vertex_shader[] = - "struct VS_INPUT\n" - "{\n" - " float4 Position : POSITION;\n" - " float2 Texture : TEXCOORD;\n" - "};\n" - "\n" - "struct VS_OUTPUT\n" - "{\n" - " float4 Position: SV_POSITION;\n" - " float2 Texture: TEXCOORD;\n" - "};\n" - "\n" - "VS_OUTPUT main(VS_INPUT input)\n" - "{\n" - " return input;\n" - "}\n"; -/* *INDENT-ON* */ - -typedef struct -{ - const PSOutputType *ps_output[CONVERTER_MAX_QUADS]; - gchar *sample_texture_func[CONVERTER_MAX_QUADS]; - const gchar *to_rgb_func[CONVERTER_MAX_QUADS]; - const gchar *to_yuv_func[CONVERTER_MAX_QUADS]; - gchar *build_output_func[CONVERTER_MAX_QUADS]; - const gchar *gamma_decode_func; - const gchar *gamma_encode_func; - const gchar *XYZ_convert_func; -} ConvertInfo; enum { @@ -673,36 +194,49 @@ enum struct _GstD3D11ConverterPrivate { + ~_GstD3D11ConverterPrivate () + { + g_free (in_mdcv_str); + g_free (out_mdcv_str); + g_free (in_cll_str); + g_free (out_cll_str); + + if (unpack_convert) + gst_video_converter_free (unpack_convert); + + gst_clear_buffer (&piv_inbuf); + gst_clear_buffer (&fallback_inbuf); + } + GstVideoInfo in_info; GstVideoInfo out_info; GstD3D11Format in_d3d11_format; GstD3D11Format out_d3d11_format; - guint num_input_view; - guint num_output_view; + guint num_input_view = 0; + guint num_output_view = 0; - GstD3D11ConverterBackend supported_backend; + GstD3D11ConverterBackend supported_backend = (GstD3D11ConverterBackend) 0; + CONVERT_TYPE convert_type = CONVERT_TYPE::IDENTITY; - ID3D11Buffer *vertex_buffer; - ID3D11Buffer *index_buffer; - ID3D11Buffer *const_buffer; - ID3D11VertexShader *vs; - ID3D11InputLayout *layout; - ID3D11SamplerState *linear_sampler; - ID3D11PixelShader *ps[CONVERTER_MAX_QUADS]; + ComPtr < ID3D11Buffer > vertex_buffer; + ComPtr < ID3D11Buffer > index_buffer; + ComPtr < ID3D11Buffer > const_buffer; + ComPtr < ID3D11VertexShader > vs; + ComPtr < ID3D11InputLayout > layout; + ComPtr < ID3D11SamplerState > sampler; + ComPtr < ID3D11SamplerState > linear_sampler; + PixelShaderList ps; D3D11_VIEWPORT viewport[GST_VIDEO_MAX_PLANES]; - ID3D11Texture1D *gamma_dec_lut; - ID3D11Texture1D *gamma_enc_lut; - ID3D11ShaderResourceView *gamma_dec_srv; - ID3D11ShaderResourceView *gamma_enc_srv; + ComPtr < ID3D11Texture1D > gamma_dec_lut; + ComPtr < ID3D11Texture1D > gamma_enc_lut; + ComPtr < ID3D11ShaderResourceView > gamma_dec_srv; + ComPtr < ID3D11ShaderResourceView > gamma_enc_srv; D3D11_BLEND_DESC blend_desc; - ID3D11BlendState *blend; - - gboolean fast_path; - gboolean do_primaries; + ComPtr < ID3D11BlendState > blend; gint input_texture_width; gint input_texture_height; @@ -710,88 +244,88 @@ struct _GstD3D11ConverterPrivate gboolean update_dest_rect; gboolean update_alpha; - ConvertInfo convert_info; PSConstBuffer const_data; gboolean clear_background; FLOAT clear_color[4][4]; GstD3D11ColorMatrix clear_color_matrix; - GstVideoConverter *unpack_convert; + GstVideoConverter *unpack_convert = nullptr; /* video processor */ D3D11_VIDEO_COLOR background_color; - ID3D11VideoDevice *video_device; - ID3D11VideoContext2 *video_context2; - ID3D11VideoContext1 *video_context; - ID3D11VideoProcessorEnumerator1 *enumerator; - ID3D11VideoProcessor *processor; + ComPtr < ID3D11VideoDevice > video_device; + ComPtr < ID3D11VideoContext2 > video_context2; + ComPtr < ID3D11VideoContext1 > video_context; + ComPtr < ID3D11VideoProcessorEnumerator1 > enumerator; + ComPtr < ID3D11VideoProcessor > processor; D3D11_VIDEO_PROCESSOR_CAPS processor_caps; RECT src_rect; RECT dest_rect; RECT dest_full_rect; - gboolean processor_in_use; - gboolean processor_direction_not_supported; - gboolean enable_mirror; - gboolean flip_h; - gboolean flip_v; - gboolean enable_rotation; - D3D11_VIDEO_PROCESSOR_ROTATION rotation; + gboolean processor_in_use = FALSE; + gboolean processor_direction_not_supported = FALSE; + gboolean enable_mirror = FALSE; + gboolean flip_h = FALSE; + gboolean flip_v = FALSE; + gboolean enable_rotation = FALSE; + D3D11_VIDEO_PROCESSOR_ROTATION rotation = + D3D11_VIDEO_PROCESSOR_ROTATION_IDENTITY; /* HDR10 */ - gboolean have_in_hdr10; - gboolean have_out_hdr10; - gboolean in_hdr10_updated; - gboolean out_hdr10_updated; + gboolean have_in_hdr10 = FALSE; + gboolean have_out_hdr10 = FALSE; + gboolean in_hdr10_updated = FALSE; + gboolean out_hdr10_updated = FALSE; DXGI_HDR_METADATA_HDR10 in_hdr10_meta; DXGI_HDR_METADATA_HDR10 out_hdr10_meta; - gchar *in_mdcv_str; - gchar *out_mdcv_str; - gchar *in_cll_str; - gchar *out_cll_str; + gchar *in_mdcv_str = nullptr; + gchar *out_mdcv_str = nullptr; + gchar *in_cll_str = nullptr; + gchar *out_cll_str = nullptr; /* Fallback buffer and info, for shader */ GstVideoInfo fallback_info; - GstBuffer *fallback_inbuf; + GstBuffer *fallback_inbuf = nullptr; /* Fallback buffer used for processor */ GstVideoInfo piv_info; - GstBuffer *piv_inbuf; + GstBuffer *piv_inbuf = nullptr; GstVideoOrientationMethod video_direction; SRWLOCK prop_lock; /* properties */ - gint src_x; - gint src_y; - gint src_width; - gint src_height; - gint dest_x; - gint dest_y; - gint dest_width; - gint dest_height; - gdouble alpha; + gint src_x = 0; + gint src_y = 0; + gint src_width = 0; + gint src_height = 0; + gint dest_x = 0; + gint dest_y = 0; + gint dest_width = 0; + gint dest_height = 0; + gdouble alpha = 0; gfloat blend_factor[4]; - guint blend_sample_mask; - gboolean fill_border; - guint64 border_color; - GstD3D11ConverterAlphaMode src_alpha_mode; - GstD3D11ConverterAlphaMode dst_alpha_mode; + guint blend_sample_mask = 0; + gboolean fill_border = FALSE; + guint64 border_color = 0; + GstD3D11ConverterAlphaMode src_alpha_mode = + GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED; + GstD3D11ConverterAlphaMode dst_alpha_mode = + GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED; }; static void gst_d3d11_converter_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_d3d11_converter_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static void gst_d3d11_converter_dispose (GObject * object); static void gst_d3d11_converter_finalize (GObject * object); static void gst_d3d11_converter_calculate_border_color (GstD3D11Converter * self); #define gst_d3d11_converter_parent_class parent_class -G_DEFINE_TYPE_WITH_PRIVATE (GstD3D11Converter, gst_d3d11_converter, - GST_TYPE_OBJECT); +G_DEFINE_TYPE (GstD3D11Converter, gst_d3d11_converter, GST_TYPE_OBJECT); static void gst_d3d11_converter_class_init (GstD3D11ConverterClass * klass) @@ -802,7 +336,6 @@ gst_d3d11_converter_class_init (GstD3D11ConverterClass * klass) object_class->set_property = gst_d3d11_converter_set_property; object_class->get_property = gst_d3d11_converter_get_property; - object_class->dispose = gst_d3d11_converter_dispose; object_class->finalize = gst_d3d11_converter_finalize; g_object_class_install_property (object_class, PROP_SRC_X, @@ -896,63 +429,18 @@ gst_d3d11_converter_class_init (GstD3D11ConverterClass * klass) static void gst_d3d11_converter_init (GstD3D11Converter * self) { - self->priv = (GstD3D11ConverterPrivate *) - gst_d3d11_converter_get_instance_private (self); - self->priv->src_alpha_mode = self->priv->dst_alpha_mode = - GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED; -} - -static void -gst_d3d11_converter_dispose (GObject * object) -{ - GstD3D11Converter *self = GST_D3D11_CONVERTER (object); - GstD3D11ConverterPrivate *priv = self->priv; - - GST_D3D11_CLEAR_COM (priv->vertex_buffer); - GST_D3D11_CLEAR_COM (priv->index_buffer); - GST_D3D11_CLEAR_COM (priv->const_buffer); - GST_D3D11_CLEAR_COM (priv->vs); - GST_D3D11_CLEAR_COM (priv->layout); - GST_D3D11_CLEAR_COM (priv->linear_sampler); - GST_D3D11_CLEAR_COM (priv->gamma_dec_lut); - GST_D3D11_CLEAR_COM (priv->gamma_dec_srv); - GST_D3D11_CLEAR_COM (priv->gamma_enc_lut); - GST_D3D11_CLEAR_COM (priv->gamma_enc_srv); - GST_D3D11_CLEAR_COM (priv->video_device); - GST_D3D11_CLEAR_COM (priv->video_context2); - GST_D3D11_CLEAR_COM (priv->video_context); - GST_D3D11_CLEAR_COM (priv->enumerator); - GST_D3D11_CLEAR_COM (priv->processor); - GST_D3D11_CLEAR_COM (priv->blend); - - for (guint i = 0; i < CONVERTER_MAX_QUADS; i++) - GST_D3D11_CLEAR_COM (priv->ps[i]); - - gst_clear_buffer (&priv->fallback_inbuf); - gst_clear_buffer (&priv->piv_inbuf); - gst_clear_object (&self->device); - - G_OBJECT_CLASS (parent_class)->dispose (object); + self->priv = new GstD3D11ConverterPrivate (); } static void gst_d3d11_converter_finalize (GObject * object) { GstD3D11Converter *self = GST_D3D11_CONVERTER (object); - GstD3D11ConverterPrivate *priv = self->priv; - for (guint i = 0; i < CONVERTER_MAX_QUADS; i++) { - g_free (priv->convert_info.sample_texture_func[i]); - g_free (priv->convert_info.build_output_func[i]); - } + delete self->priv; - g_free (priv->in_mdcv_str); - g_free (priv->out_mdcv_str); - g_free (priv->in_cll_str); - g_free (priv->out_cll_str); - - if (priv->unpack_convert) - gst_video_converter_free (priv->unpack_convert); + if (self->device) + gst_object_unref (self->device); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -1039,12 +527,10 @@ gst_d3d11_converter_set_property (GObject * object, guint prop_id, case PROP_BLEND_STATE:{ ID3D11BlendState *blend = (ID3D11BlendState *) g_value_get_pointer (value); - GST_D3D11_CLEAR_COM (priv->blend); + priv->blend = nullptr; priv->blend = blend; - if (priv->blend) { - priv->blend->AddRef (); + if (priv->blend) priv->blend->GetDesc (&priv->blend_desc); - } break; } case PROP_BLEND_FACTOR_RED: @@ -1152,7 +638,7 @@ gst_d3d11_converter_get_property (GObject * object, guint prop_id, g_value_set_double (value, priv->alpha); break; case PROP_BLEND_STATE: - g_value_set_pointer (value, priv->blend); + g_value_set_pointer (value, priv->blend.Get ()); break; case PROP_BLEND_FACTOR_RED: g_value_set_float (value, priv->blend_factor[0]); @@ -1196,143 +682,6 @@ gst_d3d11_converter_get_property (GObject * object, guint prop_id, } } -static gboolean -get_packed_yuv_components (GstVideoFormat format, gchar * y, gchar * u, - gchar * v) -{ - switch (format) { - case GST_VIDEO_FORMAT_Y410: - *y = 'g'; - *u = 'r'; - *v = 'b'; - break; - default: - g_assert_not_reached (); - return FALSE; - } - - return TRUE; -} - -static void -get_planar_component (GstVideoFormat format, gchar * x, gchar * y, gchar * z, - gchar * w, guint * scale) -{ - switch (format) { - case GST_VIDEO_FORMAT_I420_10LE: - case GST_VIDEO_FORMAT_I422_10LE: - case GST_VIDEO_FORMAT_Y444_10LE: - case GST_VIDEO_FORMAT_GBR_10LE: - case GST_VIDEO_FORMAT_GBRA_10LE: - *scale = (1 << 6); - break; - case GST_VIDEO_FORMAT_I420_12LE: - case GST_VIDEO_FORMAT_I422_12LE: - case GST_VIDEO_FORMAT_Y444_12LE: - case GST_VIDEO_FORMAT_GBR_12LE: - case GST_VIDEO_FORMAT_GBRA_12LE: - *scale = (1 << 4); - break; - default: - *scale = 1; - break; - } - - switch (format) { - case GST_VIDEO_FORMAT_RGBP: - *x = 'x'; - *y = 'y'; - *z = 'z'; - break; - case GST_VIDEO_FORMAT_BGRP: - *x = 'z'; - *y = 'y'; - *z = 'x'; - break; - case GST_VIDEO_FORMAT_GBR: - case GST_VIDEO_FORMAT_GBR_10LE: - case GST_VIDEO_FORMAT_GBR_12LE: - case GST_VIDEO_FORMAT_GBR_16LE: - *x = 'y'; - *y = 'z'; - *z = 'x'; - break; - case GST_VIDEO_FORMAT_GBRA: - case GST_VIDEO_FORMAT_GBRA_10LE: - case GST_VIDEO_FORMAT_GBRA_12LE: - *x = 'y'; - *y = 'z'; - *z = 'x'; - *w = 'w'; - break; - case GST_VIDEO_FORMAT_YV12: - *x = 'x'; - *y = 'z'; - *z = 'y'; - break; - default: - *x = 'x'; - *y = 'y'; - *z = 'z'; - break; - } -} - -static void -get_semi_planar_component (GstVideoFormat format, gchar * u, gchar * v, - gboolean is_sampling) -{ - if (format == GST_VIDEO_FORMAT_NV21) { - if (is_sampling) { - *u = 'y'; - *v = 'x'; - } else { - *u = 'z'; - *v = 'y'; - } - } else { - if (is_sampling) { - *u = 'x'; - *v = 'y'; - } else { - *u = 'y'; - *v = 'z'; - } - } -} - -static void -get_vuya_component (GstVideoFormat format, gchar * y, gchar * u, - gchar * v, gchar * a) -{ - switch (format) { - case GST_VIDEO_FORMAT_VUYA: - if (y) - *y = 'z'; - if (u) - *u = 'y'; - if (v) - *v = 'x'; - if (a) - *a = 'w'; - break; - case GST_VIDEO_FORMAT_AYUV: - case GST_VIDEO_FORMAT_AYUV64: - if (y) - *y = 'g'; - if (u) - *u = 'b'; - if (v) - *v = 'a'; - if (a) - *a = 'r'; - break; - default: - g_assert_not_reached (); - break; - } -} - static gboolean gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, const GstVideoInfo * in_info, const GstVideoInfo * out_info, @@ -1341,7 +690,6 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, GstD3D11ConverterPrivate *priv = self->priv; GstD3D11Device *device = self->device; HRESULT hr; - D3D11_SAMPLER_DESC sampler_desc; D3D11_INPUT_ELEMENT_DESC input_desc[2]; D3D11_BUFFER_DESC buffer_desc; D3D11_MAPPED_SUBRESOURCE map; @@ -1349,78 +697,45 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, WORD *indices; ID3D11Device *device_handle; ID3D11DeviceContext *context_handle; - ConvertInfo *cinfo = &priv->convert_info; - ComPtr < ID3D11PixelShader > ps[CONVERTER_MAX_QUADS]; ComPtr < ID3D11VertexShader > vs; ComPtr < ID3D11InputLayout > layout; + ComPtr < ID3D11SamplerState > sampler; ComPtr < ID3D11SamplerState > linear_sampler; ComPtr < ID3D11Buffer > const_buffer; ComPtr < ID3D11Buffer > vertex_buffer; ComPtr < ID3D11Buffer > index_buffer; - gint i; - memset (&sampler_desc, 0, sizeof (sampler_desc)); memset (input_desc, 0, sizeof (input_desc)); memset (&buffer_desc, 0, sizeof (buffer_desc)); device_handle = gst_d3d11_device_get_device_handle (device); context_handle = gst_d3d11_device_get_device_context_handle (device); - /* bilinear filtering */ - sampler_desc.Filter = sampler_filter; - sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - sampler_desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - sampler_desc.MinLOD = 0; - sampler_desc.MaxLOD = D3D11_FLOAT32_MAX; - - hr = device_handle->CreateSamplerState (&sampler_desc, &linear_sampler); + hr = gst_d3d11_device_get_sampler (device, sampler_filter, &sampler); if (!gst_d3d11_result (hr, device)) { - GST_ERROR_OBJECT (self, - "Couldn't create samplerState state, hr: 0x%x", (guint) hr); + GST_ERROR_OBJECT (self, "Couldn't create sampler, hr: 0x%x", (guint) hr); return FALSE; } - for (i = 0; i < CONVERTER_MAX_QUADS; i++) { - gchar *shader_code = nullptr; - - if (cinfo->sample_texture_func[i]) { - g_assert (cinfo->ps_output[i] != nullptr); - - shader_code = g_strdup_printf (templ_pixel_shader, - cinfo->ps_output[i]->output_template, cinfo->sample_texture_func[i], - cinfo->to_rgb_func[i], cinfo->to_yuv_func[i], - cinfo->build_output_func[i], cinfo->gamma_decode_func, - cinfo->gamma_encode_func, cinfo->XYZ_convert_func); - - hr = gst_d3d11_create_pixel_shader_simple (device, - shader_code, "main", &ps[i]); - g_free (shader_code); - if (!gst_d3d11_result (hr, device)) { - return FALSE; - } - } + hr = gst_d3d11_device_get_sampler (device, D3D11_FILTER_MIN_MAG_MIP_LINEAR, + &linear_sampler); + if (!gst_d3d11_result (hr, device)) { + GST_ERROR_OBJECT (self, + "Couldn't create linear sampler, hr: 0x%x", (guint) hr); + return FALSE; } - input_desc[0].SemanticName = "POSITION"; - input_desc[0].SemanticIndex = 0; - input_desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; - input_desc[0].InputSlot = 0; - input_desc[0].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; - input_desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; - input_desc[0].InstanceDataStepRate = 0; + auto ps_list = gst_d3d11_get_converter_pixel_shader (device, + GST_VIDEO_INFO_FORMAT (in_info), GST_VIDEO_INFO_FORMAT (out_info), + priv->src_alpha_mode == GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED, + priv->dst_alpha_mode == GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED, + priv->convert_type); + if (ps_list.empty ()) { + GST_ERROR_OBJECT (self, "Couldn't create pixel shader"); + return FALSE; + } - input_desc[1].SemanticName = "TEXCOORD"; - input_desc[1].SemanticIndex = 0; - input_desc[1].Format = DXGI_FORMAT_R32G32_FLOAT; - input_desc[1].InputSlot = 0; - input_desc[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; - input_desc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; - input_desc[1].InstanceDataStepRate = 0; - - hr = gst_d3d11_create_vertex_shader_simple (device, templ_vertex_shader, - "main", input_desc, G_N_ELEMENTS (input_desc), &vs, &layout); + 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"); return FALSE; @@ -1536,15 +851,14 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self, context_handle->Unmap (index_buffer.Get (), 0); /* holds vertex buffer for crop rect update */ - priv->vertex_buffer = vertex_buffer.Detach (); - priv->index_buffer = index_buffer.Detach (); - priv->const_buffer = const_buffer.Detach (); - priv->vs = vs.Detach (); - priv->layout = layout.Detach (); - priv->linear_sampler = linear_sampler.Detach (); - priv->ps[0] = ps[0].Detach (); - if (ps[1]) - priv->ps[1] = ps[1].Detach (); + priv->vertex_buffer = vertex_buffer; + priv->index_buffer = index_buffer; + priv->const_buffer = const_buffer; + priv->vs = vs; + priv->layout = layout; + priv->sampler = sampler; + priv->linear_sampler = linear_sampler; + priv->ps = ps_list; priv->input_texture_width = GST_VIDEO_INFO_WIDTH (in_info); priv->input_texture_height = GST_VIDEO_INFO_HEIGHT (in_info); @@ -1802,8 +1116,8 @@ gst_d3d11_converter_update_src_rect (GstD3D11Converter * self) context_handle = gst_d3d11_device_get_device_context_handle (self->device); - hr = context_handle->Map (priv->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, - 0, &map); + hr = context_handle->Map (priv->vertex_buffer.Get (), + 0, D3D11_MAP_WRITE_DISCARD, 0, &map); if (!gst_d3d11_result (hr, self->device)) { GST_ERROR_OBJECT (self, "Couldn't map vertex buffer, hr: 0x%x", (guint) hr); @@ -1863,7 +1177,7 @@ gst_d3d11_converter_update_src_rect (GstD3D11Converter * self) gst_d3d11_converter_apply_orientation (self, vertex_data, u0, u1, v0, v1); - context_handle->Unmap (priv->vertex_buffer, 0); + context_handle->Unmap (priv->vertex_buffer.Get (), 0); return TRUE; } @@ -1961,338 +1275,6 @@ gst_d3d11_converter_update_dest_rect (GstD3D11Converter * self) return TRUE; } -static gboolean -gst_d3d11_converter_prepare_output (GstD3D11Converter * self, - const GstVideoInfo * info) -{ - GstD3D11ConverterPrivate *priv = self->priv; - GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info); - ConvertInfo *cinfo = &priv->convert_info; - - switch (format) { - /* RGB */ - case GST_VIDEO_FORMAT_RGBA64_LE: - case GST_VIDEO_FORMAT_RGB10A2_LE: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_RGBx: - cinfo->ps_output[0] = &output_types[OUTPUT_SINGLE_PLANE]; - cinfo->build_output_func[0] = g_strdup (templ_OUTPUT_DEFAULT); - break; - /* VUYA */ - case GST_VIDEO_FORMAT_VUYA: - case GST_VIDEO_FORMAT_AYUV: - case GST_VIDEO_FORMAT_AYUV64:{ - gchar y, u, v, a; - - get_vuya_component (format, &y, &u, &v, &a); - cinfo->ps_output[0] = &output_types[OUTPUT_SINGLE_PLANE]; - cinfo->build_output_func[0] = - g_strdup_printf (templ_OUTPUT_VUYA, y, u, v, a); - break; - } - /* semi-planar */ - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV21: - case GST_VIDEO_FORMAT_P010_10LE: - case GST_VIDEO_FORMAT_P012_LE: - case GST_VIDEO_FORMAT_P016_LE:{ - gchar u, v; - - get_semi_planar_component (format, &u, &v, FALSE); - cinfo->ps_output[0] = &output_types[OUTPUT_SINGLE_PLANE]; - cinfo->build_output_func[0] = g_strdup (templ_OUTPUT_LUMA); - - cinfo->ps_output[1] = &output_types[OUTPUT_SINGLE_PLANE]; - cinfo->build_output_func[1] = - g_strdup_printf (templ_OUTPUT_CHROMA_SEMI_PLANAR, u, v); - break; - } - /* planar */ - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_I420_10LE: - case GST_VIDEO_FORMAT_I420_12LE: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_I422_10LE: - case GST_VIDEO_FORMAT_I422_12LE:{ - gchar y, u, v, w; - guint scale; - - get_planar_component (format, &y, &u, &v, &w, &scale); - - cinfo->ps_output[0] = &output_types[OUTPUT_SINGLE_PLANE]; - cinfo->ps_output[1] = &output_types[OUTPUT_TWO_PLANES]; - - if (info->finfo->depth[0] == 8) { - cinfo->build_output_func[0] = g_strdup (templ_OUTPUT_LUMA); - cinfo->build_output_func[1] = - g_strdup_printf (templ_OUTPUT_CHROMA_PLANAR, u, v); - } else { - cinfo->build_output_func[0] = g_strdup_printf (templ_OUTPUT_LUMA_SCALED, - scale); - cinfo->build_output_func[1] = - g_strdup_printf (templ_OUTPUT_CHROMA_PLANAR_SCALED, - u, scale, v, scale); - } - break; - } - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_Y444_10LE: - case GST_VIDEO_FORMAT_Y444_12LE: - case GST_VIDEO_FORMAT_Y444_16LE: - case GST_VIDEO_FORMAT_RGBP: - case GST_VIDEO_FORMAT_BGRP: - case GST_VIDEO_FORMAT_GBR: - case GST_VIDEO_FORMAT_GBR_10LE: - case GST_VIDEO_FORMAT_GBR_12LE: - case GST_VIDEO_FORMAT_GBR_16LE: - { - gchar x, y, z, w; - guint scale; - - get_planar_component (format, &x, &y, &z, &w, &scale); - - cinfo->ps_output[0] = &output_types[OUTPUT_THREE_PLANES]; - if (info->finfo->depth[0] == 8) { - cinfo->build_output_func[0] = g_strdup_printf (templ_OUTPUT_PLANAR, - x, y, z); - } else { - cinfo->build_output_func[0] = - g_strdup_printf (templ_OUTPUT_PLANAR_SCALED, scale, x, y, z); - } - break; - } - case GST_VIDEO_FORMAT_GBRA: - case GST_VIDEO_FORMAT_GBRA_10LE: - case GST_VIDEO_FORMAT_GBRA_12LE: - { - gchar x, y, z, w; - guint scale; - - get_planar_component (format, &x, &y, &z, &w, &scale); - - cinfo->ps_output[0] = &output_types[OUTPUT_FOUR_PLANES]; - if (info->finfo->depth[0] == 8) { - cinfo->build_output_func[0] = g_strdup_printf (templ_OUTPUT_PLANAR_4, - x, y, z, w); - } else { - cinfo->build_output_func[0] = - g_strdup_printf (templ_OUTPUT_PLANAR_4_SCALED, scale, x, y, z, w); - } - break; - } - case GST_VIDEO_FORMAT_GRAY8: - case GST_VIDEO_FORMAT_GRAY16_LE: - cinfo->ps_output[0] = &output_types[OUTPUT_SINGLE_PLANE]; - cinfo->build_output_func[0] = g_strdup (templ_OUTPUT_LUMA); - break; - default: - g_assert_not_reached (); - return FALSE; - } - - return TRUE; -} - -static gboolean -gst_d3d11_converter_prepare_sample_texture (GstD3D11Converter * self, - const GstVideoInfo * in_info, const GstVideoInfo * out_info) -{ - GstD3D11ConverterPrivate *priv = self->priv; - GstVideoFormat format = GST_VIDEO_INFO_FORMAT (in_info); - gboolean out_rgb = GST_VIDEO_INFO_IS_RGB (out_info); - gboolean out_yuv = GST_VIDEO_INFO_IS_YUV (out_info); - gboolean out_gray = GST_VIDEO_INFO_IS_GRAY (out_info); - ConvertInfo *cinfo = &priv->convert_info; - - switch (format) { - /* RGB */ - case GST_VIDEO_FORMAT_RGBA64_LE: - case GST_VIDEO_FORMAT_RGB10A2_LE: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_RGBx: - cinfo->sample_texture_func[0] = g_strdup (templ_SAMPLE_DEFAULT); - if (cinfo->ps_output[1]) - cinfo->sample_texture_func[1] = - g_strdup (cinfo->sample_texture_func[0]); - break; - /* VUYA */ - case GST_VIDEO_FORMAT_VUYA: - case GST_VIDEO_FORMAT_AYUV: - case GST_VIDEO_FORMAT_AYUV64:{ - gchar y, u, v, a; - - get_vuya_component (format, &y, &u, &v, &a); - cinfo->sample_texture_func[0] = g_strdup_printf (templ_SAMPLE_VUYA, - y, u, v, a); - if (cinfo->ps_output[1]) { - cinfo->sample_texture_func[1] = - g_strdup (cinfo->sample_texture_func[0]); - } - break; - } - /* semi-planar */ - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV21: - case GST_VIDEO_FORMAT_P010_10LE: - case GST_VIDEO_FORMAT_P012_LE: - case GST_VIDEO_FORMAT_P016_LE:{ - gchar u, v; - - get_semi_planar_component (format, &u, &v, TRUE); - if (out_rgb) { - cinfo->sample_texture_func[0] = - g_strdup_printf (templ_SAMPLE_SEMI_PLANAR, u, v); - } else if (out_gray) { - cinfo->sample_texture_func[0] = g_strdup (templ_SAMPLE_YUV_LUMA); - } else if (out_yuv) { - if (GST_VIDEO_INFO_N_PLANES (out_info) == 1 || - cinfo->ps_output[0] == &output_types[OUTPUT_THREE_PLANES]) { - /* YUV packed or Y444 */ - cinfo->sample_texture_func[0] = - g_strdup_printf (templ_SAMPLE_SEMI_PLANAR, u, v); - } else { - if (priv->fast_path) { - cinfo->sample_texture_func[0] = g_strdup (templ_SAMPLE_YUV_LUMA); - cinfo->sample_texture_func[1] = - g_strdup_printf (templ_SAMPLE_SEMI_PLANAR_CHROMA, u, v); - } else { - cinfo->sample_texture_func[0] = - g_strdup_printf (templ_SAMPLE_SEMI_PLANAR, u, v); - cinfo->sample_texture_func[1] = - g_strdup (cinfo->sample_texture_func[0]); - } - } - } else { - g_assert_not_reached (); - return FALSE; - } - break; - } - /* planar */ - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_I420_10LE: - case GST_VIDEO_FORMAT_I420_12LE: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_I422_10LE: - case GST_VIDEO_FORMAT_I422_12LE: - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_Y444_10LE: - case GST_VIDEO_FORMAT_Y444_12LE: - case GST_VIDEO_FORMAT_Y444_16LE: - { - gchar x, y, z, w; - guint scale; - - get_planar_component (format, &x, &y, &z, &w, &scale); - if (out_rgb) { - cinfo->sample_texture_func[0] = g_strdup_printf (templ_SAMPLE_PLANAR, - x, y, z, scale); - } else if (out_gray) { - cinfo->sample_texture_func[0] = - g_strdup_printf (templ_SAMPLE_YUV_LUMA_SCALED, scale); - } else if (out_yuv) { - if (GST_VIDEO_INFO_N_PLANES (out_info) == 1 || - cinfo->ps_output[0] == &output_types[OUTPUT_THREE_PLANES]) { - /* YUV packed or Y444 */ - cinfo->sample_texture_func[0] = g_strdup_printf (templ_SAMPLE_PLANAR, - x, y, z, scale); - } else { - if (priv->fast_path) { - cinfo->sample_texture_func[0] = - g_strdup_printf (templ_SAMPLE_YUV_LUMA_SCALED, scale); - cinfo->sample_texture_func[1] = - g_strdup_printf (templ_SAMPLE_PLANAR_CHROMA, y, z, scale); - } else { - cinfo->sample_texture_func[0] = - g_strdup_printf (templ_SAMPLE_PLANAR, x, y, z, scale); - cinfo->sample_texture_func[1] = - g_strdup (cinfo->sample_texture_func[0]); - } - } - } else { - g_assert_not_reached (); - return FALSE; - } - break; - } - /* RGB planar */ - case GST_VIDEO_FORMAT_RGBP: - case GST_VIDEO_FORMAT_BGRP: - case GST_VIDEO_FORMAT_GBR: - case GST_VIDEO_FORMAT_GBR_10LE: - case GST_VIDEO_FORMAT_GBR_12LE: - case GST_VIDEO_FORMAT_GBR_16LE: - case GST_VIDEO_FORMAT_GBRA: - case GST_VIDEO_FORMAT_GBRA_10LE: - case GST_VIDEO_FORMAT_GBRA_12LE: - { - gchar x, y, z, w; - guint scale; - - get_planar_component (format, &x, &y, &z, &w, &scale); - - if (GST_VIDEO_INFO_N_PLANES (in_info) == 4) { - cinfo->sample_texture_func[0] = g_strdup_printf (templ_SAMPLE_PLANAR_4, - x, y, z, w, scale); - } else { - cinfo->sample_texture_func[0] = g_strdup_printf (templ_SAMPLE_PLANAR, - x, y, z, scale); - } - - if (cinfo->ps_output[1]) { - cinfo->sample_texture_func[1] = - g_strdup (cinfo->sample_texture_func[0]); - } - break; - } - /* yuv packed */ - case GST_VIDEO_FORMAT_Y410:{ - gchar y, u, v; - - get_packed_yuv_components (format, &y, &u, &v); - cinfo->sample_texture_func[0] = g_strdup_printf (templ_SAMPLE_YUV_PACKED, - y, u, v); - if (cinfo->ps_output[1]) { - cinfo->sample_texture_func[1] = - g_strdup (cinfo->sample_texture_func[0]); - } - break; - } - case GST_VIDEO_FORMAT_GRAY8: - case GST_VIDEO_FORMAT_GRAY16_LE: - cinfo->sample_texture_func[0] = g_strdup (templ_SAMPLE_GRAY); - if (cinfo->ps_output[1]) - cinfo->sample_texture_func[1] = g_strdup (templ_SAMPLE_GRAY_CHROMA); - break; - default: - g_assert_not_reached (); - return FALSE; - } - - return TRUE; -} - -static const gchar * -get_color_range_name (GstVideoColorRange range) -{ - switch (range) { - case GST_VIDEO_COLOR_RANGE_0_255: - return "FULL"; - case GST_VIDEO_COLOR_RANGE_16_235: - return "STUDIO"; - default: - break; - } - - return "UNKNOWN"; -} - static void convert_info_gray_to_yuv (const GstVideoInfo * gray, GstVideoInfo * yuv) { @@ -2330,424 +1312,108 @@ convert_info_gray_to_yuv (const GstVideoInfo * gray, GstVideoInfo * yuv) *yuv = tmp; } -static void -convert_info_gray_to_rgb (const GstVideoInfo * gray, GstVideoInfo * rgb) -{ - GstVideoInfo tmp; - - if (GST_VIDEO_INFO_IS_RGB (gray)) { - *rgb = *gray; - return; - } - - if (gray->finfo->depth[0] == 8) { - gst_video_info_set_format (&tmp, - GST_VIDEO_FORMAT_RGBA, gray->width, gray->height); - } else { - gst_video_info_set_format (&tmp, - GST_VIDEO_FORMAT_RGBA64_LE, gray->width, gray->height); - } - - tmp.colorimetry.range = gray->colorimetry.range; - if (tmp.colorimetry.range == GST_VIDEO_COLOR_RANGE_UNKNOWN) - tmp.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; - - tmp.colorimetry.primaries = gray->colorimetry.primaries; - if (tmp.colorimetry.primaries == GST_VIDEO_COLOR_PRIMARIES_UNKNOWN) - tmp.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709; - - tmp.colorimetry.transfer = gray->colorimetry.transfer; - if (tmp.colorimetry.transfer == GST_VIDEO_TRANSFER_UNKNOWN) - tmp.colorimetry.transfer = GST_VIDEO_TRANSFER_BT709; - - *rgb = tmp; -} - static gboolean -gst_d3d11_converter_prepare_colorspace_fast (GstD3D11Converter * self, +gst_d3d11_converter_calculate_matrix (GstD3D11Converter * self, const GstVideoInfo * in_info, const GstVideoInfo * out_info) { GstD3D11ConverterPrivate *priv = self->priv; - const GstVideoColorimetry *in_color = &in_info->colorimetry; - const GstVideoColorimetry *out_color = &out_info->colorimetry; - ConvertInfo *cinfo = &priv->convert_info; - PSColorSpace *to_rgb_buf = &priv->const_data.to_rgb_buf; - PSColorSpace *to_yuv_buf = &priv->const_data.to_yuv_buf; - GstD3D11ColorMatrix to_rgb_matrix; - GstD3D11ColorMatrix to_yuv_matrix; - gchar *matrix_dump; + GstD3D11ColorMatrix pre_coeff; + GstD3D11ColorMatrix post_coeff; + GstD3D11ColorMatrix primaries_coeff; + GstVideoInfo rgb_info; - memset (&to_rgb_matrix, 0, sizeof (GstD3D11ColorMatrix)); - memset (&to_yuv_matrix, 0, sizeof (GstD3D11ColorMatrix)); + gst_d3d11_color_matrix_init (&pre_coeff); + gst_d3d11_color_matrix_init (&post_coeff); + gst_d3d11_color_matrix_init (&primaries_coeff); - for (guint i = 0; i < 2; i++) { - cinfo->to_rgb_func[i] = templ_COLOR_SPACE_IDENTITY; - cinfo->to_yuv_func[i] = templ_COLOR_SPACE_IDENTITY; - } - - cinfo->gamma_decode_func = templ_GAMMA_DECODE_IDENTITY; - cinfo->gamma_encode_func = templ_GAMMA_ENCODE_IDENTITY; - cinfo->XYZ_convert_func = templ_XYZ_CONVERT_IDENTITY; - - if (GST_VIDEO_INFO_IS_RGB (in_info)) { - if (GST_VIDEO_INFO_IS_RGB (out_info)) { - if (in_color->range == out_color->range) { - GST_DEBUG_OBJECT (self, "RGB -> RGB without colorspace conversion"); + switch (priv->convert_type) { + case CONVERT_TYPE::RANGE: + gst_d3d11_color_range_adjust_matrix_unorm (in_info, out_info, + &post_coeff); + break; + case CONVERT_TYPE::SIMPLE: + if (GST_VIDEO_INFO_IS_RGB (in_info)) { + gst_d3d11_rgb_to_yuv_matrix_unorm (in_info, out_info, &post_coeff); } else { - if (!gst_d3d11_color_range_adjust_matrix_unorm (in_info, out_info, - &to_rgb_matrix)) { - GST_ERROR_OBJECT (self, "Failed to get RGB range adjust matrix"); - return FALSE; + gst_d3d11_yuv_to_rgb_matrix_unorm (in_info, out_info, &post_coeff); + } + break; + case CONVERT_TYPE::GAMMA: + case CONVERT_TYPE::PRIMARY: + if (GST_VIDEO_INFO_IS_RGB (in_info)) { + rgb_info = *in_info; + if (in_info->colorimetry.range == GST_VIDEO_COLOR_RANGE_16_235) { + rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; + + gst_d3d11_color_range_adjust_matrix_unorm (in_info, + &rgb_info, &pre_coeff); } - - matrix_dump = gst_d3d11_dump_color_matrix (&to_rgb_matrix); - GST_DEBUG_OBJECT (self, "RGB range adjust %s -> %s\n%s", - get_color_range_name (in_color->range), - get_color_range_name (out_color->range), matrix_dump); - g_free (matrix_dump); - - cinfo->to_rgb_func[0] = templ_COLOR_SPACE_CONVERT; - } - } else { - GstVideoInfo yuv_info; - - convert_info_gray_to_yuv (out_info, &yuv_info); - - if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || - yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { - GST_WARNING_OBJECT (self, "Invalid matrix is detected"); - yuv_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; - } - - if (!gst_d3d11_rgb_to_yuv_matrix_unorm (in_info, - &yuv_info, &to_yuv_matrix)) { - GST_ERROR_OBJECT (self, "Failed to get RGB -> YUV transform matrix"); - return FALSE; - } - - matrix_dump = gst_d3d11_dump_color_matrix (&to_yuv_matrix); - GST_DEBUG_OBJECT (self, "RGB -> YUV matrix:\n%s", matrix_dump); - g_free (matrix_dump); - - if (GST_VIDEO_INFO_IS_GRAY (out_info)) { - cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT_LUMA; - } else if (GST_VIDEO_INFO_N_PLANES (out_info) == 1 || - cinfo->ps_output[0] == &output_types[OUTPUT_THREE_PLANES]) { - /* YUV packed or Y444 */ - cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT; } else { - cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT_LUMA; - cinfo->to_yuv_func[1] = templ_COLOR_SPACE_CONVERT_CHROMA; + gst_video_info_set_format (&rgb_info, + in_info->finfo->depth[0] == 8 ? GST_VIDEO_FORMAT_RGBA : + GST_VIDEO_FORMAT_RGBA64_LE, in_info->width, in_info->height); + rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; + rgb_info.colorimetry.transfer = in_info->colorimetry.transfer; + rgb_info.colorimetry.primaries = in_info->colorimetry.primaries; + + gst_d3d11_yuv_to_rgb_matrix_unorm (in_info, &rgb_info, &pre_coeff); } - } - } else if (GST_VIDEO_INFO_IS_GRAY (in_info)) { - gboolean identity = TRUE; - GstD3D11ColorMatrix matrix; - memset (&matrix, 0, sizeof (GstD3D11ColorMatrix)); + if (priv->convert_type == CONVERT_TYPE::PRIMARY) { + const GstVideoColorPrimariesInfo *in_pinfo; + const GstVideoColorPrimariesInfo *out_pinfo; - if (in_color->range != out_color->range) { - GstVideoInfo in_tmp, out_tmp; + in_pinfo = + gst_video_color_primaries_get_info (in_info->colorimetry.primaries); + out_pinfo = + gst_video_color_primaries_get_info (out_info-> + colorimetry.primaries); + + gst_d3d11_color_primaries_matrix_unorm (in_pinfo, out_pinfo, + &primaries_coeff); + } if (GST_VIDEO_INFO_IS_RGB (out_info)) { - convert_info_gray_to_rgb (in_info, &in_tmp); - out_tmp = *out_info; + if (out_info->colorimetry.range == GST_VIDEO_COLOR_RANGE_16_235) { + rgb_info = *out_info; + rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; + + gst_d3d11_color_range_adjust_matrix_unorm (&rgb_info, + out_info, &post_coeff); + } } else { - convert_info_gray_to_yuv (in_info, &in_tmp); - convert_info_gray_to_yuv (out_info, &out_tmp); + gst_d3d11_rgb_to_yuv_matrix_unorm (&rgb_info, out_info, &post_coeff); } - - identity = FALSE; - if (!gst_d3d11_color_range_adjust_matrix_unorm (&in_tmp, &out_tmp, - &matrix)) { - GST_ERROR_OBJECT (self, "Failed to get GRAY range adjust matrix"); - return FALSE; - } - - matrix_dump = gst_d3d11_dump_color_matrix (&matrix); - GST_DEBUG_OBJECT (self, "GRAY range adjust matrix:\n%s", matrix_dump); - g_free (matrix_dump); - } - - if (GST_VIDEO_INFO_IS_GRAY (out_info)) { - if (identity) { - GST_DEBUG_OBJECT (self, "GRAY to GRAY without range adjust"); - } else { - cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT_LUMA; - } - - to_yuv_matrix = matrix; - } else if (GST_VIDEO_INFO_IS_RGB (out_info)) { - if (identity) { - GST_DEBUG_OBJECT (self, "GRAY to RGB without range adjust"); - cinfo->to_rgb_func[0] = templ_COLOR_SPACE_GRAY_TO_RGB; - } else { - cinfo->to_rgb_func[0] = templ_COLOR_SPACE_GRAY_TO_RGB_RANGE_ADJUST; - } - - to_rgb_matrix = matrix; - } else if (GST_VIDEO_INFO_IS_YUV (out_info)) { - if (identity) { - GST_DEBUG_OBJECT (self, "GRAY to YUV without range adjust"); - } else { - cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT_LUMA; - cinfo->to_yuv_func[1] = templ_COLOR_SPACE_CONVERT_LUMA; - } - - to_yuv_matrix = matrix; - } else { - g_assert_not_reached (); - return FALSE; - } - } else if (GST_VIDEO_INFO_IS_YUV (in_info)) { - if (GST_VIDEO_INFO_IS_RGB (out_info)) { - GstVideoInfo yuv_info = *in_info; - - if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || - yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { - GST_WARNING_OBJECT (self, "Invalid matrix is detected"); - yuv_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; - } - - if (!gst_d3d11_yuv_to_rgb_matrix_unorm (&yuv_info, - out_info, &to_rgb_matrix)) { - GST_ERROR_OBJECT (self, "Failed to get YUV -> RGB transform matrix"); - return FALSE; - } - - matrix_dump = gst_d3d11_dump_color_matrix (&to_rgb_matrix); - GST_DEBUG_OBJECT (self, "YUV -> RGB matrix:\n%s", matrix_dump); - g_free (matrix_dump); - - cinfo->to_rgb_func[0] = templ_COLOR_SPACE_CONVERT; - } else if (in_color->range != out_color->range) { - if (!gst_d3d11_color_range_adjust_matrix_unorm (in_info, out_info, - &to_yuv_matrix)) { - GST_ERROR_OBJECT (self, "Failed to get GRAY range adjust matrix"); - return FALSE; - } - - matrix_dump = gst_d3d11_dump_color_matrix (&to_yuv_matrix); - GST_DEBUG_OBJECT (self, "YUV range adjust matrix:\n%s", matrix_dump); - g_free (matrix_dump); - - if (GST_VIDEO_INFO_IS_GRAY (out_info)) { - cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT_LUMA; - } else if (GST_VIDEO_INFO_N_PLANES (out_info) == 1 || - cinfo->ps_output[0] == &output_types[OUTPUT_THREE_PLANES]) { - /* YUV packed or Y444 */ - cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT; - } else { - cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT_LUMA; - cinfo->to_yuv_func[1] = templ_COLOR_SPACE_CONVERT_CHROMA; - } - } - } else { - g_assert_not_reached (); - return FALSE; + break; + default: + break; } + PSColorSpace *preCoeff = &priv->const_data.preCoeff; + PSColorSpace *postCoeff = &priv->const_data.postCoeff; + PSColorSpace *primariesCoeff = &priv->const_data.primariesCoeff; + for (guint i = 0; i < 3; i++) { - to_rgb_buf->coeffX[i] = to_rgb_matrix.matrix[0][i]; - to_rgb_buf->coeffY[i] = to_rgb_matrix.matrix[1][i]; - to_rgb_buf->coeffZ[i] = to_rgb_matrix.matrix[2][i]; - to_rgb_buf->offset[i] = to_rgb_matrix.offset[i]; - to_rgb_buf->min[i] = to_rgb_matrix.min[i]; - to_rgb_buf->max[i] = to_rgb_matrix.max[i]; + preCoeff->coeffX[i] = pre_coeff.matrix[0][i]; + preCoeff->coeffY[i] = pre_coeff.matrix[1][i]; + preCoeff->coeffZ[i] = pre_coeff.matrix[2][i]; + preCoeff->offset[i] = pre_coeff.offset[i]; + preCoeff->min[i] = pre_coeff.min[i]; + preCoeff->max[i] = pre_coeff.max[i]; - to_yuv_buf->coeffX[i] = to_yuv_matrix.matrix[0][i]; - to_yuv_buf->coeffY[i] = to_yuv_matrix.matrix[1][i]; - to_yuv_buf->coeffZ[i] = to_yuv_matrix.matrix[2][i]; - to_yuv_buf->offset[i] = to_yuv_matrix.offset[i]; - to_yuv_buf->min[i] = to_yuv_matrix.min[i]; - to_yuv_buf->max[i] = to_yuv_matrix.max[i]; - } + postCoeff->coeffX[i] = post_coeff.matrix[0][i]; + postCoeff->coeffY[i] = post_coeff.matrix[1][i]; + postCoeff->coeffZ[i] = post_coeff.matrix[2][i]; + postCoeff->offset[i] = post_coeff.offset[i]; + postCoeff->min[i] = post_coeff.min[i]; + postCoeff->max[i] = post_coeff.max[i]; - return TRUE; -} - -static gboolean -gst_d3d11_converter_prepare_colorspace (GstD3D11Converter * self, - const GstVideoInfo * in_info, const GstVideoInfo * out_info) -{ - GstD3D11ConverterPrivate *priv = self->priv; - const GstVideoColorimetry *in_color = &in_info->colorimetry; - const GstVideoColorimetry *out_color = &out_info->colorimetry; - ConvertInfo *cinfo = &priv->convert_info; - PSColorSpace *to_rgb_buf = &priv->const_data.to_rgb_buf; - PSColorSpace *to_yuv_buf = &priv->const_data.to_yuv_buf; - PSColorSpace *XYZ_convert_buf = &priv->const_data.XYZ_convert_buf; - GstD3D11ColorMatrix to_rgb_matrix; - GstD3D11ColorMatrix to_yuv_matrix; - GstD3D11ColorMatrix XYZ_convert_matrix; - gchar *matrix_dump; - GstVideoInfo in_rgb_info = *in_info; - GstVideoInfo out_rgb_info = *out_info; - - g_assert (GST_VIDEO_INFO_IS_RGB (in_info) || GST_VIDEO_INFO_IS_YUV (in_info)); - g_assert (GST_VIDEO_INFO_IS_RGB (out_info) - || GST_VIDEO_INFO_IS_YUV (out_info)); - - memset (&to_rgb_matrix, 0, sizeof (GstD3D11ColorMatrix)); - memset (&to_yuv_matrix, 0, sizeof (GstD3D11ColorMatrix)); - memset (&XYZ_convert_matrix, 0, sizeof (GstD3D11ColorMatrix)); - - for (guint i = 0; i < 2; i++) { - cinfo->to_rgb_func[i] = templ_COLOR_SPACE_IDENTITY; - cinfo->to_yuv_func[i] = templ_COLOR_SPACE_IDENTITY; - } - - cinfo->XYZ_convert_func = templ_XYZ_CONVERT_IDENTITY; - cinfo->gamma_decode_func = templ_GAMMA_DECODE; - cinfo->gamma_encode_func = templ_GAMMA_ENCODE; - - /* 1) convert input to 0..255 range RGB */ - if (GST_VIDEO_INFO_IS_RGB (in_info) && - in_color->range == GST_VIDEO_COLOR_RANGE_16_235) { - in_rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; - - if (!gst_d3d11_color_range_adjust_matrix_unorm (in_info, &in_rgb_info, - &to_rgb_matrix)) { - GST_ERROR_OBJECT (self, "Failed to get RGB range adjust matrix"); - return FALSE; - } - - matrix_dump = gst_d3d11_dump_color_matrix (&to_rgb_matrix); - GST_DEBUG_OBJECT (self, "Input RGB range adjust matrix\n%s", matrix_dump); - g_free (matrix_dump); - - cinfo->to_rgb_func[0] = cinfo->to_rgb_func[1] = templ_COLOR_SPACE_CONVERT; - } else if (GST_VIDEO_INFO_IS_YUV (in_info)) { - GstVideoInfo yuv_info; - GstVideoFormat rgb_format; - - yuv_info = *in_info; - if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || - yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { - GST_WARNING_OBJECT (self, "Invalid matrix is detected"); - yuv_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; - } - - if (in_info->finfo->depth[0] == 8) { - rgb_format = GST_VIDEO_FORMAT_RGBA; - } else { - rgb_format = GST_VIDEO_FORMAT_RGBA64_LE; - } - - gst_video_info_set_format (&in_rgb_info, rgb_format, in_info->width, - in_info->height); - in_rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; - in_rgb_info.colorimetry.transfer = in_color->transfer; - in_rgb_info.colorimetry.primaries = in_color->primaries; - - if (!gst_d3d11_yuv_to_rgb_matrix_unorm (&yuv_info, &in_rgb_info, - &to_rgb_matrix)) { - GST_ERROR_OBJECT (self, "Failed to get YUV -> RGB transform matrix"); - return FALSE; - } - - matrix_dump = gst_d3d11_dump_color_matrix (&to_rgb_matrix); - GST_DEBUG_OBJECT (self, "YUV -> RGB matrix:\n%s", matrix_dump); - g_free (matrix_dump); - - cinfo->to_rgb_func[0] = cinfo->to_rgb_func[1] = templ_COLOR_SPACE_CONVERT; - } - - /* 2) convert gamma/XYZ converted 0..255 RGB to output format */ - if (GST_VIDEO_INFO_IS_RGB (out_info) && - out_color->range == GST_VIDEO_COLOR_RANGE_16_235) { - out_rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; - - if (!gst_d3d11_color_range_adjust_matrix_unorm (&out_rgb_info, out_info, - &to_yuv_matrix)) { - GST_ERROR_OBJECT (self, "Failed to get RGB range adjust matrix"); - return FALSE; - } - - matrix_dump = gst_d3d11_dump_color_matrix (&to_yuv_matrix); - GST_DEBUG_OBJECT (self, "Output RGB range adjust matrix\n%s", matrix_dump); - g_free (matrix_dump); - - cinfo->to_yuv_func[0] = cinfo->to_yuv_func[1] = templ_COLOR_SPACE_CONVERT; - } else if (GST_VIDEO_INFO_IS_YUV (out_info)) { - GstVideoInfo yuv_info; - - yuv_info = *out_info; - if (yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || - yuv_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { - GST_WARNING_OBJECT (self, "Invalid matrix is detected"); - yuv_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; - } - - gst_video_info_set_format (&out_rgb_info, - GST_VIDEO_INFO_FORMAT (&in_rgb_info), out_info->width, - out_info->height); - out_rgb_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; - out_rgb_info.colorimetry.transfer = out_color->transfer; - out_rgb_info.colorimetry.primaries = out_color->primaries; - - if (!gst_d3d11_rgb_to_yuv_matrix_unorm (&out_rgb_info, - &yuv_info, &to_yuv_matrix)) { - GST_ERROR_OBJECT (self, "Failed to get RGB -> YUV transform matrix"); - return FALSE; - } - - matrix_dump = gst_d3d11_dump_color_matrix (&to_yuv_matrix); - GST_DEBUG_OBJECT (self, "RGB -> YUV matrix:\n%s", matrix_dump); - g_free (matrix_dump); - - if (GST_VIDEO_INFO_N_PLANES (out_info) == 1 || - cinfo->ps_output[0] == &output_types[OUTPUT_THREE_PLANES]) { - /* YUV packed or Y444 */ - cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT; - } else { - cinfo->to_yuv_func[0] = templ_COLOR_SPACE_CONVERT_LUMA; - cinfo->to_yuv_func[1] = templ_COLOR_SPACE_CONVERT_CHROMA; - } - } - - /* TODO: handle HDR mastring display info */ - if (priv->do_primaries) { - const GstVideoColorPrimariesInfo *in_pinfo; - const GstVideoColorPrimariesInfo *out_pinfo; - - in_pinfo = gst_video_color_primaries_get_info (in_color->primaries); - out_pinfo = gst_video_color_primaries_get_info (out_color->primaries); - - if (!gst_d3d11_color_primaries_matrix_unorm (in_pinfo, out_pinfo, - &XYZ_convert_matrix)) { - GST_ERROR_OBJECT (self, "Failed to get primaries conversion matrix"); - return FALSE; - } - - matrix_dump = gst_d3d11_dump_color_matrix (&XYZ_convert_matrix); - GST_DEBUG_OBJECT (self, "Primaries conversion matrix:\n%s", matrix_dump); - g_free (matrix_dump); - - cinfo->XYZ_convert_func = templ_XYZ_CONVERT; - } - - for (guint i = 0; i < 3; i++) { - to_rgb_buf->coeffX[i] = to_rgb_matrix.matrix[0][i]; - to_rgb_buf->coeffY[i] = to_rgb_matrix.matrix[1][i]; - to_rgb_buf->coeffZ[i] = to_rgb_matrix.matrix[2][i]; - to_rgb_buf->offset[i] = to_rgb_matrix.offset[i]; - to_rgb_buf->min[i] = to_rgb_matrix.min[i]; - to_rgb_buf->max[i] = to_rgb_matrix.max[i]; - - to_yuv_buf->coeffX[i] = to_yuv_matrix.matrix[0][i]; - to_yuv_buf->coeffY[i] = to_yuv_matrix.matrix[1][i]; - to_yuv_buf->coeffZ[i] = to_yuv_matrix.matrix[2][i]; - to_yuv_buf->offset[i] = to_yuv_matrix.offset[i]; - to_yuv_buf->min[i] = to_yuv_matrix.min[i]; - to_yuv_buf->max[i] = to_yuv_matrix.max[i]; - - XYZ_convert_buf->coeffX[i] = XYZ_convert_matrix.matrix[0][i]; - XYZ_convert_buf->coeffY[i] = XYZ_convert_matrix.matrix[1][i]; - XYZ_convert_buf->coeffZ[i] = XYZ_convert_matrix.matrix[2][i]; - XYZ_convert_buf->offset[i] = XYZ_convert_matrix.offset[i]; - XYZ_convert_buf->min[i] = XYZ_convert_matrix.min[i]; - XYZ_convert_buf->max[i] = XYZ_convert_matrix.max[i]; + primariesCoeff->coeffX[i] = primaries_coeff.matrix[0][i]; + primariesCoeff->coeffY[i] = primaries_coeff.matrix[1][i]; + primariesCoeff->coeffZ[i] = primaries_coeff.matrix[2][i]; + primariesCoeff->offset[i] = primaries_coeff.offset[i]; + primariesCoeff->min[i] = primaries_coeff.min[i]; + primariesCoeff->max[i] = primaries_coeff.max[i]; } return TRUE; @@ -2831,10 +1497,10 @@ gst_d3d11_converter_setup_lut (GstD3D11Converter * self, return FALSE; } - priv->gamma_dec_lut = gamma_dec_lut.Detach (); - priv->gamma_enc_lut = gamma_enc_lut.Detach (); - priv->gamma_dec_srv = gamma_dec_srv.Detach (); - priv->gamma_enc_srv = gamma_enc_srv.Detach (); + priv->gamma_dec_lut = gamma_dec_lut; + priv->gamma_enc_lut = gamma_enc_lut; + priv->gamma_dec_srv = gamma_dec_srv; + priv->gamma_enc_srv = gamma_enc_srv; return TRUE; } @@ -3136,13 +1802,12 @@ gst_d3d11_converter_setup_processor (GstD3D11Converter * self) out_space); priv->video_device = video_device; - video_device->AddRef (); - priv->processor = processor.Detach (); + priv->processor = processor; hr = video_context1.As (&video_context2); if (SUCCEEDED (hr)) - priv->video_context2 = video_context2.Detach (); - priv->video_context = video_context1.Detach (); - priv->enumerator = enumerator1.Detach (); + priv->video_context2 = video_context2; + priv->video_context = video_context1; + priv->enumerator = enumerator1; priv->src_rect.left = 0; priv->src_rect.top = 0; @@ -3189,6 +1854,8 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info, gboolean allow_primaries = FALSE; D3D11_FILTER sampler_filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; gchar *backend_str; + GstVideoInfo matrix_in_info; + GstVideoInfo matrix_out_info; g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), nullptr); g_return_val_if_fail (in_info != nullptr, nullptr); @@ -3226,12 +1893,6 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info, gst_structure_free (config); } - if (priv->src_alpha_mode == GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED) - priv->const_data.in_premul_alpha = TRUE; - - if (priv->dst_alpha_mode == GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED) - priv->const_data.out_premul_alpha = TRUE; - if (!wanted_backend) { wanted_backend = GST_D3D11_CONVERTER_BACKEND_SHADER | @@ -3254,7 +1915,6 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info, GST_ERROR_OBJECT (self, "%s couldn't be converted to d3d11 format", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info))); gst_object_unref (self); - return nullptr; } @@ -3263,12 +1923,10 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info, GST_ERROR_OBJECT (self, "%s couldn't be converted to d3d11 format", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info))); gst_object_unref (self); - return nullptr; } self->device = (GstD3D11Device *) gst_object_ref (device); - priv->fast_path = TRUE; priv->const_data.alpha = 1.0; priv->in_info = *in_info; priv->fallback_info = *in_info; @@ -3323,43 +1981,36 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info, if ((wanted_backend & GST_D3D11_CONVERTER_BACKEND_SHADER) == 0) goto out; - if (!GST_VIDEO_INFO_IS_GRAY (in_info) && !GST_VIDEO_INFO_IS_GRAY (out_info)) { - if (in_info->colorimetry.transfer != GST_VIDEO_TRANSFER_UNKNOWN && - out_info->colorimetry.transfer != GST_VIDEO_TRANSFER_UNKNOWN && - !gst_video_transfer_function_is_equivalent (in_info-> - colorimetry.transfer, GST_VIDEO_INFO_COMP_DEPTH (in_info, 0), - out_info->colorimetry.transfer, GST_VIDEO_INFO_COMP_DEPTH (out_info, - 0))) { - if (allow_gamma) { - GST_DEBUG_OBJECT (self, "Different transfer function %d -> %d", - in_info->colorimetry.transfer, out_info->colorimetry.transfer); - priv->fast_path = FALSE; - } else { - GST_DEBUG_OBJECT (self, - "Different transfer function %d -> %d but gamma remap is disabled", - in_info->colorimetry.transfer, out_info->colorimetry.transfer); - } - } - - if (in_info->colorimetry.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN && - out_info->colorimetry.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN && - !gst_video_color_primaries_is_equivalent (in_info-> - colorimetry.primaries, out_info->colorimetry.primaries)) { - if (allow_primaries) { - GST_DEBUG_OBJECT (self, "Different primaries %d -> %d", - in_info->colorimetry.primaries, out_info->colorimetry.primaries); - priv->fast_path = FALSE; - priv->do_primaries = TRUE; - } else { - GST_DEBUG_OBJECT (self, - "Different primaries %d -> %d but chromatic adaptation is disabled", - in_info->colorimetry.primaries, out_info->colorimetry.primaries); - } - } + priv->convert_type = CONVERT_TYPE::IDENTITY; + if (GST_VIDEO_INFO_IS_RGB (in_info) != GST_VIDEO_INFO_IS_RGB (out_info)) { + priv->convert_type = CONVERT_TYPE::SIMPLE; + } else if (in_info->colorimetry.range != GST_VIDEO_COLOR_RANGE_UNKNOWN && + out_info->colorimetry.range != GST_VIDEO_COLOR_RANGE_UNKNOWN && + in_info->colorimetry.range != out_info->colorimetry.range) { + priv->convert_type = CONVERT_TYPE::RANGE; } - if (!gst_d3d11_converter_prepare_output (self, out_info)) - goto out; + if (allow_gamma && + in_info->colorimetry.transfer != GST_VIDEO_TRANSFER_UNKNOWN && + out_info->colorimetry.transfer != GST_VIDEO_TRANSFER_UNKNOWN && + !gst_video_transfer_function_is_equivalent (in_info->colorimetry.transfer, + GST_VIDEO_INFO_COMP_DEPTH (in_info, 0), + out_info->colorimetry.transfer, GST_VIDEO_INFO_COMP_DEPTH (out_info, + 0))) { + GST_DEBUG_OBJECT (self, "Different transfer function %d -> %d", + in_info->colorimetry.transfer, out_info->colorimetry.transfer); + priv->convert_type = CONVERT_TYPE::GAMMA; + } + + if (allow_primaries && + in_info->colorimetry.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN && + out_info->colorimetry.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN && + !gst_video_color_primaries_is_equivalent (in_info->colorimetry.primaries, + out_info->colorimetry.primaries)) { + GST_DEBUG_OBJECT (self, "Different primaries %d -> %d", + in_info->colorimetry.primaries, out_info->colorimetry.primaries); + priv->convert_type = CONVERT_TYPE::PRIMARY; + } /* XXX: hard to make sampling of packed 4:2:2 format, use software * converter to convert YUV2 to Y42B */ @@ -3380,7 +2031,6 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info, gst_video_converter_new (in_info, &tmp_info, nullptr); if (!priv->unpack_convert) { GST_ERROR_OBJECT (self, "Couldn't create unpack convert"); - priv->supported_backend = (GstD3D11ConverterBackend) 0; goto out; } @@ -3388,20 +2038,37 @@ gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info, in_info = &priv->fallback_info; } - if (!gst_d3d11_converter_prepare_sample_texture (self, in_info, out_info)) - goto out; - - if (priv->fast_path) { - if (!gst_d3d11_converter_prepare_colorspace_fast (self, in_info, out_info)) - goto out; - } else { - if (!gst_d3d11_converter_prepare_colorspace (self, in_info, out_info)) - goto out; - + if ((priv->convert_type == CONVERT_TYPE::GAMMA || + priv->convert_type == CONVERT_TYPE::PRIMARY)) { if (!gst_d3d11_converter_setup_lut (self, in_info, out_info)) goto out; } + if (GST_VIDEO_INFO_IS_RGB (in_info)) { + matrix_in_info = *in_info; + } else { + convert_info_gray_to_yuv (in_info, &matrix_in_info); + if (matrix_in_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || + matrix_in_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { + matrix_in_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; + } + } + + if (GST_VIDEO_INFO_IS_RGB (out_info)) { + matrix_out_info = *out_info; + } else { + convert_info_gray_to_yuv (out_info, &matrix_out_info); + if (matrix_out_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN || + matrix_out_info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB) { + matrix_out_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; + } + } + + if (!gst_d3d11_converter_calculate_matrix (self, + &matrix_in_info, &matrix_out_info)) { + goto out; + } + if (!gst_d3d11_color_convert_setup_shader (self, in_info, out_info, sampler_filter)) { goto out; @@ -3430,14 +2097,12 @@ gst_d3d11_converter_convert_internal (GstD3D11Converter * self, ComPtr < ID3D11Resource > resource; ComPtr < ID3D11Texture2D > texture; D3D11_TEXTURE2D_DESC desc; - ConvertInfo *cinfo; ID3D11DeviceContext *context; UINT offsets = 0; UINT vertex_stride = sizeof (VertexData); ID3D11ShaderResourceView *clear_view[GST_VIDEO_MAX_PLANES] = { nullptr, }; priv = self->priv; - cinfo = &priv->convert_info; context = gst_d3d11_device_get_device_context_handle (self->device); /* check texture resolution and update crop area */ @@ -3465,8 +2130,8 @@ gst_d3d11_converter_convert_internal (GstD3D11Converter * self, PSConstBuffer *const_buffer; HRESULT hr; - hr = context->Map (priv->const_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - + hr = context->Map (priv->const_buffer.Get (), + 0, D3D11_MAP_WRITE_DISCARD, 0, &map); if (!gst_d3d11_result (hr, self->device)) { GST_ERROR_OBJECT (self, "Couldn't map constant buffer, hr: 0x%x", (guint) hr); @@ -3476,7 +2141,7 @@ gst_d3d11_converter_convert_internal (GstD3D11Converter * self, const_buffer = (PSConstBuffer *) map.pData; memcpy (const_buffer, &priv->const_data, sizeof (PSConstBuffer)); - context->Unmap (priv->const_buffer, 0); + context->Unmap (priv->const_buffer.Get (), 0); priv->update_alpha = FALSE; } @@ -3486,40 +2151,47 @@ gst_d3d11_converter_convert_internal (GstD3D11Converter * self, } context->IASetPrimitiveTopology (D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - context->IASetInputLayout (priv->layout); - context->IASetVertexBuffers (0, 1, &priv->vertex_buffer, &vertex_stride, - &offsets); - context->IASetIndexBuffer (priv->index_buffer, DXGI_FORMAT_R16_UINT, 0); - context->PSSetSamplers (0, 1, &priv->linear_sampler); - context->VSSetShader (priv->vs, nullptr, 0); - context->PSSetConstantBuffers (0, 1, &priv->const_buffer); + 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); + + ID3D11SamplerState *samplers[] = { priv->sampler.Get (), + priv->linear_sampler.Get () + }; + context->PSSetSamplers (0, 2, samplers); + context->VSSetShader (priv->vs.Get (), nullptr, 0); + + ID3D11Buffer *const_buffer[] = { priv->const_buffer.Get () }; + context->PSSetConstantBuffers (0, 1, const_buffer); context->PSSetShaderResources (0, priv->num_input_view, srv); - if (!priv->fast_path) { - ID3D11ShaderResourceView *gamma_srv[2]; - gamma_srv[0] = priv->gamma_dec_srv; - gamma_srv[1] = priv->gamma_enc_srv; + if (priv->gamma_enc_srv) { + ID3D11ShaderResourceView *gamma_srv[] = { priv->gamma_dec_srv.Get (), + priv->gamma_enc_srv.Get () + }; context->PSSetShaderResources (4, 2, gamma_srv); } - context->PSSetShader (priv->ps[0], nullptr, 0); - context->RSSetViewports (cinfo->ps_output[0]->num_rtv, priv->viewport); - context->OMSetRenderTargets (cinfo->ps_output[0]->num_rtv, rtv, nullptr); + auto ps = priv->ps[0]; + context->PSSetShader (ps->shader.Get (), nullptr, 0); + context->RSSetViewports (ps->num_rtv, priv->viewport); + context->OMSetRenderTargets (ps->num_rtv, rtv, nullptr); if (priv->blend) { - context->OMSetBlendState (priv->blend, + context->OMSetBlendState (priv->blend.Get (), priv->blend_factor, priv->blend_sample_mask); } else { context->OMSetBlendState (nullptr, nullptr, 0xffffffff); } context->DrawIndexed (6, 0, 0); - if (priv->ps[1]) { - guint view_offset = cinfo->ps_output[0]->num_rtv; + if (priv->ps.size () == 2) { + guint view_offset = ps->num_rtv; + ps = priv->ps[1]; - context->PSSetShader (priv->ps[1], nullptr, 0); - context->RSSetViewports (cinfo->ps_output[1]->num_rtv, - &priv->viewport[view_offset]); - context->OMSetRenderTargets (cinfo->ps_output[1]->num_rtv, - &rtv[view_offset], nullptr); + context->PSSetShader (ps->shader.Get (), nullptr, 0); + context->RSSetViewports (ps->num_rtv, &priv->viewport[view_offset]); + context->OMSetRenderTargets (ps->num_rtv, &rtv[view_offset], nullptr); context->DrawIndexed (6, 0, 0); } @@ -4080,8 +2752,8 @@ gst_d3d11_converter_do_processor_blt (GstD3D11Converter * self, GstD3D11ConverterPrivate *priv = self->priv; ID3D11VideoProcessorInputView *piv = nullptr; ID3D11VideoProcessorOutputView *pov = nullptr; - ID3D11VideoContext1 *video_ctx = priv->video_context; - ID3D11VideoProcessor *proc = priv->processor; + ID3D11VideoContext1 *video_ctx = priv->video_context.Get (); + ID3D11VideoProcessor *proc = priv->processor.Get (); D3D11_VIDEO_PROCESSOR_STREAM stream = { 0, }; HRESULT hr; GstMemory *in_mem, *out_mem; @@ -4113,14 +2785,14 @@ gst_d3d11_converter_do_processor_blt (GstD3D11Converter * self, out_dmem = GST_D3D11_MEMORY_CAST (out_mem); piv = gst_d3d11_memory_get_processor_input_view (in_dmem, - priv->video_device, priv->enumerator); + priv->video_device.Get (), priv->enumerator.Get ()); if (!piv) { GST_ERROR_OBJECT (self, "PIV is unavailable"); goto out; } pov = gst_d3d11_memory_get_processor_output_view (out_dmem, - priv->video_device, priv->enumerator); + priv->video_device.Get (), priv->enumerator.Get ()); if (!pov) { GST_ERROR_OBJECT (self, "POV is unavailable"); goto out; diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converterbuilder.cpp b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converterbuilder.cpp new file mode 100644 index 0000000000..8e82f84fa2 --- /dev/null +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converterbuilder.cpp @@ -0,0 +1,438 @@ +/* GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstd3d11converterbuilder.h" +#include "gstd3d11device-private.h" +#include "gstd3d11-private.h" +#include +#include +#include +#include +#include + +/* *INDENT-OFF* */ +using namespace Microsoft::WRL; + +struct ConverterPSSource +{ + gint64 token; + std::string entry_point; + const BYTE *bytecode; + SIZE_T bytecode_size; + std::vector> macros; + guint num_rtv; +}; + +enum class PS_OUTPUT +{ + PACKED, + LUMA, + CHROMA, + CHROMA_PLANAR, + PLANAR, + PLANAR_FULL, +}; + +static std::map> ps_source_cache; +static std::mutex cache_lock; +#ifdef HLSL_PRECOMPILED +#include "PSMainConverter.h" +#include "VSMain_converter.h" +#else +static const std::map> precompiled_bytecode; +#endif + +#include "hlsl/PSMain_converter.hlsl" +#include "hlsl/VSMain_converter.hlsl" + +static const std::string +ps_output_to_string (PS_OUTPUT output) +{ + switch (output) { + case PS_OUTPUT::PACKED: + return "PS_OUTPUT_PACKED"; + case PS_OUTPUT::LUMA: + return "PS_OUTPUT_LUMA"; + case PS_OUTPUT::CHROMA: + return "PS_OUTPUT_CHROMA"; + case PS_OUTPUT::CHROMA_PLANAR: + return "PS_OUTPUT_CHROMA_PLANAR"; + case PS_OUTPUT::PLANAR: + return "PS_OUTPUT_PLANAR"; + case PS_OUTPUT::PLANAR_FULL: + return "PS_OUTPUT_PLANAR_FULL"; + default: + g_assert_not_reached (); + break; + } + + return ""; +} + +static guint +ps_output_get_num_rtv (PS_OUTPUT output) +{ + switch (output) { + case PS_OUTPUT::PACKED: + case PS_OUTPUT::LUMA: + case PS_OUTPUT::CHROMA: + return 1; + case PS_OUTPUT::CHROMA_PLANAR: + return 2; + case PS_OUTPUT::PLANAR: + return 3; + case PS_OUTPUT::PLANAR_FULL: + return 4; + default: + g_assert_not_reached (); + break; + } + + return 0; +} + +static std::string +make_input (GstVideoFormat format, gboolean premul) +{ + switch (format) { + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_RGBA64_LE: + case GST_VIDEO_FORMAT_RGB10A2_LE: + case GST_VIDEO_FORMAT_BGRA: + if (premul) + return "RGBAPremul"; + return "RGBA"; + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + return "RGBx"; + case GST_VIDEO_FORMAT_VUYA: + if (premul) + return "VUYAPremul"; + return "VUYA"; + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_AYUV64: + return "AYUV"; + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_P010_10LE: + case GST_VIDEO_FORMAT_P012_LE: + case GST_VIDEO_FORMAT_P016_LE: + return "NV12"; + case GST_VIDEO_FORMAT_NV21: + return "NV21"; + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_Y444_16LE: + return "I420"; + case GST_VIDEO_FORMAT_YV12: + return "YV12"; + case GST_VIDEO_FORMAT_I420_10LE: + case GST_VIDEO_FORMAT_I422_10LE: + case GST_VIDEO_FORMAT_Y444_10LE: + return "I420_10"; + case GST_VIDEO_FORMAT_I420_12LE: + case GST_VIDEO_FORMAT_I422_12LE: + case GST_VIDEO_FORMAT_Y444_12LE: + return "I420_12"; + case GST_VIDEO_FORMAT_Y410: + return "Y410"; + case GST_VIDEO_FORMAT_GRAY8: + case GST_VIDEO_FORMAT_GRAY16_LE: + return "GRAY"; + case GST_VIDEO_FORMAT_RGBP: + return "RGBP"; + case GST_VIDEO_FORMAT_BGRP: + return "BGRP"; + case GST_VIDEO_FORMAT_GBR: + case GST_VIDEO_FORMAT_GBR_16LE: + return "GBR"; + case GST_VIDEO_FORMAT_GBR_10LE: + return "GBR_10"; + case GST_VIDEO_FORMAT_GBR_12LE: + return "GBR_12"; + case GST_VIDEO_FORMAT_GBRA: + if (premul) + return "GBRAPremul"; + return "GBRA"; + case GST_VIDEO_FORMAT_GBRA_10LE: + if (premul) + return "GBRAPremul_10"; + return "GBRA_10"; + case GST_VIDEO_FORMAT_GBRA_12LE: + if (premul) + return "GBRAPremul_12"; + return "GBRA_12"; + default: + g_assert_not_reached (); + break; + } + + return ""; +} + +static std::vector> +make_output (GstVideoFormat format, gboolean premul) +{ + std::vector> ret; + + switch (format) { + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_RGBA64_LE: + case GST_VIDEO_FORMAT_RGB10A2_LE: + case GST_VIDEO_FORMAT_BGRA: + if (premul) + ret.push_back(std::make_pair(PS_OUTPUT::PACKED, "RGBAPremul")); + else + ret.push_back(std::make_pair(PS_OUTPUT::PACKED, "RGBA")); + break; + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + ret.push_back(std::make_pair(PS_OUTPUT::PACKED, "RGBx")); + break; + case GST_VIDEO_FORMAT_VUYA: + if (premul) + ret.push_back(std::make_pair(PS_OUTPUT::PACKED, "VUYAPremul")); + else + ret.push_back(std::make_pair(PS_OUTPUT::PACKED, "VUYA")); + break; + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_AYUV64: + ret.push_back(std::make_pair(PS_OUTPUT::PACKED, "AYUV")); + break; + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_P010_10LE: + case GST_VIDEO_FORMAT_P012_LE: + case GST_VIDEO_FORMAT_P016_LE: + ret.push_back(std::make_pair(PS_OUTPUT::LUMA, "Luma")); + ret.push_back(std::make_pair(PS_OUTPUT::CHROMA, "ChromaNV12")); + break; + case GST_VIDEO_FORMAT_NV21: + ret.push_back(std::make_pair(PS_OUTPUT::LUMA, "Luma")); + ret.push_back(std::make_pair(PS_OUTPUT::CHROMA, "ChromaNV21")); + break; + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_Y42B: + ret.push_back(std::make_pair(PS_OUTPUT::LUMA, "Luma")); + ret.push_back(std::make_pair(PS_OUTPUT::CHROMA_PLANAR, "ChromaI420")); + break; + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_Y444_16LE: + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR, "Y444")); + break; + case GST_VIDEO_FORMAT_YV12: + ret.push_back(std::make_pair(PS_OUTPUT::LUMA, "Luma")); + ret.push_back(std::make_pair(PS_OUTPUT::CHROMA_PLANAR, "ChromaYV12")); + break; + case GST_VIDEO_FORMAT_I420_10LE: + case GST_VIDEO_FORMAT_I422_10LE: + ret.push_back(std::make_pair(PS_OUTPUT::LUMA, "Luma_10")); + ret.push_back(std::make_pair(PS_OUTPUT::CHROMA_PLANAR, "ChromaI420_10")); + break; + case GST_VIDEO_FORMAT_Y444_10LE: + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR, "Y444_10")); + break; + case GST_VIDEO_FORMAT_I420_12LE: + case GST_VIDEO_FORMAT_I422_12LE: + ret.push_back(std::make_pair(PS_OUTPUT::LUMA, "Luma_12")); + ret.push_back(std::make_pair(PS_OUTPUT::CHROMA_PLANAR, "ChromaI420_12")); + break; + case GST_VIDEO_FORMAT_Y444_12LE: + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR, "Y444_12")); + break; + case GST_VIDEO_FORMAT_GRAY8: + case GST_VIDEO_FORMAT_GRAY16_LE: + ret.push_back(std::make_pair(PS_OUTPUT::LUMA, "Luma")); + break; + case GST_VIDEO_FORMAT_RGBP: + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR, "RGBP")); + break; + case GST_VIDEO_FORMAT_BGRP: + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR, "BGRP")); + break; + case GST_VIDEO_FORMAT_GBR: + case GST_VIDEO_FORMAT_GBR_16LE: + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR, "GBR")); + break; + case GST_VIDEO_FORMAT_GBR_10LE: + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR, "GBR_10")); + break; + case GST_VIDEO_FORMAT_GBR_12LE: + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR, "GBR_12")); + break; + case GST_VIDEO_FORMAT_GBRA: + if (premul) + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR_FULL, "GBRAPremul")); + else + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR_FULL, "GBRA")); + break; + case GST_VIDEO_FORMAT_GBRA_10LE: + if (premul) + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR_FULL, "GBRAPremul_10")); + else + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR_FULL, "GBRA_10")); + break; + case GST_VIDEO_FORMAT_GBRA_12LE: + if (premul) + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR_FULL, "GBRAPremul_12")); + else + ret.push_back(std::make_pair(PS_OUTPUT::PLANAR_FULL, "GBRA_12")); + break; + default: + g_assert_not_reached (); + break; + } + + return ret; +} + +PixelShaderList +gst_d3d11_get_converter_pixel_shader (GstD3D11Device * device, + GstVideoFormat in_format, GstVideoFormat out_format, gboolean in_premul, + gboolean out_premul, CONVERT_TYPE type) +{ + HRESULT hr; + auto input = make_input (in_format, in_premul); + auto output = make_output (out_format, out_premul); + std::string conv_type; + PixelShaderList ret; + + switch (type) { + case CONVERT_TYPE::IDENTITY: + conv_type = "Identity"; + break; + case CONVERT_TYPE::SIMPLE: + conv_type = "Simple"; + break; + case CONVERT_TYPE::RANGE: + conv_type = "Range"; + break; + case CONVERT_TYPE::GAMMA: + conv_type = "Gamma"; + break; + case CONVERT_TYPE::PRIMARY: + conv_type = "Primary"; + break; + } + + for (const auto & it : output) { + std::string entry_point = "PSMain_" + input + "_" + conv_type + "_" + + it.second; + std::shared_ptr source; + std::vector macros; + ComPtr shader; + cache_lock.lock (); + auto cached = ps_source_cache.find(entry_point); + if (cached != ps_source_cache.end()) { + source = cached->second; + } else { + source = std::make_shared (); + source->token = gst_d3d11_pixel_shader_token_new (); + source->entry_point = entry_point; + auto precompiled = precompiled_bytecode.find (entry_point); + if (precompiled != precompiled_bytecode.end ()) { + source->bytecode = precompiled->second.first; + source->bytecode_size = precompiled->second.second; + } else { + source->bytecode = nullptr; + source->bytecode_size = 0; + } + + source->num_rtv = ps_output_get_num_rtv (it.first); + + source->macros.push_back(std::make_pair("ENTRY_POINT", entry_point)); + source->macros.push_back(std::make_pair("SAMPLER", "Sampler" + input)); + source->macros.push_back(std::make_pair("CONVERTER", + "Converter" + conv_type)); + source->macros.push_back(std::make_pair("OUTPUT_TYPE", + ps_output_to_string(it.first))); + source->macros.push_back(std::make_pair("OUTPUT_BUILDER", + "Output" + it.second)); + ps_source_cache[entry_point] = source; + } + cache_lock.unlock (); + + for (const auto & defines : source->macros) + macros.push_back({defines.first.c_str (), defines.second.c_str ()}); + + macros.push_back({nullptr, nullptr}); + + hr = gst_d3d11_device_get_pixel_shader_uncached (device, source->token, + source->bytecode, source->bytecode_size, g_PSMain_converter_str, + sizeof (g_PSMain_converter_str), source->entry_point.c_str (), + ¯os[0], &shader); + if (FAILED (hr)) { + ret.clear (); + return ret; + } + + auto ps = std::make_shared (); + ps->shader = shader; + ps->num_rtv = source->num_rtv; + + ret.push_back (ps); + } + + return ret; +} +/* *INDENT-ON* */ + +HRESULT +gst_d3d11_get_converter_vertex_shader (GstD3D11Device * device, + ID3D11VertexShader ** vs, ID3D11InputLayout ** layout) +{ + static gint64 token = 0; + const void *bytecode = nullptr; + gsize bytecode_size = 0; + + GST_D3D11_CALL_ONCE_BEGIN { + token = gst_d3d11_vertex_shader_token_new (); + } GST_D3D11_CALL_ONCE_END; + +#ifdef HLSL_PRECOMPILED + bytecode = g_VSMain_converter; + bytecode_size = sizeof (g_VSMain_converter); +#endif + + D3D11_INPUT_ELEMENT_DESC input_desc[2]; + + input_desc[0].SemanticName = "POSITION"; + input_desc[0].SemanticIndex = 0; + input_desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; + input_desc[0].InputSlot = 0; + input_desc[0].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + input_desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + input_desc[0].InstanceDataStepRate = 0; + + input_desc[1].SemanticName = "TEXCOORD"; + input_desc[1].SemanticIndex = 0; + input_desc[1].Format = DXGI_FORMAT_R32G32_FLOAT; + input_desc[1].InputSlot = 0; + input_desc[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + input_desc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + input_desc[1].InstanceDataStepRate = 0; + + return gst_d3d11_device_get_vertex_shader (device, token, + bytecode, bytecode_size, g_VSMain_converter_str, + sizeof (g_VSMain_converter_str), "VSMain_converter", input_desc, + G_N_ELEMENTS (input_desc), vs, layout); +} diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converterbuilder.h b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converterbuilder.h new file mode 100644 index 0000000000..bce879abc2 --- /dev/null +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converterbuilder.h @@ -0,0 +1,57 @@ +/* GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +enum class CONVERT_TYPE +{ + IDENTITY, + SIMPLE, + RANGE, + GAMMA, + PRIMARY, +}; + +struct PixelShader +{ + Microsoft::WRL::ComPtr shader; + guint num_rtv; +}; + +typedef std::vector> PixelShaderList; + +PixelShaderList +gst_d3d11_get_converter_pixel_shader (GstD3D11Device * device, + GstVideoFormat in_format, + GstVideoFormat out_format, + gboolean in_premul, + gboolean out_premul, + CONVERT_TYPE type); + +HRESULT gst_d3d11_get_converter_vertex_shader (GstD3D11Device * device, + ID3D11VertexShader ** vs, + ID3D11InputLayout ** layout); diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11device-private.h b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11device-private.h index 4d84104798..1c923ed5b4 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11device-private.h +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11device-private.h @@ -38,8 +38,20 @@ HRESULT gst_d3d11_device_get_pixel_shader (GstD3D11Device * device, const gchar * source, gsize source_size, const gchar * entry_point, + const D3D_SHADER_MACRO * defines, ID3D11PixelShader ** ps); +GST_D3D11_API +HRESULT gst_d3d11_device_get_pixel_shader_uncached (GstD3D11Device * device, + gint64 token, + const void * bytecode, + gsize bytecode_size, + const gchar * source, + gsize source_size, + const gchar * entry_point, + const D3D_SHADER_MACRO * defines, + ID3D11PixelShader ** ps); + GST_D3D11_API HRESULT gst_d3d11_device_get_vertex_shader (GstD3D11Device * device, gint64 token, diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11device.cpp b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11device.cpp index fe891c5d45..3da32f7a70 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11device.cpp +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11device.cpp @@ -1704,10 +1704,73 @@ gst_d3d11_vertex_shader_token_new (void) return token_.fetch_add (1); } +HRESULT +gst_d3d11_device_get_pixel_shader_uncached (GstD3D11Device * device, + gint64 token, const void *bytecode, gsize bytecode_size, + const gchar * source, gsize source_size, const gchar * entry_point, + const D3D_SHADER_MACRO * defines, ID3D11PixelShader ** ps) +{ + GstD3D11DevicePrivate *priv = device->priv; + HRESULT hr; + ComPtr < ID3D11PixelShader > shader; + ComPtr < ID3DBlob > blob; + const void *data; + gsize size; + + GST_LOG_OBJECT (device, + "Creating pixel shader for token %" G_GINT64_FORMAT ", source:\n%s", + token, source); + + if (priv->feature_level >= D3D_FEATURE_LEVEL_11_0) { + if (bytecode && bytecode_size > 1) { + data = bytecode; + size = bytecode_size; + GST_DEBUG_OBJECT (device, + "Creating shader \"%s\" using precompiled bytecode", entry_point); + } else { + hr = gst_d3d11_shader_cache_get_pixel_shader_blob (token, + source, source_size, entry_point, defines, &blob); + if (!gst_d3d11_result (hr, device)) + return hr; + + data = blob->GetBufferPointer (); + size = blob->GetBufferSize (); + } + } else { + const gchar *target; + if (priv->feature_level >= D3D_FEATURE_LEVEL_10_0) + target = "ps_4_0"; + else if (priv->feature_level >= D3D_FEATURE_LEVEL_9_3) + target = "ps_4_0_level_9_3"; + else + target = "ps_4_0_level_9_1"; + + hr = gst_d3d11_compile (source, source_size, nullptr, defines, + nullptr, entry_point, target, 0, 0, &blob, nullptr); + if (!gst_d3d11_result (hr, device)) + return hr; + + data = blob->GetBufferPointer (); + size = blob->GetBufferSize (); + } + + hr = priv->device->CreatePixelShader (data, size, nullptr, &shader); + if (!gst_d3d11_result (hr, device)) + return hr; + + GST_DEBUG_OBJECT (device, + "Created pixel shader \"%s\" for token %" G_GINT64_FORMAT, + entry_point, token); + *ps = shader.Detach (); + + return S_OK; +} + HRESULT gst_d3d11_device_get_pixel_shader (GstD3D11Device * device, gint64 token, - const void *bytecode, gsize bytecode_len, const gchar * source, - gsize source_size, const gchar * entry_point, ID3D11PixelShader ** ps) + const void *bytecode, gsize bytecode_size, const gchar * source, + gsize source_size, const gchar * entry_point, + const D3D_SHADER_MACRO * defines, ID3D11PixelShader ** ps) { GstD3D11DevicePrivate *priv = device->priv; HRESULT hr; @@ -1727,43 +1790,11 @@ gst_d3d11_device_get_pixel_shader (GstD3D11Device * device, gint64 token, return S_OK; } - GST_LOG_OBJECT (device, - "Creating pixel shader for token %" G_GINT64_FORMAT ", source:\n%s", - token, source); + hr = gst_d3d11_device_get_pixel_shader_uncached (device, token, bytecode, + bytecode_size, source, source_size, entry_point, defines, &shader); + if (!gst_d3d11_result (hr, device)) + return hr; - if (priv->feature_level >= D3D_FEATURE_LEVEL_11_0) { - ComPtr < ID3DBlob > blob; - const void *data; - gsize size; - - if (bytecode && bytecode_len > 1) { - data = bytecode; - size = bytecode_len; - GST_DEBUG_OBJECT (device, - "Creating shader \"%s\" using precompiled bytecode", entry_point); - } else { - hr = gst_d3d11_shader_cache_get_pixel_shader_blob (token, - source, source_size, entry_point, &blob); - if (!gst_d3d11_result (hr, device)) - return hr; - - data = blob->GetBufferPointer (); - size = blob->GetBufferSize (); - } - - hr = priv->device->CreatePixelShader (data, size, nullptr, &shader); - if (!gst_d3d11_result (hr, device)) - return hr; - } else { - hr = gst_d3d11_create_pixel_shader_simple (device, source, entry_point, - &shader); - if (!gst_d3d11_result (hr, device)) - return hr; - } - - GST_DEBUG_OBJECT (device, - "Created pixel shader \"%s\" for token %" G_GINT64_FORMAT, - entry_point, token); priv->ps_cache[token] = shader; *ps = shader.Detach (); @@ -1772,7 +1803,7 @@ gst_d3d11_device_get_pixel_shader (GstD3D11Device * device, gint64 token, HRESULT gst_d3d11_device_get_vertex_shader (GstD3D11Device * device, gint64 token, - const void *bytecode, gsize bytecode_len, const gchar * source, + const void *bytecode, gsize bytecode_size, const gchar * source, gsize source_size, const gchar * entry_point, const D3D11_INPUT_ELEMENT_DESC * input_desc, guint desc_len, ID3D11VertexShader ** vs, ID3D11InputLayout ** layout) @@ -1807,9 +1838,9 @@ gst_d3d11_device_get_vertex_shader (GstD3D11Device * device, gint64 token, const void *data; gsize size; - if (bytecode && bytecode_len > 1) { + if (bytecode && bytecode_size > 1) { data = bytecode; - size = bytecode_len; + size = bytecode_size; GST_DEBUG_OBJECT (device, "Creating shader \"%s\" using precompiled bytecode", entry_point); } else { diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11format.cpp b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11format.cpp index af6ee93c78..6b1dcc4355 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11format.cpp +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11format.cpp @@ -987,6 +987,19 @@ color_matrix_identity (GstD3D11ColorMatrix * m) } } +void +gst_d3d11_color_matrix_init (GstD3D11ColorMatrix * matrix) +{ + g_return_if_fail (matrix); + + color_matrix_identity (matrix); + for (guint i = 0; i < 3; i++) { + matrix->min[i] = 0; + matrix->max[i] = 1; + matrix->offset[i] = 0; + } +} + static gboolean color_matrix_invert (GstD3D11ColorMatrix * dst, GstD3D11ColorMatrix * src) { diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11shadercache.cpp b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11shadercache.cpp index 36fe3f3b50..e2a1bde454 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11shadercache.cpp +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11shadercache.cpp @@ -36,7 +36,7 @@ static std::map vs_blob_; HRESULT gst_d3d11_shader_cache_get_pixel_shader_blob (gint64 token, const gchar * source, gsize source_size, const gchar * entry_point, - ID3DBlob ** blob) + const D3D_SHADER_MACRO * defines, ID3DBlob ** blob) { std::lock_guard < std::mutex > lk (cache_lock_); @@ -47,7 +47,7 @@ gst_d3d11_shader_cache_get_pixel_shader_blob (gint64 token, return S_OK; } - HRESULT hr = gst_d3d11_compile (source, source_size, nullptr, nullptr, + HRESULT hr = gst_d3d11_compile (source, source_size, nullptr, defines, nullptr, entry_point, "ps_5_0", 0, 0, blob, nullptr); if (FAILED (hr)) return hr; diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11shadercache.h b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11shadercache.h index bc4e0ee641..352a7c9ce5 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11shadercache.h +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11shadercache.h @@ -28,6 +28,7 @@ HRESULT gst_d3d11_shader_cache_get_pixel_shader_blob (gint64 token, const gchar * source, gsize source_size, const gchar * entry_point, + const D3D_SHADER_MACRO * defines, ID3DBlob ** blob); HRESULT gst_d3d11_shader_cache_get_vertex_shader_blob (gint64 token, diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/PSMain_converter.hlsl b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/PSMain_converter.hlsl new file mode 100644 index 0000000000..4db654c47d --- /dev/null +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/PSMain_converter.hlsl @@ -0,0 +1,1785 @@ +/* GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef BUILDING_HLSL +struct PSColorSpace +{ + float3 CoeffX; + float3 CoeffY; + float3 CoeffZ; + float3 Offset; + float3 Min; + float3 Max; + float padding; +}; + +cbuffer PsConstBuffer : register(b0) +{ + PSColorSpace preCoeff; + PSColorSpace postCoeff; + PSColorSpace primariesCoeff; + float alphaFactor; +}; + +Texture2D shaderTexture[4] : register(t0); +Texture1D gammaDecLUT : register(t4); +Texture1D gammaEncLUT: register(t5); +SamplerState samplerState : register(s0); +SamplerState linearSampler : register(s1); + +struct PS_INPUT +{ + float4 Position: SV_POSITION; + float2 Texture: TEXCOORD; +}; + +struct PS_OUTPUT_LUMA +{ + float Plane0: SV_TARGET0; +}; + +struct PS_OUTPUT_CHROMA +{ + float2 Plane0: SV_TARGET0; +}; + +struct PS_OUTPUT_CHROMA_PLANAR +{ + float Plane0: SV_TARGET0; + float Plane1: SV_TARGET1; +}; + +struct PS_OUTPUT_PLANAR +{ + float Plane0: SV_TARGET0; + float Plane1: SV_TARGET1; + float Plane2: SV_TARGET2; +}; + +struct PS_OUTPUT_PLANAR_FULL +{ + float Plane0: SV_TARGET0; + float Plane1: SV_TARGET1; + float Plane2: SV_TARGET2; + float Plane3: SV_TARGET3; +}; + +struct PS_OUTPUT_PACKED +{ + float4 Plane0: SV_TARGET0; +}; + +float4 DoAlphaPremul (float4 sample) +{ + float4 premul_tex; + premul_tex.rgb = sample.rgb * sample.a; + premul_tex.a = sample.a; + return premul_tex; +} + +float4 DoAlphaUnpremul (float4 sample) +{ + float4 unpremul_tex; + if (sample.a == 0 || sample.a == 1) + return sample; + + unpremul_tex.rgb = saturate (sample.rgb / sample.a); + unpremul_tex.a = sample.a; + return unpremul_tex; +} + +interface ISampler +{ + float4 Execute (float2 uv); +}; + +class SamplerGRAY : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.x = shaderTexture[0].Sample(samplerState, uv).x; + sample.y = 0.5; + sample.z = 0.5; + sample.a = 1.0; + return sample; + } +}; + +class SamplerNV12 : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.x = shaderTexture[0].Sample(samplerState, uv).x; + sample.yz = shaderTexture[1].Sample(samplerState, uv).xy; + sample.a = 1.0; + return sample; + } +}; + +class SamplerNV21 : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.x = shaderTexture[0].Sample(samplerState, uv).x; + sample.yz = shaderTexture[1].Sample(samplerState, uv).yx; + sample.a = 1.0; + return sample; + } +}; + +class SamplerI420 : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.x = shaderTexture[0].Sample(samplerState, uv).x; + sample.y = shaderTexture[1].Sample(samplerState, uv).x; + sample.z = shaderTexture[2].Sample(samplerState, uv).x; + sample.a = 1.0; + return sample; + } +}; + +class SamplerYV12 : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.x = shaderTexture[0].Sample(samplerState, uv).x; + sample.z = shaderTexture[1].Sample(samplerState, uv).x; + sample.y = shaderTexture[2].Sample(samplerState, uv).x; + sample.a = 1.0; + return sample; + } +}; + +class SamplerI420_10 : ISampler +{ + float4 Execute (float2 uv) + { + float3 sample; + sample.x = shaderTexture[0].Sample(samplerState, uv).x; + sample.y = shaderTexture[1].Sample(samplerState, uv).x; + sample.z = shaderTexture[2].Sample(samplerState, uv).x; + return float4 (saturate (sample * 64.0), 1.0); + } +}; + +class SamplerI420_12 : ISampler +{ + float4 Execute (float2 uv) + { + float3 sample; + sample.x = shaderTexture[0].Sample(samplerState, uv).x; + sample.y = shaderTexture[1].Sample(samplerState, uv).x; + sample.z = shaderTexture[2].Sample(samplerState, uv).x; + return float4 (saturate (sample * 16.0), 1.0); + } +}; + +class SamplerVUYA : ISampler +{ + float4 Execute (float2 uv) + { + return shaderTexture[0].Sample(samplerState, uv).zyxw; + } +}; + +class SamplerVUYAPremul : ISampler +{ + float4 Execute (float2 uv) + { + return DoAlphaUnpremul (shaderTexture[0].Sample(samplerState, uv).zyxw); + } +}; + +class SamplerY410 : ISampler +{ + float4 Execute (float2 uv) + { + return float4 (shaderTexture[0].Sample(samplerState, uv).yxz, 1.0); + } +}; + +class SamplerAYUV : ISampler +{ + float4 Execute (float2 uv) + { + return shaderTexture[0].Sample(samplerState, uv).yzwx; + } +}; + +class SamplerAYUVPremul : ISampler +{ + float4 Execute (float2 uv) + { + return DoAlphaUnpremul (shaderTexture[0].Sample(samplerState, uv).yzwx); + } +}; + +class SamplerRGBA : ISampler +{ + float4 Execute (float2 uv) + { + return shaderTexture[0].Sample(samplerState, uv); + } +}; + +class SamplerRGBAPremul : ISampler +{ + float4 Execute (float2 uv) + { + return DoAlphaUnpremul (shaderTexture[0].Sample(samplerState, uv)); + } +}; + +class SamplerRGBx : ISampler +{ + float4 Execute (float2 uv) + { + return float4 (shaderTexture[0].Sample(samplerState, uv).rgb, 1.0); + } +}; + +class SamplerGBR : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.g = shaderTexture[0].Sample(samplerState, uv).x; + sample.b = shaderTexture[1].Sample(samplerState, uv).x; + sample.r = shaderTexture[2].Sample(samplerState, uv).x; + sample.a = 1.0; + return sample; + } +}; + +class SamplerGBR_10 : ISampler +{ + float4 Execute (float2 uv) + { + float3 sample; + sample.g = shaderTexture[0].Sample(samplerState, uv).x; + sample.b = shaderTexture[1].Sample(samplerState, uv).x; + sample.r = shaderTexture[2].Sample(samplerState, uv).x; + return float4 (saturate (sample * 64.0), 1.0); + } +}; + +class SamplerGBR_12 : ISampler +{ + float4 Execute (float2 uv) + { + float3 sample; + sample.g = shaderTexture[0].Sample(samplerState, uv).x; + sample.b = shaderTexture[1].Sample(samplerState, uv).x; + sample.r = shaderTexture[2].Sample(samplerState, uv).x; + return float4 (saturate (sample * 16.0), 1.0); + } +}; + +class SamplerGBRA : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.g = shaderTexture[0].Sample(samplerState, uv).x; + sample.b = shaderTexture[1].Sample(samplerState, uv).x; + sample.r = shaderTexture[2].Sample(samplerState, uv).x; + sample.a = shaderTexture[3].Sample(samplerState, uv).x; + return sample; + } +}; + +class SamplerGBRAPremul : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.g = shaderTexture[0].Sample(samplerState, uv).x; + sample.b = shaderTexture[1].Sample(samplerState, uv).x; + sample.r = shaderTexture[2].Sample(samplerState, uv).x; + sample.a = shaderTexture[3].Sample(samplerState, uv).x; + return DoAlphaUnpremul (sample); + } +}; + +class SamplerGBRA_10 : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.g = shaderTexture[0].Sample(samplerState, uv).x; + sample.b = shaderTexture[1].Sample(samplerState, uv).x; + sample.r = shaderTexture[2].Sample(samplerState, uv).x; + sample.a = shaderTexture[3].Sample(samplerState, uv).x; + return saturate (sample * 64.0); + } +}; + +class SamplerGBRAPremul_10 : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.g = shaderTexture[0].Sample(samplerState, uv).x; + sample.b = shaderTexture[1].Sample(samplerState, uv).x; + sample.r = shaderTexture[2].Sample(samplerState, uv).x; + sample.a = shaderTexture[3].Sample(samplerState, uv).x; + return DoAlphaUnpremul (saturate (sample * 64.0)); + } +}; + +class SamplerGBRA_12 : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.g = shaderTexture[0].Sample(samplerState, uv).x; + sample.b = shaderTexture[1].Sample(samplerState, uv).x; + sample.r = shaderTexture[2].Sample(samplerState, uv).x; + sample.a = shaderTexture[3].Sample(samplerState, uv).x; + return saturate (sample * 16.0); + } +}; + +class SamplerGBRAPremul_12 : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.g = shaderTexture[0].Sample(samplerState, uv).x; + sample.b = shaderTexture[1].Sample(samplerState, uv).x; + sample.r = shaderTexture[2].Sample(samplerState, uv).x; + sample.a = shaderTexture[3].Sample(samplerState, uv).x; + return DoAlphaUnpremul (saturate (sample * 16.0)); + } +}; + +class SamplerRGBP : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.r = shaderTexture[0].Sample(samplerState, uv).x; + sample.g = shaderTexture[1].Sample(samplerState, uv).x; + sample.b = shaderTexture[2].Sample(samplerState, uv).x; + sample.a = 1.0; + return sample; + } +}; + +class SamplerBGRP : ISampler +{ + float4 Execute (float2 uv) + { + float4 sample; + sample.b = shaderTexture[0].Sample(samplerState, uv).x; + sample.g = shaderTexture[1].Sample(samplerState, uv).x; + sample.r = shaderTexture[2].Sample(samplerState, uv).x; + sample.a = 1.0; + return sample; + } +}; + +interface IConverter +{ + float4 Execute (float4 sample); +}; + +class ConverterIdentity : IConverter +{ + float4 Execute (float4 sample) + { + return sample; + } +}; + +class ConverterRange : IConverter +{ + float4 Execute (float4 sample) + { + float3 out_space; + out_space.x = postCoeff.CoeffX.x * sample.x; + out_space.y = postCoeff.CoeffY.y * sample.y; + out_space.z = postCoeff.CoeffZ.z * sample.z; + out_space += postCoeff.Offset; + return float4 (clamp (out_space, postCoeff.Min, postCoeff.Max), sample.a); + } +}; + +class ConverterSimple : IConverter +{ + float4 Execute (float4 sample) + { + float3 out_space; + out_space.x = dot (postCoeff.CoeffX, sample.xyz); + out_space.y = dot (postCoeff.CoeffY, sample.xyz); + out_space.z = dot (postCoeff.CoeffZ, sample.xyz); + out_space += postCoeff.Offset; + return float4 (clamp (out_space, postCoeff.Min, postCoeff.Max), sample.a); + } +}; + +class ConverterGamma : IConverter +{ + float4 Execute (float4 sample) + { + float3 out_space; + out_space.x = dot (preCoeff.CoeffX, sample.xyz); + out_space.y = dot (preCoeff.CoeffY, sample.xyz); + out_space.z = dot (preCoeff.CoeffZ, sample.xyz); + out_space += preCoeff.Offset; + out_space = clamp (out_space, preCoeff.Min, preCoeff.Max); + + out_space.x = gammaDecLUT.Sample (linearSampler, out_space.x); + out_space.y = gammaDecLUT.Sample (linearSampler, out_space.y); + out_space.z = gammaDecLUT.Sample (linearSampler, out_space.z); + + out_space.x = gammaEncLUT.Sample (linearSampler, out_space.x); + out_space.y = gammaEncLUT.Sample (linearSampler, out_space.y); + out_space.z = gammaEncLUT.Sample (linearSampler, out_space.z); + + out_space.x = dot (postCoeff.CoeffX, out_space); + out_space.y = dot (postCoeff.CoeffY, out_space); + out_space.z = dot (postCoeff.CoeffZ, out_space); + out_space += postCoeff.Offset; + return float4 (clamp (out_space, postCoeff.Min, postCoeff.Max), sample.a); + } +}; + +class ConverterPrimary : IConverter +{ + float4 Execute (float4 sample) + { + float3 out_space; + float3 tmp; + out_space.x = dot (preCoeff.CoeffX, sample.xyz); + out_space.y = dot (preCoeff.CoeffY, sample.xyz); + out_space.z = dot (preCoeff.CoeffZ, sample.xyz); + out_space += preCoeff.Offset; + out_space = clamp (out_space, preCoeff.Min, preCoeff.Max); + + out_space.x = gammaDecLUT.Sample (linearSampler, out_space.x); + out_space.y = gammaDecLUT.Sample (linearSampler, out_space.y); + out_space.z = gammaDecLUT.Sample (linearSampler, out_space.z); + + tmp.x = dot (primariesCoeff.CoeffX, out_space); + tmp.y = dot (primariesCoeff.CoeffY, out_space); + tmp.z = dot (primariesCoeff.CoeffZ, out_space); + + out_space.x = gammaEncLUT.Sample (linearSampler, tmp.x); + out_space.y = gammaEncLUT.Sample (linearSampler, tmp.y); + out_space.z = gammaEncLUT.Sample (linearSampler, tmp.z); + + out_space.x = dot (postCoeff.CoeffX, out_space); + out_space.y = dot (postCoeff.CoeffY, out_space); + out_space.z = dot (postCoeff.CoeffZ, out_space); + out_space += postCoeff.Offset; + return float4 (clamp (out_space, postCoeff.Min, postCoeff.Max), sample.a); + } +}; + +interface IOutputLuma +{ + PS_OUTPUT_LUMA Build (float4 sample); +}; + +class OutputLuma : IOutputLuma +{ + PS_OUTPUT_LUMA Build (float4 sample) + { + PS_OUTPUT_LUMA output; + output.Plane0 = sample.x; + return output; + } +}; + +class OutputLuma_10 : IOutputLuma +{ + PS_OUTPUT_LUMA Build (float4 sample) + { + PS_OUTPUT_LUMA output; + output.Plane0 = sample.x / 64.0; + return output; + } +}; + +class OutputLuma_12 : IOutputLuma +{ + PS_OUTPUT_LUMA Build (float4 sample) + { + PS_OUTPUT_LUMA output; + output.Plane0 = sample.x / 16.0; + return output; + } +}; + +interface IOutputChroma +{ + PS_OUTPUT_CHROMA Build (float4 sample); +}; + +class OutputChromaNV12 : IOutputChroma +{ + PS_OUTPUT_CHROMA Build (float4 sample) + { + PS_OUTPUT_CHROMA output; + output.Plane0 = sample.yz; + return output; + } +}; + +class OutputChromaNV21 : IOutputChroma +{ + PS_OUTPUT_CHROMA Build (float4 sample) + { + PS_OUTPUT_CHROMA output; + output.Plane0 = sample.zy; + return output; + } +}; + +interface IOutputChromaPlanar +{ PS_OUTPUT_CHROMA_PLANAR Build (float4 sample); +}; + +class OutputChromaI420 : IOutputChromaPlanar +{ + PS_OUTPUT_CHROMA_PLANAR Build (float4 sample) + { + PS_OUTPUT_CHROMA_PLANAR output; + output.Plane0 = sample.y; + output.Plane1 = sample.z; + return output; + } +}; + +class OutputChromaYV12 : IOutputChromaPlanar +{ + PS_OUTPUT_CHROMA_PLANAR Build (float4 sample) + { + PS_OUTPUT_CHROMA_PLANAR output; + output.Plane0 = sample.z; + output.Plane1 = sample.y; + return output; + } +}; + +class OutputChromaI420_10 : IOutputChromaPlanar +{ + PS_OUTPUT_CHROMA_PLANAR Build (float4 sample) + { + PS_OUTPUT_CHROMA_PLANAR output; + float2 scaled = sample.yz / 64.0; + output.Plane0 = scaled.x; + output.Plane1 = scaled.y; + return output; + } +}; + +class OutputChromaI420_12 : IOutputChromaPlanar +{ + PS_OUTPUT_CHROMA_PLANAR Build (float4 sample) + { + PS_OUTPUT_CHROMA_PLANAR output; + float2 scaled = sample.yz / 16.0; + output.Plane0 = scaled.x; + output.Plane1 = scaled.y; + return output; + } +}; + +interface IOutputPlanar +{ + PS_OUTPUT_PLANAR Build (float4 sample); +}; + +class OutputY444 : IOutputPlanar +{ + PS_OUTPUT_PLANAR Build (float4 sample) + { + PS_OUTPUT_PLANAR output; + output.Plane0 = sample.x; + output.Plane1 = sample.y; + output.Plane2 = sample.z; + return output; + } +}; + +class OutputY444_10 : IOutputPlanar +{ + PS_OUTPUT_PLANAR Build (float4 sample) + { + PS_OUTPUT_PLANAR output; + float3 scaled = sample.xyz / 64.0; + output.Plane0 = scaled.x; + output.Plane1 = scaled.y; + output.Plane2 = scaled.z; + return output; + } +}; + +class OutputY444_12 : IOutputPlanar +{ + PS_OUTPUT_PLANAR Build (float4 sample) + { + PS_OUTPUT_PLANAR output; + float3 scaled = sample.xyz / 16.0; + output.Plane0 = scaled.x; + output.Plane1 = scaled.y; + output.Plane2 = scaled.z; + return output; + } +}; + +class OutputGBR : IOutputPlanar +{ + PS_OUTPUT_PLANAR Build (float4 sample) + { + PS_OUTPUT_PLANAR output; + output.Plane0 = sample.g; + output.Plane1 = sample.b; + output.Plane2 = sample.r; + return output; + } +}; + +class OutputGBR_10 : IOutputPlanar +{ + PS_OUTPUT_PLANAR Build (float4 sample) + { + PS_OUTPUT_PLANAR output; + float3 scaled = sample.rgb / 64.0; + output.Plane0 = scaled.g; + output.Plane1 = scaled.b; + output.Plane2 = scaled.r; + return output; + } +}; + +class OutputGBR_12 : IOutputPlanar +{ + PS_OUTPUT_PLANAR Build (float4 sample) + { + PS_OUTPUT_PLANAR output; + float3 scaled = sample.rgb / 16.0; + output.Plane0 = scaled.g; + output.Plane1 = scaled.b; + output.Plane2 = scaled.r; + return output; + } +}; + +class OutputRGBP : IOutputPlanar +{ + PS_OUTPUT_PLANAR Build (float4 sample) + { + PS_OUTPUT_PLANAR output; + output.Plane0 = sample.r; + output.Plane1 = sample.g; + output.Plane2 = sample.b; + return output; + } +}; + +class OutputBGRP : IOutputPlanar +{ + PS_OUTPUT_PLANAR Build (float4 sample) + { + PS_OUTPUT_PLANAR output; + output.Plane0 = sample.b; + output.Plane1 = sample.g; + output.Plane2 = sample.r; + return output; + } +}; + +interface IOutputPlanarFull +{ + PS_OUTPUT_PLANAR_FULL Build (float4 sample); +}; + +class OutputGBRA : IOutputPlanarFull +{ + PS_OUTPUT_PLANAR_FULL Build (float4 sample) + { + PS_OUTPUT_PLANAR_FULL output; + output.Plane0 = sample.g; + output.Plane1 = sample.b; + output.Plane2 = sample.r; + output.Plane3 = sample.a * alphaFactor; + return output; + } +}; + +class OutputGBRAPremul : IOutputPlanarFull +{ + PS_OUTPUT_PLANAR_FULL Build (float4 sample) + { + PS_OUTPUT_PLANAR_FULL output; + float4 premul; + sample.a *= alphaFactor; + premul = DoAlphaPremul (sample); + output.Plane0 = premul.g; + output.Plane1 = premul.b; + output.Plane2 = premul.r; + output.Plane3 = premul.a; + return output; + } +}; + +class OutputGBRA_10 : IOutputPlanarFull +{ + PS_OUTPUT_PLANAR_FULL Build (float4 sample) + { + PS_OUTPUT_PLANAR_FULL output; + float4 scaled; + sample.a *= alphaFactor; + scaled = sample / 64.0; + output.Plane0 = scaled.g; + output.Plane1 = scaled.b; + output.Plane2 = scaled.r; + output.Plane3 = scaled.a; + return output; + } +}; + +class OutputGBRAPremul_10 : IOutputPlanarFull +{ + PS_OUTPUT_PLANAR_FULL Build (float4 sample) + { + PS_OUTPUT_PLANAR_FULL output; + float4 scaled; + sample.a *= alphaFactor; + scaled = DoAlphaPremul (sample) / 64.0; + output.Plane0 = scaled.g; + output.Plane1 = scaled.b; + output.Plane2 = scaled.r; + output.Plane3 = scaled.a; + return output; + } +}; + +class OutputGBRA_12 : IOutputPlanarFull +{ + PS_OUTPUT_PLANAR_FULL Build (float4 sample) + { + PS_OUTPUT_PLANAR_FULL output; + float4 scaled; + sample.a *= alphaFactor; + scaled = sample / 16.0; + output.Plane0 = scaled.g; + output.Plane1 = scaled.b; + output.Plane2 = scaled.r; + output.Plane3 = scaled.a; + return output; + } +}; + +class OutputGBRAPremul_12 : IOutputPlanarFull +{ + PS_OUTPUT_PLANAR_FULL Build (float4 sample) + { + PS_OUTPUT_PLANAR_FULL output; + float4 scaled; + sample.a *= alphaFactor; + scaled = DoAlphaPremul (sample) / 16.0; + output.Plane0 = scaled.g; + output.Plane1 = scaled.b; + output.Plane2 = scaled.r; + output.Plane3 = scaled.a; + return output; + } +}; + +interface IOutputPacked +{ + PS_OUTPUT_PACKED Build (float4 sample); +}; + +class OutputRGBA : IOutputPacked +{ + PS_OUTPUT_PACKED Build (float4 sample) + { + PS_OUTPUT_PACKED output; + output.Plane0 = float4 (sample.rgb, sample.a * alphaFactor); + return output; + } +}; + +class OutputRGBAPremul : IOutputPacked +{ + PS_OUTPUT_PACKED Build (float4 sample) + { + PS_OUTPUT_PACKED output; + sample.a *= alphaFactor; + output.Plane0 = DoAlphaPremul (sample); + return output; + } +}; + +class OutputRGBx : IOutputPacked +{ + PS_OUTPUT_PACKED Build (float4 sample) + { + PS_OUTPUT_PACKED output; + output.Plane0 = float4 (sample.rgb, 1.0); + return output; + } +}; + +class OutputVUYA : IOutputPacked +{ + PS_OUTPUT_PACKED Build (float4 sample) + { + PS_OUTPUT_PACKED output; + sample.a *= alphaFactor; + output.Plane0 = sample.zyxw; + return output; + } +}; + +class OutputVUYAPremul : IOutputPacked +{ + PS_OUTPUT_PACKED Build (float4 sample) + { + PS_OUTPUT_PACKED output; + sample.a *= alphaFactor; + output.Plane0 = DoAlphaPremul (sample).zyxw; + return output; + } +}; + +class OutputAYUV : IOutputPacked +{ + PS_OUTPUT_PACKED Build (float4 sample) + { + PS_OUTPUT_PACKED output; + sample.a *= alphaFactor; + output.Plane0 = sample.wxyz; + return output; + } +}; + +class OutputAYUVPremul : IOutputPacked +{ + PS_OUTPUT_PACKED Build (float4 sample) + { + PS_OUTPUT_PACKED output; + sample.a *= alphaFactor; + output.Plane0 = DoAlphaPremul (sample).wxyz; + return output; + } +}; + +OUTPUT_TYPE ENTRY_POINT (PS_INPUT input) +{ + SAMPLER g_sampler; + CONVERTER g_converter; + OUTPUT_BUILDER g_builder; + return g_builder.Build (g_converter.Execute (g_sampler.Execute (input.Texture))); +} +#else /* BUILDING_HLSL */ +static const char g_PSMain_converter_str[] = +"struct PSColorSpace\n" +"{\n" +" float3 CoeffX;\n" +" float3 CoeffY;\n" +" float3 CoeffZ;\n" +" float3 Offset;\n" +" float3 Min;\n" +" float3 Max;\n" +" float padding;\n" +"};\n" +"\n" +"cbuffer PsConstBuffer : register(b0)\n" +"{\n" +" PSColorSpace preCoeff;\n" +" PSColorSpace postCoeff;\n" +" PSColorSpace primariesCoeff;\n" +" float alphaFactor;\n" +"};\n" +"\n" +"Texture2D shaderTexture[4] : register(t0);\n" +"Texture1D gammaDecLUT : register(t4);\n" +"Texture1D gammaEncLUT: register(t5);\n" +"SamplerState samplerState : register(s0);\n" +"SamplerState linearSampler : register(s1);\n" +"\n" +"struct PS_INPUT\n" +"{\n" +" float4 Position: SV_POSITION;\n" +" float2 Texture: TEXCOORD;\n" +"};\n" +"\n" +"struct PS_OUTPUT_LUMA\n" +"{\n" +" float Plane0: SV_TARGET0;\n" +"};\n" +"\n" +"struct PS_OUTPUT_CHROMA\n" +"{\n" +" float2 Plane0: SV_TARGET0;\n" +"};\n" +"\n" +"struct PS_OUTPUT_CHROMA_PLANAR\n" +"{\n" +" float Plane0: SV_TARGET0;\n" +" float Plane1: SV_TARGET1;\n" +"};\n" +"\n" +"struct PS_OUTPUT_PLANAR\n" +"{\n" +" float Plane0: SV_TARGET0;\n" +" float Plane1: SV_TARGET1;\n" +" float Plane2: SV_TARGET2;\n" +"};\n" +"\n" +"struct PS_OUTPUT_PLANAR_FULL\n" +"{\n" +" float Plane0: SV_TARGET0;\n" +" float Plane1: SV_TARGET1;\n" +" float Plane2: SV_TARGET2;\n" +" float Plane3: SV_TARGET3;\n" +"};\n" +"\n" +"struct PS_OUTPUT_PACKED\n" +"{\n" +" float4 Plane0: SV_TARGET0;\n" +"};\n" +"\n" +"float4 DoAlphaPremul (float4 sample)\n" +"{\n" +" float4 premul_tex;\n" +" premul_tex.rgb = sample.rgb * sample.a;\n" +" premul_tex.a = sample.a;\n" +" return premul_tex;\n" +"}\n" +"\n" +"float4 DoAlphaUnpremul (float4 sample)\n" +"{\n" +" float4 unpremul_tex;\n" +" if (sample.a == 0 || sample.a == 1)\n" +" return sample;\n" +"\n" +" unpremul_tex.rgb = saturate (sample.rgb / sample.a);\n" +" unpremul_tex.a = sample.a;\n" +" return unpremul_tex;\n" +"}\n" +"\n" +"interface ISampler\n" +"{\n" +" float4 Execute (float2 uv);\n" +"};\n" +"\n" +"class SamplerGRAY : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.x = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.y = 0.5;\n" +" sample.z = 0.5;\n" +" sample.a = 1.0;\n" +" return sample;\n" +" }\n" +"};\n" +"\n" +"class SamplerNV12 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.x = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.yz = shaderTexture[1].Sample(samplerState, uv).xy;\n" +" sample.a = 1.0;\n" +" return sample;\n" +" }\n" +"};\n" +"\n" +"class SamplerNV21 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.x = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.yz = shaderTexture[1].Sample(samplerState, uv).yx;\n" +" sample.a = 1.0;\n" +" return sample;\n" +" }\n" +"};\n" +"\n" +"class SamplerI420 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.x = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.y = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.z = shaderTexture[2].Sample(samplerState, uv).x;\n" +" sample.a = 1.0;\n" +" return sample;\n" +" }\n" +"};\n" +"\n" +"class SamplerYV12 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.x = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.z = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.y = shaderTexture[2].Sample(samplerState, uv).x;\n" +" sample.a = 1.0;\n" +" return sample;\n" +" }\n" +"};\n" +"\n" +"class SamplerI420_10 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float3 sample;\n" +" sample.x = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.y = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.z = shaderTexture[2].Sample(samplerState, uv).x;\n" +" return float4 (saturate (sample * 64.0), 1.0);\n" +" }\n" +"};\n" +"\n" +"class SamplerI420_12 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float3 sample;\n" +" sample.x = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.y = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.z = shaderTexture[2].Sample(samplerState, uv).x;\n" +" return float4 (saturate (sample * 16.0), 1.0);\n" +" }\n" +"};\n" +"\n" +"class SamplerVUYA : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" return shaderTexture[0].Sample(samplerState, uv).zyxw;\n" +" }\n" +"};\n" +"\n" +"class SamplerVUYAPremul : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" return DoAlphaUnpremul (shaderTexture[0].Sample(samplerState, uv).zyxw);\n" +" }\n" +"};\n" +"\n" +"class SamplerY410 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" return float4 (shaderTexture[0].Sample(samplerState, uv).yxz, 1.0);\n" +" }\n" +"};\n" +"\n" +"class SamplerAYUV : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" return shaderTexture[0].Sample(samplerState, uv).yzwx;\n" +" }\n" +"};\n" +"\n" +"class SamplerAYUVPremul : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" return DoAlphaUnpremul (shaderTexture[0].Sample(samplerState, uv).yzwx);\n" +" }\n" +"};\n" +"\n" +"class SamplerRGBA : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" return shaderTexture[0].Sample(samplerState, uv);\n" +" }\n" +"};\n" +"\n" +"class SamplerRGBAPremul : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" return DoAlphaUnpremul (shaderTexture[0].Sample(samplerState, uv));\n" +" }\n" +"};\n" +"\n" +"class SamplerRGBx : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" return float4 (shaderTexture[0].Sample(samplerState, uv).rgb, 1.0);\n" +" }\n" +"};\n" +"\n" +"class SamplerGBR : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.g = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.b = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.r = shaderTexture[2].Sample(samplerState, uv).x;\n" +" sample.a = 1.0;\n" +" return sample;\n" +" }\n" +"};\n" +"\n" +"class SamplerGBR_10 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float3 sample;\n" +" sample.g = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.b = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.r = shaderTexture[2].Sample(samplerState, uv).x;\n" +" return float4 (saturate (sample * 64.0), 1.0);\n" +" }\n" +"};\n" +"\n" +"class SamplerGBR_12 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float3 sample;\n" +" sample.g = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.b = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.r = shaderTexture[2].Sample(samplerState, uv).x;\n" +" return float4 (saturate (sample * 16.0), 1.0);\n" +" }\n" +"};\n" +"\n" +"class SamplerGBRA : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.g = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.b = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.r = shaderTexture[2].Sample(samplerState, uv).x;\n" +" sample.a = shaderTexture[3].Sample(samplerState, uv).x;\n" +" return sample;\n" +" }\n" +"};\n" +"\n" +"class SamplerGBRAPremul : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.g = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.b = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.r = shaderTexture[2].Sample(samplerState, uv).x;\n" +" sample.a = shaderTexture[3].Sample(samplerState, uv).x;\n" +" return DoAlphaUnpremul (sample);\n" +" }\n" +"};\n" +"\n" +"class SamplerGBRA_10 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.g = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.b = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.r = shaderTexture[2].Sample(samplerState, uv).x;\n" +" sample.a = shaderTexture[3].Sample(samplerState, uv).x;\n" +" return saturate (sample * 64.0);\n" +" }\n" +"};\n" +"\n" +"class SamplerGBRAPremul_10 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.g = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.b = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.r = shaderTexture[2].Sample(samplerState, uv).x;\n" +" sample.a = shaderTexture[3].Sample(samplerState, uv).x;\n" +" return DoAlphaUnpremul (saturate (sample * 64.0));\n" +" }\n" +"};\n" +"\n" +"class SamplerGBRA_12 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.g = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.b = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.r = shaderTexture[2].Sample(samplerState, uv).x;\n" +" sample.a = shaderTexture[3].Sample(samplerState, uv).x;\n" +" return saturate (sample * 16.0);\n" +" }\n" +"};\n" +"\n" +"class SamplerGBRAPremul_12 : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.g = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.b = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.r = shaderTexture[2].Sample(samplerState, uv).x;\n" +" sample.a = shaderTexture[3].Sample(samplerState, uv).x;\n" +" return DoAlphaUnpremul (saturate (sample * 16.0));\n" +" }\n" +"};\n" +"\n" +"class SamplerRGBP : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.r = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.g = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.b = shaderTexture[2].Sample(samplerState, uv).x;\n" +" sample.a = 1.0;\n" +" return sample;\n" +" }\n" +"};\n" +"\n" +"class SamplerBGRP : ISampler\n" +"{\n" +" float4 Execute (float2 uv)\n" +" {\n" +" float4 sample;\n" +" sample.b = shaderTexture[0].Sample(samplerState, uv).x;\n" +" sample.g = shaderTexture[1].Sample(samplerState, uv).x;\n" +" sample.r = shaderTexture[2].Sample(samplerState, uv).x;\n" +" sample.a = 1.0;\n" +" return sample;\n" +" }\n" +"};\n" +"\n" +"interface IConverter\n" +"{\n" +" float4 Execute (float4 sample);\n" +"};\n" +"\n" +"class ConverterIdentity : IConverter\n" +"{\n" +" float4 Execute (float4 sample)\n" +" {\n" +" return sample;\n" +" }\n" +"};\n" +"\n" +"class ConverterRange : IConverter\n" +"{\n" +" float4 Execute (float4 sample)\n" +" {\n" +" float3 out_space;\n" +" out_space.x = postCoeff.CoeffX.x * sample.x;\n" +" out_space.y = postCoeff.CoeffY.y * sample.y;\n" +" out_space.z = postCoeff.CoeffZ.z * sample.z;\n" +" out_space += postCoeff.Offset;\n" +" return float4 (clamp (out_space, postCoeff.Min, postCoeff.Max), sample.a);\n" +" }\n" +"};\n" +"\n" +"class ConverterSimple : IConverter\n" +"{\n" +" float4 Execute (float4 sample)\n" +" {\n" +" float3 out_space;\n" +" out_space.x = dot (postCoeff.CoeffX, sample.xyz);\n" +" out_space.y = dot (postCoeff.CoeffY, sample.xyz);\n" +" out_space.z = dot (postCoeff.CoeffZ, sample.xyz);\n" +" out_space += postCoeff.Offset;\n" +" return float4 (clamp (out_space, postCoeff.Min, postCoeff.Max), sample.a);\n" +" }\n" +"};\n" +"\n" +"class ConverterGamma : IConverter\n" +"{\n" +" float4 Execute (float4 sample)\n" +" {\n" +" float3 out_space;\n" +" out_space.x = dot (preCoeff.CoeffX, sample.xyz);\n" +" out_space.y = dot (preCoeff.CoeffY, sample.xyz);\n" +" out_space.z = dot (preCoeff.CoeffZ, sample.xyz);\n" +" out_space += preCoeff.Offset;\n" +" out_space = clamp (out_space, preCoeff.Min, preCoeff.Max);\n" +"\n" +" out_space.x = gammaDecLUT.Sample (linearSampler, out_space.x);\n" +" out_space.y = gammaDecLUT.Sample (linearSampler, out_space.y);\n" +" out_space.z = gammaDecLUT.Sample (linearSampler, out_space.z);\n" +"\n" +" out_space.x = gammaEncLUT.Sample (linearSampler, out_space.x);\n" +" out_space.y = gammaEncLUT.Sample (linearSampler, out_space.y);\n" +" out_space.z = gammaEncLUT.Sample (linearSampler, out_space.z);\n" +"\n" +" out_space.x = dot (postCoeff.CoeffX, out_space);\n" +" out_space.y = dot (postCoeff.CoeffY, out_space);\n" +" out_space.z = dot (postCoeff.CoeffZ, out_space);\n" +" out_space += postCoeff.Offset;\n" +" return float4 (clamp (out_space, postCoeff.Min, postCoeff.Max), sample.a);\n" +" }\n" +"};\n" +"\n" +"class ConverterPrimary : IConverter\n" +"{\n" +" float4 Execute (float4 sample)\n" +" {\n" +" float3 out_space;\n" +" float3 tmp;\n" +" out_space.x = dot (preCoeff.CoeffX, sample.xyz);\n" +" out_space.y = dot (preCoeff.CoeffY, sample.xyz);\n" +" out_space.z = dot (preCoeff.CoeffZ, sample.xyz);\n" +" out_space += preCoeff.Offset;\n" +" out_space = clamp (out_space, preCoeff.Min, preCoeff.Max);\n" +"\n" +" out_space.x = gammaDecLUT.Sample (linearSampler, out_space.x);\n" +" out_space.y = gammaDecLUT.Sample (linearSampler, out_space.y);\n" +" out_space.z = gammaDecLUT.Sample (linearSampler, out_space.z);\n" +"\n" +" tmp.x = dot (primariesCoeff.CoeffX, out_space);\n" +" tmp.y = dot (primariesCoeff.CoeffY, out_space);\n" +" tmp.z = dot (primariesCoeff.CoeffZ, out_space);\n" +"\n" +" out_space.x = gammaEncLUT.Sample (linearSampler, tmp.x);\n" +" out_space.y = gammaEncLUT.Sample (linearSampler, tmp.y);\n" +" out_space.z = gammaEncLUT.Sample (linearSampler, tmp.z);\n" +"\n" +" out_space.x = dot (postCoeff.CoeffX, out_space);\n" +" out_space.y = dot (postCoeff.CoeffY, out_space);\n" +" out_space.z = dot (postCoeff.CoeffZ, out_space);\n" +" out_space += postCoeff.Offset;\n" +" return float4 (clamp (out_space, postCoeff.Min, postCoeff.Max), sample.a);\n" +" }\n" +"};\n" +"\n" +"interface IOutputLuma\n" +"{\n" +" PS_OUTPUT_LUMA Build (float4 sample);\n" +"};\n" +"\n" +"class OutputLuma : IOutputLuma\n" +"{\n" +" PS_OUTPUT_LUMA Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_LUMA output;\n" +" output.Plane0 = sample.x;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputLuma_10 : IOutputLuma\n" +"{\n" +" PS_OUTPUT_LUMA Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_LUMA output;\n" +" output.Plane0 = sample.x / 64.0;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputLuma_12 : IOutputLuma\n" +"{\n" +" PS_OUTPUT_LUMA Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_LUMA output;\n" +" output.Plane0 = sample.x / 16.0;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"interface IOutputChroma\n" +"{\n" +" PS_OUTPUT_CHROMA Build (float4 sample);\n" +"};\n" +"\n" +"class OutputChromaNV12 : IOutputChroma\n" +"{\n" +" PS_OUTPUT_CHROMA Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_CHROMA output;\n" +" output.Plane0 = sample.yz;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputChromaNV21 : IOutputChroma\n" +"{\n" +" PS_OUTPUT_CHROMA Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_CHROMA output;\n" +" output.Plane0 = sample.zy;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"interface IOutputChromaPlanar\n" +"{ PS_OUTPUT_CHROMA_PLANAR Build (float4 sample);\n" +"};\n" +"\n" +"class OutputChromaI420 : IOutputChromaPlanar\n" +"{\n" +" PS_OUTPUT_CHROMA_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_CHROMA_PLANAR output;\n" +" output.Plane0 = sample.y;\n" +" output.Plane1 = sample.z;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputChromaYV12 : IOutputChromaPlanar\n" +"{\n" +" PS_OUTPUT_CHROMA_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_CHROMA_PLANAR output;\n" +" output.Plane0 = sample.z;\n" +" output.Plane1 = sample.y;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputChromaI420_10 : IOutputChromaPlanar\n" +"{\n" +" PS_OUTPUT_CHROMA_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_CHROMA_PLANAR output;\n" +" float2 scaled = sample.yz / 64.0;\n" +" output.Plane0 = scaled.x;\n" +" output.Plane1 = scaled.y;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputChromaI420_12 : IOutputChromaPlanar\n" +"{\n" +" PS_OUTPUT_CHROMA_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_CHROMA_PLANAR output;\n" +" float2 scaled = sample.yz / 16.0;\n" +" output.Plane0 = scaled.x;\n" +" output.Plane1 = scaled.y;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"interface IOutputPlanar\n" +"{\n" +" PS_OUTPUT_PLANAR Build (float4 sample);\n" +"};\n" +"\n" +"class OutputY444 : IOutputPlanar\n" +"{\n" +" PS_OUTPUT_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR output;\n" +" output.Plane0 = sample.x;\n" +" output.Plane1 = sample.y;\n" +" output.Plane2 = sample.z;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputY444_10 : IOutputPlanar\n" +"{\n" +" PS_OUTPUT_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR output;\n" +" float3 scaled = sample.xyz / 64.0;\n" +" output.Plane0 = scaled.x;\n" +" output.Plane1 = scaled.y;\n" +" output.Plane2 = scaled.z;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputY444_12 : IOutputPlanar\n" +"{\n" +" PS_OUTPUT_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR output;\n" +" float3 scaled = sample.xyz / 16.0;\n" +" output.Plane0 = scaled.x;\n" +" output.Plane1 = scaled.y;\n" +" output.Plane2 = scaled.z;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputGBR : IOutputPlanar\n" +"{\n" +" PS_OUTPUT_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR output;\n" +" output.Plane0 = sample.g;\n" +" output.Plane1 = sample.b;\n" +" output.Plane2 = sample.r;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputGBR_10 : IOutputPlanar\n" +"{\n" +" PS_OUTPUT_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR output;\n" +" float3 scaled = sample.rgb / 64.0;\n" +" output.Plane0 = scaled.g;\n" +" output.Plane1 = scaled.b;\n" +" output.Plane2 = scaled.r;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputGBR_12 : IOutputPlanar\n" +"{\n" +" PS_OUTPUT_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR output;\n" +" float3 scaled = sample.rgb / 16.0;\n" +" output.Plane0 = scaled.g;\n" +" output.Plane1 = scaled.b;\n" +" output.Plane2 = scaled.r;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputRGBP : IOutputPlanar\n" +"{\n" +" PS_OUTPUT_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR output;\n" +" output.Plane0 = sample.r;\n" +" output.Plane1 = sample.g;\n" +" output.Plane2 = sample.b;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputBGRP : IOutputPlanar\n" +"{\n" +" PS_OUTPUT_PLANAR Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR output;\n" +" output.Plane0 = sample.b;\n" +" output.Plane1 = sample.g;\n" +" output.Plane2 = sample.r;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"interface IOutputPlanarFull\n" +"{\n" +" PS_OUTPUT_PLANAR_FULL Build (float4 sample);\n" +"};\n" +"\n" +"class OutputGBRA : IOutputPlanarFull\n" +"{\n" +" PS_OUTPUT_PLANAR_FULL Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR_FULL output;\n" +" output.Plane0 = sample.g;\n" +" output.Plane1 = sample.b;\n" +" output.Plane2 = sample.r;\n" +" output.Plane3 = sample.a * alphaFactor;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputGBRAPremul : IOutputPlanarFull\n" +"{\n" +" PS_OUTPUT_PLANAR_FULL Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR_FULL output;\n" +" float4 premul;\n" +" sample.a *= alphaFactor;\n" +" premul = DoAlphaPremul (sample);\n" +" output.Plane0 = premul.g;\n" +" output.Plane1 = premul.b;\n" +" output.Plane2 = premul.r;\n" +" output.Plane3 = premul.a;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputGBRA_10 : IOutputPlanarFull\n" +"{\n" +" PS_OUTPUT_PLANAR_FULL Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR_FULL output;\n" +" float4 scaled;\n" +" sample.a *= alphaFactor;\n" +" scaled = sample / 64.0;\n" +" output.Plane0 = scaled.g;\n" +" output.Plane1 = scaled.b;\n" +" output.Plane2 = scaled.r;\n" +" output.Plane3 = scaled.a;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputGBRAPremul_10 : IOutputPlanarFull\n" +"{\n" +" PS_OUTPUT_PLANAR_FULL Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR_FULL output;\n" +" float4 scaled;\n" +" sample.a *= alphaFactor;\n" +" scaled = DoAlphaPremul (sample) / 64.0;\n" +" output.Plane0 = scaled.g;\n" +" output.Plane1 = scaled.b;\n" +" output.Plane2 = scaled.r;\n" +" output.Plane3 = scaled.a;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputGBRA_12 : IOutputPlanarFull\n" +"{\n" +" PS_OUTPUT_PLANAR_FULL Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR_FULL output;\n" +" float4 scaled;\n" +" sample.a *= alphaFactor;\n" +" scaled = sample / 16.0;\n" +" output.Plane0 = scaled.g;\n" +" output.Plane1 = scaled.b;\n" +" output.Plane2 = scaled.r;\n" +" output.Plane3 = scaled.a;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputGBRAPremul_12 : IOutputPlanarFull\n" +"{\n" +" PS_OUTPUT_PLANAR_FULL Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PLANAR_FULL output;\n" +" float4 scaled;\n" +" sample.a *= alphaFactor;\n" +" scaled = DoAlphaPremul (sample) / 16.0;\n" +" output.Plane0 = scaled.g;\n" +" output.Plane1 = scaled.b;\n" +" output.Plane2 = scaled.r;\n" +" output.Plane3 = scaled.a;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"interface IOutputPacked\n" +"{\n" +" PS_OUTPUT_PACKED Build (float4 sample);\n" +"};\n" +"\n" +"class OutputRGBA : IOutputPacked\n" +"{\n" +" PS_OUTPUT_PACKED Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PACKED output;\n" +" output.Plane0 = float4 (sample.rgb, sample.a * alphaFactor);\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputRGBAPremul : IOutputPacked\n" +"{\n" +" PS_OUTPUT_PACKED Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PACKED output;\n" +" sample.a *= alphaFactor;\n" +" output.Plane0 = DoAlphaPremul (sample);\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputRGBx : IOutputPacked\n" +"{\n" +" PS_OUTPUT_PACKED Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PACKED output;\n" +" output.Plane0 = float4 (sample.rgb, 1.0);\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputVUYA : IOutputPacked\n" +"{\n" +" PS_OUTPUT_PACKED Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PACKED output;\n" +" sample.a *= alphaFactor;\n" +" output.Plane0 = sample.zyxw;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputVUYAPremul : IOutputPacked\n" +"{\n" +" PS_OUTPUT_PACKED Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PACKED output;\n" +" sample.a *= alphaFactor;\n" +" output.Plane0 = DoAlphaPremul (sample).zyxw;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputAYUV : IOutputPacked\n" +"{\n" +" PS_OUTPUT_PACKED Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PACKED output;\n" +" sample.a *= alphaFactor;\n" +" output.Plane0 = sample.wxyz;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"class OutputAYUVPremul : IOutputPacked\n" +"{\n" +" PS_OUTPUT_PACKED Build (float4 sample)\n" +" {\n" +" PS_OUTPUT_PACKED output;\n" +" sample.a *= alphaFactor;\n" +" output.Plane0 = DoAlphaPremul (sample).wxyz;\n" +" return output;\n" +" }\n" +"};\n" +"\n" +"OUTPUT_TYPE ENTRY_POINT (PS_INPUT input)\n" +"{\n" +" SAMPLER g_sampler;\n" +" CONVERTER g_converter;\n" +" OUTPUT_BUILDER g_builder;\n" +" return g_builder.Build (g_converter.Execute (g_sampler.Execute (input.Texture)));\n" +"}\n"; +#endif diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/VSMain_converter.hlsl b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/VSMain_converter.hlsl new file mode 100644 index 0000000000..b93920d27d --- /dev/null +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/VSMain_converter.hlsl @@ -0,0 +1,55 @@ +/* GStreamer + * Copyright (C) 2023 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef BUILDING_HLSL +struct VS_INPUT +{ + float4 Position : POSITION; + float2 Texture : TEXCOORD; +}; + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float2 Texture : TEXCOORD; +}; + +VS_OUTPUT VSMain_converter (VS_INPUT input) +{ + return input; +} +#else +static const char g_VSMain_converter_str[] = +"struct VS_INPUT\n" +"{\n" +" float4 Position : POSITION;\n" +" float2 Texture : TEXCOORD;\n" +"};\n" +"\n" +"struct VS_OUTPUT\n" +"{\n" +" float4 Position : SV_POSITION;\n" +" float2 Texture : TEXCOORD;\n" +"};\n" +"\n" +"VS_OUTPUT VSMain_converter (VS_INPUT input)\n" +"{\n" +" return input;\n" +"}\n"; +#endif diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/collect_hlsl_header.py b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/collect_hlsl_header.py new file mode 100644 index 0000000000..6249d86fa5 --- /dev/null +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/collect_hlsl_header.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# GStreamer +# Copyright (C) 2023 Seungha Yang +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +# Boston, MA 02110-1301, USA. + +import sys +import os +import argparse + +start_header = """/* + * This file is autogenerated by collect_hlsl_header.py + */ +#pragma once + +""" + +start_map = """ +#define MAKE_BYTECODE(name) { G_STRINGIFY (name), { g_##name, sizeof (g_##name)} } +static const std::map> precompiled_bytecode = { +""" + +end_map = """}; +#undef MAKE_BYTECODE +""" + +def main(args): + parser = argparse.ArgumentParser(description='Read precompiled HLSL headers from directory and make single header') + parser.add_argument("--input", help="the precompiled HLSL header directory") + parser.add_argument("--output", help="output header file location") + args = parser.parse_args(args) + + # Scan precompiled PSMain_*.h headers in build directory + # and generate single header + hlsl_headers = [os.path.basename(file) for file in os.listdir(args.input) if file.startswith("PSMain_") and file.endswith(".h") ] + + with open(args.output, 'w', newline='\n', encoding='utf8') as f: + f.write(start_header) + for file in hlsl_headers: + f.write("#include \"") + f.write(file) + f.write("\"\n") + f.write(start_map) + for file in hlsl_headers: + f.write(" MAKE_BYTECODE ({}),\n".format(os.path.splitext(file)[0])) + f.write(end_map) + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/meson.build b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/meson.build new file mode 100644 index 0000000000..4750ef3656 --- /dev/null +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/hlsl/meson.build @@ -0,0 +1,128 @@ +hlsl_ps_source = files('PSMain_converter.hlsl') + +hlsl_ps_input_formats = [ + ['NV12', false], + ['NV21', false], + ['I420', false], + ['YV12', false], + ['I420_10', false], + ['I420_12', false], + ['VUYA', false], + ['VUYAPremul', false], + ['Y410', false], + ['AYUV', false], + ['AYUVPremul', false], + ['RGBA', true], + ['RGBAPremul', true], + ['RGBx', true], + ['GBR', true], + ['GBR_10', true], + ['GBR_12', true], + ['GBRA', true], + ['GBRAPremul', true], + ['GBRA_10', true], + ['GBRAPremul_10', true], + ['GBRA_12', true], + ['GBRAPremul_12', true], + ['RGBP', true], + ['BGRP', true], +] + +hlsl_ps_output_formats = [ + ['PS_OUTPUT_LUMA', 'Luma', false], + ['PS_OUTPUT_LUMA', 'Luma_10', false], + ['PS_OUTPUT_LUMA', 'Luma_12', false], + ['PS_OUTPUT_CHROMA', 'ChromaNV12', false], + ['PS_OUTPUT_CHROMA', 'ChromaNV21', false], + ['PS_OUTPUT_CHROMA_PLANAR', 'ChromaI420', false], + ['PS_OUTPUT_CHROMA_PLANAR', 'ChromaYV12', false], + ['PS_OUTPUT_CHROMA_PLANAR', 'ChromaI420_10', false], + ['PS_OUTPUT_CHROMA_PLANAR', 'ChromaI420_12', false], + ['PS_OUTPUT_PLANAR', 'Y444', false], + ['PS_OUTPUT_PLANAR', 'Y444_10', false], + ['PS_OUTPUT_PLANAR', 'Y444_12', false], + ['PS_OUTPUT_PLANAR', 'GBR', true], + ['PS_OUTPUT_PLANAR', 'GBR_10', true], + ['PS_OUTPUT_PLANAR', 'GBR_12', true], + ['PS_OUTPUT_PLANAR', 'RGBP', true], + ['PS_OUTPUT_PLANAR', 'BGRP', true], + ['PS_OUTPUT_PLANAR_FULL', 'GBRA', true], + ['PS_OUTPUT_PLANAR_FULL', 'GBRAPremul', true], + ['PS_OUTPUT_PLANAR_FULL', 'GBRA_10', true], + ['PS_OUTPUT_PLANAR_FULL', 'GBRAPremul_10', true], + ['PS_OUTPUT_PLANAR_FULL', 'GBRA_12', true], + ['PS_OUTPUT_PLANAR_FULL', 'GBRAPremul_12', true], + ['PS_OUTPUT_PACKED', 'RGBA', true], + ['PS_OUTPUT_PACKED', 'RGBAPremul', true], + ['PS_OUTPUT_PACKED', 'RGBx', true], + ['PS_OUTPUT_PACKED', 'VUYA', false], + ['PS_OUTPUT_PACKED', 'VUYAPremul', false], + ['PS_OUTPUT_PACKED', 'AYUV', false], + ['PS_OUTPUT_PACKED', 'AYUVPremul', false], +] + +header_collector = find_program('collect_hlsl_header.py') + +foreach input_format : hlsl_ps_input_formats + in_format = input_format.get(0) + foreach output_format : hlsl_ps_output_formats + converter = '' + if input_format.get(1) != output_format.get(2) + converter = 'Simple' + else + converter = 'Identity' + endif + output_type = output_format.get(0) + output_builder = output_format.get(1) + entry_point = 'PSMain_@0@_@1@_@2@'.format(in_format, converter, output_builder) + header = '@0@.h'.format(entry_point) + compiled_shader = custom_target(header, + input : hlsl_ps_source, + output : header, + command : [fxc, '/Fh', '@OUTPUT@', + '/E', entry_point, + '/T', 'ps_5_0', + '/D', 'BUILDING_HLSL=1', + '/D', 'OUTPUT_TYPE=@0@'.format(output_type), + '/D', 'ENTRY_POINT=@0@'.format(entry_point), + '/D', 'SAMPLER=Sampler@0@'.format(in_format), + '/D', 'CONVERTER=Converter@0@'.format(converter), + '/D', 'OUTPUT_BUILDER=Output@0@'.format(output_builder), + '/nologo', + '@INPUT@']) + hlsl_precompiled += [compiled_shader] + endforeach +endforeach + +header_collection = 'PSMainConverter.h' +generated_collection = custom_target(header_collection, + input : hlsl_precompiled, + output : header_collection, + command : [header_collector, + '--input', + meson.current_build_dir(), + '--output', + '@OUTPUT@' + ]) + +hlsl_precompiled += generated_collection + +hlsl_vs_sources = [ + [files('VSMain_converter.hlsl'), 'VSMain_converter', 'vs_5_0'], +] + +foreach shader : hlsl_vs_sources + source = shader.get(0) + entry_point = shader.get(1) + header = '@0@.h'.format(entry_point) + compiled_shader = custom_target(header, + input : source, + output : header, + command : [fxc, '/Fh', '@OUTPUT@', + '/E', entry_point, + '/T', shader.get(2), + '/D', 'BUILDING_HLSL=1', + '/nologo', + '@INPUT@']) + hlsl_precompiled += [compiled_shader] +endforeach diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/meson.build b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/meson.build index eaf566a171..0ddabf8594 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/meson.build +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d11/meson.build @@ -2,6 +2,7 @@ d3d11_sources = [ 'gstd3d11bufferpool.cpp', 'gstd3d11compile.cpp', 'gstd3d11converter.cpp', + 'gstd3d11converterbuilder.cpp', 'gstd3d11device.cpp', 'gstd3d11format.cpp', 'gstd3d11memory.cpp', @@ -167,6 +168,13 @@ if cc.get_id() != 'msvc' extra_comm_args += extra_args endif +hlsl_precompiled = [] +fxc = find_program ('fxc', required : get_option ('d3d11-hlsl-precompile')) +if cc.get_id() == 'msvc' and fxc.found() + subdir('hlsl') + extra_comm_args += ['-DHLSL_PRECOMPILED'] +endif + configure_file( input : 'gstd3d11config.h.meson', output : 'gstd3d11config.h', @@ -177,7 +185,7 @@ configure_file( pkg_name = 'gstreamer-d3d11-' + api_version gstd3d11 = library('gstd3d11-' + api_version, - d3d11_sources, + d3d11_sources + hlsl_precompiled, c_args : gst_plugins_bad_args + extra_c_args + extra_comm_args, cpp_args : gst_plugins_bad_args + extra_comm_args, include_directories : [configinc, libsinc], diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11pluginutils.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11pluginutils.cpp index 9c1b43e724..23d32bee23 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11pluginutils.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11pluginutils.cpp @@ -709,7 +709,7 @@ gst_d3d11_get_pixel_shader_checker_luma (GstD3D11Device * device, return gst_d3d11_device_get_pixel_shader (device, token, g_PSMain_checker_luma, sizeof (g_PSMain_checker_luma), g_PSMain_checker_luma_str, sizeof (g_PSMain_checker_luma_str), - "PSMain_checker_luma", ps); + "PSMain_checker_luma", nullptr, ps); } HRESULT @@ -725,7 +725,7 @@ gst_d3d11_get_pixel_shader_checker_rgb (GstD3D11Device * device, return gst_d3d11_device_get_pixel_shader (device, token, g_PSMain_checker_rgb, sizeof (g_PSMain_checker_rgb), g_PSMain_checker_rgb_str, sizeof (g_PSMain_checker_rgb_str), - "PSMain_checker_rgb", ps); + "PSMain_checker_rgb", nullptr, ps); } HRESULT @@ -741,7 +741,7 @@ gst_d3d11_get_pixel_shader_checker_vuya (GstD3D11Device * device, return gst_d3d11_device_get_pixel_shader (device, token, g_PSMain_checker_vuya, sizeof (g_PSMain_checker_vuya), g_PSMain_checker_vuya_str, sizeof (g_PSMain_checker_vuya_str), - "PSMain_checker_vuya", ps); + "PSMain_checker_vuya", nullptr, ps); } HRESULT @@ -757,7 +757,7 @@ gst_d3d11_get_pixel_shader_checker (GstD3D11Device * device, return gst_d3d11_device_get_pixel_shader (device, token, g_PSMain_checker, sizeof (g_PSMain_checker), g_PSMain_checker_str, sizeof (g_PSMain_checker_str), - "PSMain_checker", ps); + "PSMain_checker", nullptr, ps); } HRESULT @@ -772,7 +772,8 @@ gst_d3d11_get_pixel_shader_color (GstD3D11Device * device, return gst_d3d11_device_get_pixel_shader (device, token, g_PSMain_color, sizeof (g_PSMain_color), - g_PSMain_color_str, sizeof (g_PSMain_color_str), "PSMain_color", ps); + g_PSMain_color_str, sizeof (g_PSMain_color_str), "PSMain_color", + nullptr, ps); } HRESULT @@ -788,7 +789,7 @@ gst_d3d11_get_pixel_shader_sample_premul (GstD3D11Device * device, return gst_d3d11_device_get_pixel_shader (device, token, g_PSMain_sample_premul, sizeof (g_PSMain_sample_premul), g_PSMain_sample_premul_str, sizeof (g_PSMain_sample_premul_str), - "PSMain_sample_premul", ps); + "PSMain_sample_premul", nullptr, ps); } HRESULT @@ -803,7 +804,8 @@ gst_d3d11_get_pixel_shader_sample (GstD3D11Device * device, return gst_d3d11_device_get_pixel_shader (device, token, g_PSMain_sample, sizeof (g_PSMain_sample), - g_PSMain_sample_str, sizeof (g_PSMain_sample_str), "PSMain_sample", ps); + g_PSMain_sample_str, sizeof (g_PSMain_sample_str), "PSMain_sample", + nullptr, ps); } HRESULT @@ -818,7 +820,8 @@ gst_d3d11_get_pixel_shader_snow (GstD3D11Device * device, return gst_d3d11_device_get_pixel_shader (device, token, g_PSMain_snow, sizeof (g_PSMain_snow), - g_PSMain_snow_str, sizeof (g_PSMain_snow_str), "PSMain_snow", ps); + g_PSMain_snow_str, sizeof (g_PSMain_snow_str), "PSMain_snow", + nullptr, ps); } HRESULT