amd/vpelib: Luma AND Color Keyer Full Support

[New]
- Added new vpe_stream params for color keying
- Added new struct in dpp to capture keying params
- Added new capability for color keying
- Added keying support in vpe1.0

[Updated]
- Updated capability check
- Updated Luma and Color Keying functions to better implement the entire feature
- Updated resource to map stream params -> dpp keyer param

Reviewed-by: Roy Chan <Roy.Chan@amd.com>
Acked-by: Chih-Wei Chien <Chih-Wei.Chien@amd.com>
Signed-off-by: Evan <evan.damphousse@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31605>
This commit is contained in:
Evan 2024-07-26 12:03:20 -04:00 committed by Marge Bot
parent 338760d9b5
commit 3ef8e6a6ae
7 changed files with 174 additions and 36 deletions

View file

@ -69,6 +69,8 @@ enum vpe_status {
VPE_STATUS_ALPHA_BLENDING_NOT_SUPPORTED, /**< Alpha blending is not supported. */
VPE_STATUS_VIEWPORT_SIZE_NOT_SUPPORTED, /**< Given viewport size is not supported. */
VPE_STATUS_LUMA_KEYING_NOT_SUPPORTED, /**< Luma keying is not supported. */
VPE_STATUS_COLOR_KEYING_NOT_SUPPORTED, /**< Color keying is not supported. */
VPE_STATUS_INVALID_KEYER_CONFIG, /**< Keying config is invalid. */
VPE_STATUS_PLANE_ADDR_NOT_SUPPORTED, /**< Given plane address is not supported. */
VPE_STATUS_ADJUSTMENT_NOT_SUPPORTED, /**< Color adjustment is not supported. */
VPE_STATUS_CMD_OVERFLOW_ERROR, /**< More than 256 commands/jobs. */
@ -161,6 +163,7 @@ struct vpe_rom_curve_caps {
struct dpp_color_caps {
uint32_t pre_csc : 1;
uint32_t luma_key : 1;
uint32_t color_key : 1;
uint32_t dgam_ram : 1;
uint32_t post_csc : 1; /**< before gamut remap */
uint32_t gamma_corr : 1;
@ -727,6 +730,33 @@ struct vpe_tonemap_params {
bool enable_3dlut; /**< Enable/Disable 3D-LUT */
};
/** @enum vpe_keyer_mode
* @brief Dictates the behavior of keyer's generated alpha
*/
enum vpe_keyer_mode {
VPE_KEYER_MODE_RANGE_00 = 0, /**< (Default) if in range -> generated alpha = 00 */
VPE_KEYER_MODE_RANGE_FF, /**< if in_range -> generated alpha = FF */
VPE_KEYER_MODE_FORCE_00, /**< ignore range setting, force generating alpha = 00 */
VPE_KEYER_MODE_FORCE_FF, /**< ignore range setting, force generating alpha = FF */
};
/** @enum vpe_color_keyer
* @brief Input Parameters for Color keyer.
* bounds should be programmed to 0.0 <= 1.0, with lower < upper
* if format does not have alpha (RGBx) when using the color keyer, alpha should be programmed to
* lower=0.0, upper=1.0
*/
struct vpe_color_keyer {
bool enable_color_key; /**< Enable Color Key. Mutually Exclusive with Luma Key */
float lower_g_bound; /**< Green Low Bound. */
float upper_g_bound; /**< Green High Bound. */
float lower_b_bound; /**< Blue Low Bound. */
float upper_b_bound; /**< Blue High Bound. */
float lower_r_bound; /**< Red Low Bound. */
float upper_r_bound; /**< Red High Bound. */
float lower_a_bound; /**< Alpha Low Bound. Program 0.0f if no alpha channel in input format.*/
float upper_a_bound; /**< Alpha High Bound. Program 1.0f if no alpha channel in input format.*/
};
/** @struct vpe_stream
* @brief Input stream/frame properties to be passed to vpelib
*/
@ -756,6 +786,10 @@ struct vpe_stream {
*/
float lower_luma_bound; /**< Lowest range of the luma */
float upper_luma_bound; /**< Highest range of the luma */
struct vpe_color_keyer color_keyer; /**< Enable Luma Keying & Set Parameters. */
enum vpe_keyer_mode keyer_mode; /**< Set Keyer Behavior.
* Used for both Luma & Color Keying.
*/
struct vpe_reserved_param reserved_param;
struct {

View file

@ -870,7 +870,11 @@ void vpe10_dpp_cnv_program_pre_dgam(struct dpp *dpp, enum color_transfer_func tr
void vpe10_dpp_program_cnv_bias_scale(struct dpp *dpp, struct bias_and_scale *bias_and_scale);
void vpe10_dpp_cnv_program_alpha_keyer(struct dpp *dpp, enum vpe_surface_pixel_format format, bool enable_luma_key, float lower_luma_bound, float upper_luma_bound);
void vpe10_dpp_build_keyer_params(
struct dpp *dpp, const struct stream_ctx *stream_ctx, struct cnv_keyer_params *keyer_params);
void vpe10_dpp_cnv_program_alpha_keyer(
struct dpp *dpp, const struct cnv_keyer_params *keyer_params);
void vpe10_dpp_program_input_transfer_func(struct dpp *dpp, struct transfer_func *input_tf);

View file

@ -41,6 +41,7 @@ static struct dpp_funcs vpe10_dpp_funcs = {
.program_cnv = vpe10_dpp_program_cnv,
.program_pre_dgam = vpe10_dpp_cnv_program_pre_dgam,
.program_cnv_bias_scale = vpe10_dpp_program_cnv_bias_scale,
.build_keyer_params = vpe10_dpp_build_keyer_params,
.program_alpha_keyer = vpe10_dpp_cnv_program_alpha_keyer,
.program_crc = vpe10_dpp_program_crc,
@ -346,37 +347,88 @@ void vpe10_dpp_cnv_program_pre_dgam(struct dpp *dpp, enum color_transfer_func tr
VPCNVC_PRE_DEGAM, 0, PRE_DEGAM_MODE, pre_degam_en, PRE_DEGAM_SELECT, degamma_lut_selection);
}
void vpe10_dpp_cnv_program_alpha_keyer(
struct dpp *dpp,
enum vpe_surface_pixel_format format,
bool enable_luma_key,
float lower_luma_bound,
float upper_luma_bound)
/** @brief Build the color Keyer Structure */
void vpe10_dpp_build_keyer_params(
struct dpp *dpp, const struct stream_ctx *stream_ctx, struct cnv_keyer_params *keyer_params)
{
uint32_t lower_luma_bound_int = (uint32_t)lower_luma_bound * 65535;
uint32_t upper_luma_bound_int = (uint32_t)upper_luma_bound * 65535;
if (stream_ctx->stream.enable_luma_key) {
keyer_params->keyer_en = 1;
keyer_params->is_color_key = 0;
keyer_params->keyer_mode = stream_ctx->stream.keyer_mode;
keyer_params->luma_keyer.lower_luma_bound =
(uint16_t)(stream_ctx->stream.lower_luma_bound * 65535);
keyer_params->luma_keyer.upper_luma_bound =
(uint16_t)(stream_ctx->stream.upper_luma_bound * 65535);
} else if (stream_ctx->stream.color_keyer.enable_color_key) {
keyer_params->keyer_en = 1;
keyer_params->is_color_key = 1;
keyer_params->keyer_mode = stream_ctx->stream.keyer_mode;
keyer_params->color_keyer.color_keyer_green_low =
(uint16_t)(stream_ctx->stream.color_keyer.lower_g_bound * 65535);
keyer_params->color_keyer.color_keyer_green_high =
(uint16_t)(stream_ctx->stream.color_keyer.upper_g_bound * 65535);
keyer_params->color_keyer.color_keyer_alpha_low =
(uint16_t)(stream_ctx->stream.color_keyer.lower_a_bound * 65535);
keyer_params->color_keyer.color_keyer_alpha_high =
(uint16_t)(stream_ctx->stream.color_keyer.upper_a_bound * 65535);
keyer_params->color_keyer.color_keyer_red_low =
(uint16_t)(stream_ctx->stream.color_keyer.lower_r_bound * 65535);
keyer_params->color_keyer.color_keyer_red_high =
(uint16_t)(stream_ctx->stream.color_keyer.upper_r_bound * 65535);
keyer_params->color_keyer.color_keyer_blue_low =
(uint16_t)(stream_ctx->stream.color_keyer.lower_b_bound * 65535);
keyer_params->color_keyer.color_keyer_blue_high =
(uint16_t)(stream_ctx->stream.color_keyer.upper_b_bound * 65535);
} else {
keyer_params->keyer_en = 0;
}
}
/** @brief Program DPP FCNV Keyer
* if keyer_params.keyer_en -> Program keyer
* else program reset default
*/
void vpe10_dpp_cnv_program_alpha_keyer(struct dpp *dpp, const struct cnv_keyer_params *keyer_params)
{
PROGRAM_ENTRY();
REG_SET_2(VPCNVC_COLOR_KEYER_CONTROL, 0,
COLOR_KEYER_EN, enable_luma_key,
COLOR_KEYER_MODE, CNV_COLOR_KEYER_MODE_RANGE_00);
if (keyer_params->keyer_en && keyer_params->is_color_key) {
uint8_t keyer_mode = 0;
REG_SET_2(VPCNVC_COLOR_KEYER_ALPHA, 0,
COLOR_KEYER_ALPHA_LOW, lower_luma_bound_int,
COLOR_KEYER_ALPHA_HIGH, upper_luma_bound_int);
switch (keyer_params->keyer_mode) {
case VPE_KEYER_MODE_FORCE_00:
keyer_mode = 0;
break;
case VPE_KEYER_MODE_FORCE_FF:
keyer_mode = 1;
break;
case VPE_KEYER_MODE_RANGE_FF:
keyer_mode = 2;
break;
case VPE_KEYER_MODE_RANGE_00:
default:
keyer_mode = 3; // Default Mode VPE_KEYER_MODE_RANGE_00
break;
}
REG_SET_2(VPCNVC_COLOR_KEYER_RED, 0,
COLOR_KEYER_RED_LOW, lower_luma_bound_int,
COLOR_KEYER_RED_HIGH, upper_luma_bound_int);
REG_SET_2(VPCNVC_COLOR_KEYER_GREEN, 0,
COLOR_KEYER_GREEN_LOW, lower_luma_bound_int,
COLOR_KEYER_GREEN_HIGH, upper_luma_bound_int);
REG_SET_2(VPCNVC_COLOR_KEYER_BLUE, 0,
COLOR_KEYER_BLUE_LOW, lower_luma_bound_int,
COLOR_KEYER_BLUE_HIGH, upper_luma_bound_int);
REG_SET_2(VPCNVC_COLOR_KEYER_CONTROL, 0, COLOR_KEYER_EN, 1, COLOR_KEYER_MODE, keyer_mode);
REG_SET_2(VPCNVC_COLOR_KEYER_GREEN, 0, COLOR_KEYER_GREEN_LOW,
keyer_params->color_keyer.color_keyer_green_low, COLOR_KEYER_GREEN_HIGH,
keyer_params->color_keyer.color_keyer_green_high);
REG_SET_2(VPCNVC_COLOR_KEYER_BLUE, 0, COLOR_KEYER_BLUE_LOW,
keyer_params->color_keyer.color_keyer_blue_low, COLOR_KEYER_BLUE_HIGH,
keyer_params->color_keyer.color_keyer_blue_high);
REG_SET_2(VPCNVC_COLOR_KEYER_RED, 0, COLOR_KEYER_RED_LOW,
keyer_params->color_keyer.color_keyer_red_low, COLOR_KEYER_RED_HIGH,
keyer_params->color_keyer.color_keyer_red_high);
REG_SET_2(VPCNVC_COLOR_KEYER_ALPHA, 0, COLOR_KEYER_ALPHA_LOW,
keyer_params->color_keyer.color_keyer_alpha_low, COLOR_KEYER_ALPHA_HIGH,
keyer_params->color_keyer.color_keyer_alpha_high);
} else {
REG_SET_DEFAULT(VPCNVC_COLOR_KEYER_CONTROL);
}
}
uint32_t vpe10_get_line_buffer_size()

View file

@ -130,6 +130,7 @@ static struct vpe_caps caps = {
{
.pre_csc = 1,
.luma_key = 0,
.color_key = 1,
.dgam_ram = 0,
.post_csc = 1,
.gamma_corr = 1,
@ -718,6 +719,7 @@ int32_t vpe10_program_frontend(struct vpe_priv *vpe_priv, uint32_t pipe_idx, uin
struct mpc *mpc = vpe_priv->resource.mpc[pipe_idx];
enum input_csc_select select = INPUT_CSC_SELECT_BYPASS;
uint32_t hw_mult = 0;
struct cnv_keyer_params keyer_params;
struct custom_float_format fmt;
vpe_priv->fe_cb_ctx.stream_idx = cmd_input->stream_idx;
@ -741,6 +743,9 @@ int32_t vpe10_program_frontend(struct vpe_priv *vpe_priv, uint32_t pipe_idx, uin
if (stream_ctx->bias_scale)
dpp->funcs->program_cnv_bias_scale(dpp, stream_ctx->bias_scale);
dpp->funcs->build_keyer_params(dpp, stream_ctx, &keyer_params);
dpp->funcs->program_alpha_keyer(dpp, &keyer_params);
/* If input adjustment exists, program the ICSC with those values. */
if (stream_ctx->input_cs) {
select = INPUT_CSC_SELECT_ICSC;

View file

@ -82,6 +82,7 @@ static struct vpe_caps caps = {
{
.pre_csc = 1,
.luma_key = 0,
.color_key = 1,
.dgam_ram = 0,
.post_csc = 1,
.gamma_corr = 1,

View file

@ -184,6 +184,12 @@ bool vpe_is_yuv444(enum vpe_surface_pixel_format format)
return (vpe_is_yuv444_8(format) || vpe_is_yuv444_10(format));
}
bool vpe_is_yuv(enum vpe_surface_pixel_format format)
{
return (vpe_is_yuv420(format) ||
vpe_is_yuv444(format));
}
static uint8_t vpe_get_element_size_in_bytes(enum vpe_surface_pixel_format format, int plane_idx)
{
switch (format) {
@ -539,12 +545,29 @@ enum vpe_status vpe_check_input_support(struct vpe *vpe, const struct vpe_stream
return VPE_STATUS_ROTATION_NOT_SUPPORTED;
}
// luma keying
if (stream->enable_luma_key && !vpe->caps->color_caps.dpp.luma_key) {
vpe_log("luma keying not supported\n");
return VPE_STATUS_LUMA_KEYING_NOT_SUPPORTED;
// keying
if (stream->enable_luma_key && stream->color_keyer.enable_color_key) {
vpe_log("Invalid Keying configuration. Both Luma and Color Keying Enabled\n");
return VPE_STATUS_INVALID_KEYER_CONFIG;
} else if (stream->enable_luma_key) {
if (!vpe->caps->color_caps.dpp.luma_key) {
vpe_log("Luma keying not supported\n");
return VPE_STATUS_LUMA_KEYING_NOT_SUPPORTED;
} else if (!vpe_is_yuv(surface_info->format)) {
vpe_log("Invalid Keying configuration. Luma Key Enabled with RGB Input\n");
return VPE_STATUS_INVALID_KEYER_CONFIG;
}
} else if (stream->color_keyer.enable_color_key) {
if (!vpe->caps->color_caps.dpp.color_key) {
vpe_log("color keying not supported\n");
return VPE_STATUS_COLOR_KEYING_NOT_SUPPORTED;
} else if (vpe_is_yuv(surface_info->format)) {
vpe_log("Invalid Keying configuration. Color Keying Enabled with YUV Input\n");
return VPE_STATUS_INVALID_KEYER_CONFIG;
}
}
// mirroring
if (stream->horizontal_mirror && !vpe->caps->h_mirror_support) {
vpe_log("output horizontal mirroring not supported h:%d\n", (int)stream->horizontal_mirror);
return VPE_STATUS_MIRROR_NOT_SUPPORTED;

View file

@ -44,11 +44,27 @@ struct cnv_alpha_2bit_lut {
int lut3;
};
enum CNV_COLOR_KEYER_MODE {
CNV_COLOR_KEYER_MODE_FORCE_00 = 0,
CNV_COLOR_KEYER_MODE_FORCE_FF = 1,
CNV_COLOR_KEYER_MODE_RANGE_FF = 2,
CNV_COLOR_KEYER_MODE_RANGE_00 = 3
struct cnv_keyer_params {
uint8_t keyer_en;
uint8_t is_color_key;
enum vpe_keyer_mode keyer_mode;
union {
struct {
uint16_t color_keyer_green_low;
uint16_t color_keyer_green_high;
uint16_t color_keyer_alpha_low;
uint16_t color_keyer_alpha_high;
uint16_t color_keyer_red_low;
uint16_t color_keyer_red_high;
uint16_t color_keyer_blue_low;
uint16_t color_keyer_blue_high;
} color_keyer;
struct {
uint16_t lower_luma_bound;
uint16_t upper_luma_bound;
} luma_keyer;
};
};
enum input_csc_select {
@ -72,7 +88,10 @@ struct dpp_funcs {
void (*program_cnv_bias_scale)(struct dpp *dpp, struct bias_and_scale *bias_and_scale);
void (*program_alpha_keyer)(struct dpp *dpp, enum vpe_surface_pixel_format format, bool enable_luma_key, float lower_luma_bound, float upper_luma_bound);
void (*build_keyer_params)(struct dpp *dpp, const struct stream_ctx *stream_ctx,
struct cnv_keyer_params *keyer_params);
void (*program_alpha_keyer)(struct dpp *dpp, const struct cnv_keyer_params *keyer_params);
void (*program_input_transfer_func)(struct dpp *dpp, struct transfer_func *input_tf);