amd/vpelib: Move bg color

Refactor bg gen as it check_bg_support simply calls into other version specific function.
Move that function directly into check_bg_support call, and refactor unnecessary functions + format fix.

Co-authored-by: Brendan <breleder@amd.com>
Reviewed-by: Krunoslav Kovac <Krunoslav.Kovac@amd.com>
Reviewed-by: Jesse Agate <Jesse.Agate@amd.com>
Reviewed-by: Navid Assadian <Navid.Assadian@amd.com>
Acked-by: Chenyu Chen <Chen-Yu.Chen@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32646>
This commit is contained in:
Leder, Brendan Steve
2024-11-06 11:57:20 -05:00
committed by Marge Bot
parent 3943ed8199
commit 4ef45d8d4e
8 changed files with 101 additions and 95 deletions

View File

@@ -496,11 +496,6 @@ bool vpe10_check_h_mirror_support(bool *input_mirror, bool *output_mirror)
return true;
}
enum vpe_status vpe10_check_bg_color_support(struct vpe_priv* vpe_priv, struct vpe_color* bg_color)
{
return vpe_is_valid_bg_color(vpe_priv, bg_color);
}
void vpe10_calculate_dst_viewport_and_active(
struct segment_ctx *segment_ctx, uint32_t max_seg_width)
{
@@ -917,14 +912,14 @@ int32_t vpe10_program_backend(
if (vpe_is_fp16(surface_info->format)) {
if (vpe_priv->output_ctx.alpha_mode == VPE_ALPHA_BGCOLOR)
vpe_convert_from_float_to_fp16(
(double)vpe_priv->output_ctx.bg_color.rgba.a, &alpha_16);
(double)vpe_priv->output_ctx.mpc_bg_color.rgba.a, &alpha_16);
else
vpe_convert_from_float_to_fp16(1.0, &alpha_16);
opp_dig_bypass = true;
} else {
if (vpe_priv->output_ctx.alpha_mode == VPE_ALPHA_BGCOLOR)
alpha_16 = (uint16_t)(vpe_priv->output_ctx.bg_color.rgba.a * 0xffff);
alpha_16 = (uint16_t)(vpe_priv->output_ctx.mpc_bg_color.rgba.a * 0xffff);
else
alpha_16 = 0xffff;
}
@@ -1042,7 +1037,7 @@ void vpe10_create_stream_ops_config(struct vpe_priv *vpe_priv, uint32_t pipe_idx
vpe_priv->output_ctx.output_tf, vpe_priv->output_ctx.surface.format,
false); // 3DLUT should only affect input visual confirm
} else {
blndcfg.bg_color = vpe_priv->output_ctx.bg_color;
blndcfg.bg_color = vpe_priv->output_ctx.mpc_bg_color;
}
blndcfg.global_gain = 0xff;
blndcfg.pre_multiplied_alpha = false;
@@ -1265,3 +1260,65 @@ enum vpe_status vpe10_update_blnd_gamma(struct vpe_priv *vpe_priv,
}
return status;
}
static enum vpe_status bg_color_outside_cs_gamut(
const struct vpe_priv *vpe_priv, struct vpe_color *bg_color)
{
enum color_space cs;
enum color_transfer_func tf;
struct vpe_color bg_color_copy = *bg_color;
const struct vpe_color_space *vcs = &vpe_priv->output_ctx.surface.cs;
vpe_color_get_color_space_and_tf(vcs, &cs, &tf);
if ((bg_color->is_ycbcr)) {
// using the bg_color_copy instead as bg_csc will modify it
// we should not do modification in checking stage
// otherwise validate_cached_param() will fail
if (vpe_bg_csc(&bg_color_copy, cs)) {
return VPE_STATUS_BG_COLOR_OUT_OF_RANGE;
}
}
return VPE_STATUS_OK;
}
/*
In order to support background color fill correctly, we need to do studio -> full range
conversion before the blend block. However, there is also a requirement for HDR output to be
blended in linear space. Hence, if we have PQ out and studio range, we need to make sure no
blending will occur. Otherwise the job is invalid.
*/
static enum vpe_status is_valid_blend(const struct vpe_priv *vpe_priv, struct vpe_color *bg_color)
{
enum vpe_status status = VPE_STATUS_OK;
const struct vpe_color_space *vcs = &vpe_priv->output_ctx.surface.cs;
struct stream_ctx *stream_ctx = vpe_priv->stream_ctx; // Only need to check the first stream.
if ((vcs->range == VPE_COLOR_RANGE_STUDIO) && (vcs->tf == VPE_TF_PQ) &&
((stream_ctx->stream.surface_info.cs.encoding == VPE_PIXEL_ENCODING_RGB) ||
vpe_is_global_bg_blend_applied(stream_ctx)))
status = VPE_STATUS_BG_COLOR_OUT_OF_RANGE;
return status;
}
enum vpe_status vpe10_check_bg_color_support(struct vpe_priv *vpe_priv, struct vpe_color *bg_color)
{
enum vpe_status status = VPE_STATUS_OK;
/* no need for background filling as for target rect equal to dest rect */
if (vpe_rec_is_equal(vpe_priv->output_ctx.target_rect,
vpe_priv->stream_ctx[0].stream.scaling_info.dst_rect)) {
return VPE_STATUS_OK;
}
status = is_valid_blend(vpe_priv, bg_color);
if (status == VPE_STATUS_OK)
status = bg_color_outside_cs_gamut(vpe_priv, bg_color);
return status;
}

View File

@@ -208,7 +208,7 @@ static void set_gamut_remap_matrix(double* res, enum color_space src_cs, enum co
}
static bool bg_csc(struct vpe_color *bg_color, enum color_space cs)
bool vpe_bg_csc(struct vpe_color *bg_color, enum color_space cs)
{
struct csc_table *entry = &bgcolor_to_rgbfull_table[cs];
float csc_final[3] = {0};
@@ -250,35 +250,14 @@ static bool bg_csc(struct vpe_color *bg_color, enum color_space cs)
return output_is_clipped;
}
static inline bool is_global_bg_blend_applied(struct stream_ctx *stream_ctx) {
bool vpe_is_global_bg_blend_applied(struct stream_ctx *stream_ctx)
{
return (stream_ctx->stream.blend_info.blending) &&
(stream_ctx->stream.blend_info.global_alpha) &&
(stream_ctx->stream.blend_info.global_alpha_value != 1.0);
}
/*
In order to support background color fill correctly, we need to do studio -> full range conversion
before the blend block. However, there is also a requirement for HDR output to be blended in linear space.
Hence, if we have PQ out and studio range, we need to make sure no blenidng will occur. Othewise the job
is invalid.
*/
static enum vpe_status is_valid_blend(const struct vpe_priv *vpe_priv, struct vpe_color *bg_color) {
enum vpe_status status = VPE_STATUS_OK;
const struct vpe_color_space *vcs = &vpe_priv->output_ctx.surface.cs;
struct stream_ctx *stream_ctx = vpe_priv->stream_ctx; //Only need to check the first stream.
if ((vcs->range == VPE_COLOR_RANGE_STUDIO) &&
(vcs->tf == VPE_TF_PQ) &&
((stream_ctx->stream.surface_info.cs.encoding == VPE_PIXEL_ENCODING_RGB) ||
is_global_bg_blend_applied(stream_ctx)))
status = VPE_STATUS_BG_COLOR_OUT_OF_RANGE;
return status;
}
struct gamma_coefs {
float a0;
float a1;
@@ -502,65 +481,17 @@ static void vpe_bg_inverse_gamut_remap(enum color_space output_cs,
// To understand the logic for background color conversion,
// please refer to vpe_update_output_gamma_sequence in color.c
void vpe_bg_color_convert(
enum color_space output_cs, struct transfer_func *output_tf, enum vpe_surface_pixel_format pixel_format, struct vpe_color *bg_color, bool enable_3dlut)
void vpe_bg_color_convert(enum color_space output_cs, struct transfer_func *output_tf,
enum vpe_surface_pixel_format pixel_format, struct vpe_color *mpc_bg_color,
struct vpe_color *opp_bg_color, bool enable_3dlut)
{
if (output_tf->type != TF_TYPE_BYPASS) {
// inverse degam
if (output_tf->tf == TRANSFER_FUNC_PQ2084 && !is_limited_cs(output_cs))
vpe_bg_degam(output_tf, bg_color);
vpe_bg_degam(output_tf, mpc_bg_color);
// inverse gamut remap
if (enable_3dlut)
vpe_bg_inverse_gamut_remap(output_cs, output_tf, bg_color);
vpe_bg_inverse_gamut_remap(output_cs, output_tf, mpc_bg_color);
}
// for TF_TYPE_BYPASS, bg color should be programmed to mpc as linear
}
enum vpe_status vpe_bg_color_outside_cs_gamut(
const struct vpe_priv *vpe_priv, struct vpe_color *bg_color)
{
enum color_space cs;
enum color_transfer_func tf;
struct vpe_color bg_color_copy = *bg_color;
const struct vpe_color_space *vcs = &vpe_priv->output_ctx.surface.cs;
vpe_color_get_color_space_and_tf(vcs, &cs, &tf);
if ((bg_color->is_ycbcr)) {
// using the bg_color_copy instead as bg_csc will modify it
// we should not do modification in checking stage
// otherwise validate_cached_param() will fail
if (bg_csc(&bg_color_copy, cs)) {
return VPE_STATUS_BG_COLOR_OUT_OF_RANGE;
}
}
return VPE_STATUS_OK;
}
static inline bool is_target_rect_equal_to_dest_rect(const struct vpe_priv *vpe_priv)
{
const struct vpe_rect *target_rect = &vpe_priv->output_ctx.target_rect;
const struct vpe_rect *dst_rect = &vpe_priv->stream_ctx[0].stream.scaling_info.dst_rect;
return (target_rect->height == dst_rect ->height) && (target_rect->width == dst_rect ->width) &&
(target_rect->x == dst_rect ->x) && (target_rect->y == dst_rect ->y);
}
// These two checks are only necessary for VPE1.0 and contain a lot of quirks to work around VPE 1.0
// limitations.
enum vpe_status vpe_is_valid_bg_color(const struct vpe_priv *vpe_priv, struct vpe_color *bg_color) {
enum vpe_status status = VPE_STATUS_OK;
/* no need for background filling as for target rect equal to dest rect */
if (is_target_rect_equal_to_dest_rect(vpe_priv)) {
return VPE_STATUS_OK;
}
status = is_valid_blend(vpe_priv, bg_color);
if (status == VPE_STATUS_OK)
status = vpe_bg_color_outside_cs_gamut(vpe_priv, bg_color);
return status;
}

View File

@@ -26,11 +26,13 @@
#include "color.h"
void vpe_bg_color_convert(
enum color_space cs, struct transfer_func *output_tf, enum vpe_surface_pixel_format pixel_format, struct vpe_color *bg_color, bool enable_3dlut);
void vpe_bg_color_convert(enum color_space cs, struct transfer_func *output_tf,
enum vpe_surface_pixel_format pixel_format, struct vpe_color *mpc_bg_color,
struct vpe_color *opp_bg_color, bool enable_3dlut);
enum vpe_status vpe_bg_color_outside_cs_gamut(
const struct vpe_priv *vpe_priv, struct vpe_color *bg_color);
enum vpe_status vpe_is_valid_bg_color(const struct vpe_priv *vpe_priv, struct vpe_color *bg_color);
bool vpe_bg_csc(struct vpe_color *bg_color, enum color_space cs);
bool vpe_is_global_bg_blend_applied(struct stream_ctx *stream_ctx);

View File

@@ -168,6 +168,8 @@ void vpe_frontend_config_callback(
void vpe_backend_config_callback(
void *ctx, uint64_t cfg_base_gpu, uint64_t cfg_base_cpu, uint64_t size, uint32_t pipe_idx);
bool vpe_rec_is_equal(struct vpe_rect rec1, struct vpe_rect rec2);
#ifdef __cplusplus
}
#endif

View File

@@ -166,7 +166,8 @@ struct stream_ctx {
struct output_ctx {
// stores the paramters built for generating vpep configs
struct vpe_surface_info surface;
struct vpe_color bg_color;
struct vpe_color mpc_bg_color;
struct vpe_color opp_bg_color;
struct vpe_rect target_rect;
enum vpe_alpha_mode alpha_mode;
struct vpe_clamping_params clamping_params;

View File

@@ -789,3 +789,10 @@ void vpe_backend_config_callback(
vpe_priv->vpe_desc_writer.add_config_desc(
&vpe_priv->vpe_desc_writer, cfg_base_gpu, false, (uint8_t)vpe_priv->config_writer.buf->tmz);
}
bool vpe_rec_is_equal(struct vpe_rect rec1, struct vpe_rect rec2)
{
return (rec1.x == rec2.x && rec1.y == rec2.y && rec1.width == rec2.width &&
rec1.height == rec2.height);
}

View File

@@ -158,7 +158,8 @@ struct vpe_color vpe_get_visual_confirm_color(enum vpe_surface_pixel_format form
}
// Due to there will be regamma (ogam), need convert the bg color for visual confirm
vpe_bg_color_convert(output_cs, output_tf, output_format, &visual_confirm_color, enable_3dlut);
vpe_bg_color_convert(
output_cs, output_tf, output_format, &visual_confirm_color, NULL, enable_3dlut);
// Experimental: To make FP16 Linear color looks more visually ok
if (vpe_is_fp16(output_format)) {

View File

@@ -542,7 +542,8 @@ enum vpe_status vpe_check_support(
// output resource preparation for further checking (cache the result)
output_ctx = &vpe_priv->output_ctx;
output_ctx->surface = param->dst_surface;
output_ctx->bg_color = param->bg_color;
output_ctx->mpc_bg_color = param->bg_color;
output_ctx->opp_bg_color = param->bg_color;
output_ctx->target_rect = param->target_rect;
output_ctx->alpha_mode = param->alpha_mode;
output_ctx->flags.hdr_metadata = param->flags.hdr_metadata;
@@ -576,7 +577,7 @@ enum vpe_status vpe_check_support(
// if the bg_color support is false, there is a flag to verify if the bg_color falls in the
// output gamut
if (!vpe_priv->pub.caps->bg_color_check_support) {
status = vpe_priv->resource.check_bg_color_support(vpe_priv, &output_ctx->bg_color);
status = vpe_priv->resource.check_bg_color_support(vpe_priv, &output_ctx->mpc_bg_color);
if (status != VPE_STATUS_OK) {
vpe_log(
"failed in checking the background color versus the output color space %d\n",
@@ -649,7 +650,10 @@ static bool validate_cached_param(struct vpe_priv *vpe_priv, const struct vpe_bu
if (output_ctx->alpha_mode != param->alpha_mode)
return false;
if (memcmp(&output_ctx->bg_color, &param->bg_color, sizeof(struct vpe_color)))
if (memcmp(&output_ctx->mpc_bg_color, &param->bg_color, sizeof(struct vpe_color)))
return false;
if (memcmp(&output_ctx->opp_bg_color, &param->bg_color, sizeof(struct vpe_color)))
return false;
if (memcmp(&output_ctx->target_rect, &param->target_rect, sizeof(struct vpe_rect)))
@@ -776,8 +780,9 @@ enum vpe_status vpe_build_commands(
* the 3dlut enablement for the background color conversion
* is used based on the information of the first stream.
*/
vpe_bg_color_convert(vpe_priv->output_ctx.cs, vpe_priv->output_ctx.output_tf, vpe_priv->output_ctx.surface.format,
&vpe_priv->output_ctx.bg_color, vpe_priv->stream_ctx[0].enable_3dlut);
vpe_bg_color_convert(vpe_priv->output_ctx.cs, vpe_priv->output_ctx.output_tf,
vpe_priv->output_ctx.surface.format, &vpe_priv->output_ctx.mpc_bg_color,
&vpe_priv->output_ctx.opp_bg_color, vpe_priv->stream_ctx[0].enable_3dlut);
if (vpe_priv->collaboration_mode == true) {
status = builder->build_collaborate_sync_cmd(vpe_priv, &curr_bufs);