mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-03 14:08:56 +00:00
d3d11converter: Add support for premultiplied alpha
Adding "src-alpha-mode" and "dest-alpha-mode" properties and performs premultiplied alpha conversion if needed Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4825>
This commit is contained in:
parent
04bcff4dce
commit
15735a4ef3
2 changed files with 130 additions and 1 deletions
|
@ -91,6 +91,27 @@ gst_d3d11_converter_sampler_filter_get_type (void)
|
||||||
return filter_type;
|
return filter_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GType
|
||||||
|
gst_d3d11_converter_alpha_mode_get_type (void)
|
||||||
|
{
|
||||||
|
static GType type = 0;
|
||||||
|
static const GEnumValue alpha_mode[] = {
|
||||||
|
{GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED,
|
||||||
|
"GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED", "unspecified"},
|
||||||
|
{GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED,
|
||||||
|
"GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED", "premultiplied"},
|
||||||
|
{GST_D3D11_CONVERTER_ALPHA_MODE_STRAIGHT,
|
||||||
|
"GST_D3D11_CONVERTER_ALPHA_MODE_STRAIGHT", "straight"},
|
||||||
|
{0, nullptr, nullptr},
|
||||||
|
};
|
||||||
|
|
||||||
|
GST_D3D11_CALL_ONCE_BEGIN {
|
||||||
|
type = g_enum_register_static ("GstD3D11ConverterAlphaMode", alpha_mode);
|
||||||
|
} GST_D3D11_CALL_ONCE_END;
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
using namespace Microsoft::WRL;
|
using namespace Microsoft::WRL;
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
@ -124,7 +145,9 @@ typedef struct
|
||||||
PSColorSpace to_yuv_buf;
|
PSColorSpace to_yuv_buf;
|
||||||
PSColorSpace XYZ_convert_buf;
|
PSColorSpace XYZ_convert_buf;
|
||||||
FLOAT alpha;
|
FLOAT alpha;
|
||||||
FLOAT padding[3];
|
DWORD in_premul_alpha;
|
||||||
|
DWORD out_premul_alpha;
|
||||||
|
FLOAT padding;
|
||||||
} PSConstBuffer;
|
} PSConstBuffer;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -525,6 +548,8 @@ static const gchar templ_pixel_shader[] =
|
||||||
" PSColorSpace toYUVCoeff;\n"
|
" PSColorSpace toYUVCoeff;\n"
|
||||||
" PSColorSpace primariesCoeff;\n"
|
" PSColorSpace primariesCoeff;\n"
|
||||||
" float AlphaMul;\n"
|
" float AlphaMul;\n"
|
||||||
|
" dword InPremulAlpha;\n"
|
||||||
|
" dword OutPremulAlpha;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"Texture2D shaderTexture[4] : register(t0);\n"
|
"Texture2D shaderTexture[4] : register(t0);\n"
|
||||||
"Texture1D<float> gammaDecLUT: register(t4);\n"
|
"Texture1D<float> gammaDecLUT: register(t4);\n"
|
||||||
|
@ -551,16 +576,40 @@ static const gchar templ_pixel_shader[] =
|
||||||
"%s\n"
|
"%s\n"
|
||||||
/* XYZ_convert() function */
|
/* XYZ_convert() function */
|
||||||
"%s\n"
|
"%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"
|
"PS_OUTPUT main(PS_INPUT input)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" float4 sample;\n"
|
" float4 sample;\n"
|
||||||
" sample = sample_texture (input.Texture);\n"
|
" sample = sample_texture (input.Texture);\n"
|
||||||
|
" if (InPremulAlpha)\n"
|
||||||
|
" sample = alpha_unpremul (sample);\n"
|
||||||
" sample.a = saturate (sample.a * AlphaMul);\n"
|
" sample.a = saturate (sample.a * AlphaMul);\n"
|
||||||
" sample.xyz = to_rgb (sample.xyz, toRGBCoeff);\n"
|
" sample.xyz = to_rgb (sample.xyz, toRGBCoeff);\n"
|
||||||
" sample.xyz = gamma_decode (sample.xyz);\n"
|
" sample.xyz = gamma_decode (sample.xyz);\n"
|
||||||
" sample.xyz = XYZ_convert (sample.xyz);\n"
|
" sample.xyz = XYZ_convert (sample.xyz);\n"
|
||||||
" sample.xyz = gamma_encode (sample.xyz);\n"
|
" sample.xyz = gamma_encode (sample.xyz);\n"
|
||||||
" sample.xyz = to_yuv (sample.xyz, toYUVCoeff);\n"
|
" sample.xyz = to_yuv (sample.xyz, toYUVCoeff);\n"
|
||||||
|
" if (OutPremulAlpha)\n"
|
||||||
|
" sample = alpha_premul (sample);\n"
|
||||||
" return build_output (sample);\n"
|
" return build_output (sample);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
|
@ -620,6 +669,8 @@ enum
|
||||||
PROP_DEST_MASTERING_DISPLAY_INFO,
|
PROP_DEST_MASTERING_DISPLAY_INFO,
|
||||||
PROP_DEST_CONTENT_LIGHT_LEVEL,
|
PROP_DEST_CONTENT_LIGHT_LEVEL,
|
||||||
PROP_VIDEO_DIRECTION,
|
PROP_VIDEO_DIRECTION,
|
||||||
|
PROP_SRC_ALPHA_MODE,
|
||||||
|
PROP_DEST_ALPHA_MODE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstD3D11ConverterPrivate
|
struct _GstD3D11ConverterPrivate
|
||||||
|
@ -727,6 +778,8 @@ struct _GstD3D11ConverterPrivate
|
||||||
guint blend_sample_mask;
|
guint blend_sample_mask;
|
||||||
gboolean fill_border;
|
gboolean fill_border;
|
||||||
guint64 border_color;
|
guint64 border_color;
|
||||||
|
GstD3D11ConverterAlphaMode src_alpha_mode;
|
||||||
|
GstD3D11ConverterAlphaMode dst_alpha_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void gst_d3d11_converter_set_property (GObject * object, guint prop_id,
|
static void gst_d3d11_converter_set_property (GObject * object, guint prop_id,
|
||||||
|
@ -837,6 +890,14 @@ gst_d3d11_converter_class_init (GstD3D11ConverterClass * klass)
|
||||||
g_param_spec_enum ("video-direction", "Video Direction",
|
g_param_spec_enum ("video-direction", "Video Direction",
|
||||||
"Video direction", GST_TYPE_VIDEO_ORIENTATION_METHOD,
|
"Video direction", GST_TYPE_VIDEO_ORIENTATION_METHOD,
|
||||||
GST_VIDEO_ORIENTATION_IDENTITY, param_flags));
|
GST_VIDEO_ORIENTATION_IDENTITY, param_flags));
|
||||||
|
g_object_class_install_property (object_class, PROP_SRC_ALPHA_MODE,
|
||||||
|
g_param_spec_enum ("src-alpha-mode", "Src Alpha Mode",
|
||||||
|
"Src alpha mode to use", GST_TYPE_D3D11_CONVERTER_ALPHA_MODE,
|
||||||
|
GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED, param_flags));
|
||||||
|
g_object_class_install_property (object_class, PROP_DEST_ALPHA_MODE,
|
||||||
|
g_param_spec_enum ("dest-alpha-mode", "Dest Alpha Mode",
|
||||||
|
"Dest alpha mode to use", GST_TYPE_D3D11_CONVERTER_ALPHA_MODE,
|
||||||
|
GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED, param_flags));
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_d3d11_converter_debug,
|
GST_DEBUG_CATEGORY_INIT (gst_d3d11_converter_debug,
|
||||||
"d3d11converter", 0, "d3d11converter");
|
"d3d11converter", 0, "d3d11converter");
|
||||||
|
@ -847,6 +908,8 @@ gst_d3d11_converter_init (GstD3D11Converter * self)
|
||||||
{
|
{
|
||||||
self->priv = (GstD3D11ConverterPrivate *)
|
self->priv = (GstD3D11ConverterPrivate *)
|
||||||
gst_d3d11_converter_get_instance_private (self);
|
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
|
static void
|
||||||
|
@ -1056,6 +1119,38 @@ gst_d3d11_converter_set_property (GObject * object, guint prop_id,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PROP_SRC_ALPHA_MODE:
|
||||||
|
{
|
||||||
|
DWORD prev_premul = priv->const_data.in_premul_alpha;
|
||||||
|
priv->src_alpha_mode = (GstD3D11ConverterAlphaMode)
|
||||||
|
g_value_get_enum (value);
|
||||||
|
if (priv->src_alpha_mode == GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED) {
|
||||||
|
priv->const_data.in_premul_alpha = TRUE;
|
||||||
|
} else {
|
||||||
|
priv->const_data.in_premul_alpha = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev_premul != priv->const_data.in_premul_alpha) {
|
||||||
|
priv->update_alpha = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PROP_DEST_ALPHA_MODE:
|
||||||
|
{
|
||||||
|
DWORD prev_premul = priv->const_data.out_premul_alpha;
|
||||||
|
priv->dst_alpha_mode = (GstD3D11ConverterAlphaMode)
|
||||||
|
g_value_get_enum (value);
|
||||||
|
if (priv->dst_alpha_mode == GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED) {
|
||||||
|
priv->const_data.out_premul_alpha = TRUE;
|
||||||
|
} else {
|
||||||
|
priv->const_data.out_premul_alpha = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev_premul != priv->const_data.out_premul_alpha) {
|
||||||
|
priv->update_alpha = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -1137,6 +1232,12 @@ gst_d3d11_converter_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_VIDEO_DIRECTION:
|
case PROP_VIDEO_DIRECTION:
|
||||||
g_value_set_enum (value, priv->video_direction);
|
g_value_set_enum (value, priv->video_direction);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SRC_ALPHA_MODE:
|
||||||
|
g_value_set_enum (value, priv->src_alpha_mode);
|
||||||
|
break;
|
||||||
|
case PROP_DEST_ALPHA_MODE:
|
||||||
|
g_value_set_enum (value, priv->dst_alpha_mode);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -4176,6 +4277,13 @@ gst_d3d11_converter_convert_buffer_internal (GstD3D11Converter * self,
|
||||||
if ((priv->supported_backend & GST_D3D11_CONVERTER_BACKEND_SHADER) == 0) {
|
if ((priv->supported_backend & GST_D3D11_CONVERTER_BACKEND_SHADER) == 0) {
|
||||||
/* processor only */
|
/* processor only */
|
||||||
use_processor = TRUE;
|
use_processor = TRUE;
|
||||||
|
} else if ((priv->src_alpha_mode ==
|
||||||
|
GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED ||
|
||||||
|
priv->dst_alpha_mode ==
|
||||||
|
GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED)
|
||||||
|
&& GST_VIDEO_INFO_HAS_ALPHA (&priv->in_info)) {
|
||||||
|
/* Needs alpha conversion */
|
||||||
|
use_processor = FALSE;
|
||||||
} else if (piv_available) {
|
} else if (piv_available) {
|
||||||
in_dmem = (GstD3D11Memory *) gst_buffer_peek_memory (in_buf, 0);
|
in_dmem = (GstD3D11Memory *) gst_buffer_peek_memory (in_buf, 0);
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,27 @@ GST_D3D11_API
|
||||||
GType gst_d3d11_converter_sampler_filter_get_type (void);
|
GType gst_d3d11_converter_sampler_filter_get_type (void);
|
||||||
#define GST_TYPE_D3D11_CONVERTER_SAMPLER_FILTER (gst_d3d11_converter_sampler_filter_get_type())
|
#define GST_TYPE_D3D11_CONVERTER_SAMPLER_FILTER (gst_d3d11_converter_sampler_filter_get_type())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstD3D11ConverterAlphaMode:
|
||||||
|
* @GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED: Unspecified alpha mode
|
||||||
|
* @GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED: Premultiplied alpha
|
||||||
|
* @GST_D3D11_CONVERTER_ALPHA_MODE_STRAIGHT: Straight alpha
|
||||||
|
*
|
||||||
|
* Alpha mode. Enum values are idnetical to DXGI_ALPHA_MODE
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GST_D3D11_CONVERTER_ALPHA_MODE_UNSPECIFIED = 0,
|
||||||
|
GST_D3D11_CONVERTER_ALPHA_MODE_PREMULTIPLIED = 1,
|
||||||
|
GST_D3D11_CONVERTER_ALPHA_MODE_STRAIGHT = 2,
|
||||||
|
} GstD3D11ConverterAlphaMode;
|
||||||
|
|
||||||
|
GST_D3D11_API
|
||||||
|
GType gst_d3d11_converter_alpha_mode_get_type (void);
|
||||||
|
#define GST_TYPE_D3D11_CONVERTER_ALPHA_MODE (gst_d3d11_converter_alpha_mode_get_type())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstD3D11Converter:
|
* GstD3D11Converter:
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue