diff --git a/src/amd/vpelib/src/chip/vpe10/inc/vpe10_resource.h b/src/amd/vpelib/src/chip/vpe10/inc/vpe10_resource.h index ab76ca144e0..7edd4f93f77 100644 --- a/src/amd/vpelib/src/chip/vpe10/inc/vpe10_resource.h +++ b/src/amd/vpelib/src/chip/vpe10/inc/vpe10_resource.h @@ -72,6 +72,10 @@ void vpe10_get_bufs_req(struct vpe_priv *vpe_priv, struct vpe_bufs_req *req); enum vpe_status vpe10_check_mirror_rotation_support(const struct vpe_stream *stream); +enum vpe_status vpe10_update_blnd_gamma(struct vpe_priv *vpe_priv, + const struct vpe_build_param *param, const struct vpe_stream *stream, + struct transfer_func *blnd_tf); + struct opp *vpe10_opp_create(struct vpe_priv *vpe_priv, int inst); struct mpc *vpe10_mpc_create(struct vpe_priv *vpe_priv, int inst); diff --git a/src/amd/vpelib/src/chip/vpe10/vpe10_resource.c b/src/amd/vpelib/src/chip/vpe10/vpe10_resource.c index f1a6190372c..41211f5179e 100644 --- a/src/amd/vpelib/src/chip/vpe10/vpe10_resource.c +++ b/src/amd/vpelib/src/chip/vpe10/vpe10_resource.c @@ -420,6 +420,7 @@ enum vpe_status vpe10_construct_resource(struct vpe_priv *vpe_priv, struct resou res->get_bufs_req = vpe10_get_bufs_req; res->check_bg_color_support = vpe10_check_bg_color_support; res->check_mirror_rotation_support = vpe10_check_mirror_rotation_support; + res->update_blnd_gamma = vpe10_update_blnd_gamma; return VPE_STATUS_OK; err: @@ -1178,3 +1179,89 @@ enum vpe_status vpe10_check_mirror_rotation_support(const struct vpe_stream *str return VPE_STATUS_OK; } + +/* This function generates software points for the blnd gam programming block. + The logic for the blndgam/ogam programming sequence is a function of: + 1. Output Range (Studio Full) + 2. 3DLUT usage + 3. Output format (HDR SDR) + + SDR Out or studio range out + TM Case + BLNDGAM : NL -> NL*S + B + OGAM : Bypass + Non TM Case + BLNDGAM : L -> NL*S + B + OGAM : Bypass + Full range HDR Out + TM Case + BLNDGAM : NL -> L + OGAM : L -> NL + Non TM Case + BLNDGAM : Bypass + OGAM : L -> NL + +*/ +enum vpe_status vpe10_update_blnd_gamma(struct vpe_priv *vpe_priv, + const struct vpe_build_param *param, const struct vpe_stream *stream, + struct transfer_func *blnd_tf) +{ + struct output_ctx *output_ctx; + struct vpe_color_space tm_out_cs; + struct fixed31_32 x_scale = vpe_fixpt_one; + struct fixed31_32 y_scale = vpe_fixpt_one; + struct fixed31_32 y_bias = vpe_fixpt_zero; + bool is_studio = false; + bool can_bypass = false; + bool lut3d_enabled = false; + enum color_space cs = COLOR_SPACE_2020_RGB_FULLRANGE; + enum color_transfer_func tf = TRANSFER_FUNC_LINEAR; + enum vpe_status status = VPE_STATUS_OK; + const struct vpe_tonemap_params *tm_params = &stream->tm_params; + + is_studio = (param->dst_surface.cs.range == VPE_COLOR_RANGE_STUDIO); + output_ctx = &vpe_priv->output_ctx; + lut3d_enabled = tm_params->UID != 0 || tm_params->enable_3dlut; + + if (stream->flags.geometric_scaling) { + vpe_color_update_degamma_tf(vpe_priv, tf, x_scale, y_scale, y_bias, true, blnd_tf); + } else { + if (is_studio) { + + if (vpe_is_rgb8(param->dst_surface.format)) { + y_scale = STUDIO_RANGE_SCALE_8_BIT; + y_bias = STUDIO_RANGE_FOOT_ROOM_8_BIT; + } else { + y_scale = STUDIO_RANGE_SCALE_10_BIT; + y_bias = STUDIO_RANGE_FOOT_ROOM_10_BIT; + } + } + // If SDR out -> Blend should be NL + // If studio out -> No choice but to blend in NL + if (!vpe_is_HDR(output_ctx->tf) || (is_studio)) { + if (lut3d_enabled) { + tf = TRANSFER_FUNC_LINEAR; + } else { + tf = output_ctx->tf; + } + + if (vpe_is_fp16(param->dst_surface.format)) { + y_scale = vpe_fixpt_mul_int(y_scale, CCCS_NORM); + } + vpe_color_update_regamma_tf( + vpe_priv, tf, x_scale, y_scale, y_bias, can_bypass, blnd_tf); + } else { + + if (lut3d_enabled) { + vpe_color_build_tm_cs(tm_params, param->dst_surface, &tm_out_cs); + vpe_color_get_color_space_and_tf(&tm_out_cs, &cs, &tf); + } else { + can_bypass = true; + } + + vpe_color_update_degamma_tf( + vpe_priv, tf, x_scale, y_scale, y_bias, can_bypass, blnd_tf); + } + } + return status; +} diff --git a/src/amd/vpelib/src/chip/vpe11/vpe11_resource.c b/src/amd/vpelib/src/chip/vpe11/vpe11_resource.c index 587b1a43e97..2bfac48f7ae 100644 --- a/src/amd/vpelib/src/chip/vpe11/vpe11_resource.c +++ b/src/amd/vpelib/src/chip/vpe11/vpe11_resource.c @@ -202,6 +202,7 @@ enum vpe_status vpe11_construct_resource(struct vpe_priv *vpe_priv, struct resou res->get_bufs_req = vpe10_get_bufs_req; res->check_bg_color_support = vpe10_check_bg_color_support; res->check_mirror_rotation_support = vpe10_check_mirror_rotation_support; + res->update_blnd_gamma = vpe10_update_blnd_gamma; return VPE_STATUS_OK; err: diff --git a/src/amd/vpelib/src/core/color.c b/src/amd/vpelib/src/core/color.c index b2d64fb996c..fc4836c0b54 100644 --- a/src/amd/vpelib/src/core/color.c +++ b/src/amd/vpelib/src/core/color.c @@ -43,15 +43,6 @@ static void color_check_input_cm_update(struct vpe_priv *vpe_priv, struct stream static void color_check_output_cm_update( struct vpe_priv *vpe_priv, const struct vpe_color_space *vcs, bool geometric_update); -static bool color_update_regamma_tf(struct vpe_priv *vpe_priv, - enum color_transfer_func output_transfer_function, struct fixed31_32 x_scale, - struct fixed31_32 y_scale, struct fixed31_32 y_bias, bool can_bypass, - struct transfer_func *output_tf); - -static bool color_update_degamma_tf(struct vpe_priv *vpe_priv, - enum color_transfer_func color_input_tf, struct fixed31_32 x_scale, struct fixed31_32 y_scale, - struct fixed31_32 y_bias, bool can_bypass, struct transfer_func *input_tf); - static bool color_update_input_cs(struct vpe_priv *vpe_priv, enum color_space in_cs, const struct vpe_color_adjust *adjustments, struct vpe_csc_matrix *input_cs, struct vpe_color_adjust *stream_clr_adjustments, struct fixed31_32 *matrix_scaling_factor); @@ -149,132 +140,6 @@ static void color_check_input_cm_update(struct vpe_priv *vpe_priv, struct stream stream_ctx->enable_3dlut = enable_3dlut; } -static bool color_update_regamma_tf(struct vpe_priv *vpe_priv, - enum color_transfer_func output_transfer_function, struct fixed31_32 x_scale, - struct fixed31_32 y_scale, struct fixed31_32 y_bias, bool can_bypass, - struct transfer_func *output_tf) -{ - struct pwl_params *params = NULL; - bool ret = true; - bool update = false; - - if (can_bypass || output_transfer_function == TRANSFER_FUNC_HLG) { - output_tf->type = TF_TYPE_BYPASS; - return true; - } - - output_tf->sdr_ref_white_level = 80; - output_tf->cm_gamma_type = CM_REGAM; - output_tf->type = TF_TYPE_DISTRIBUTED_POINTS; - output_tf->start_base = y_bias; - - switch (output_transfer_function) { - case TRANSFER_FUNC_SRGB: - case TRANSFER_FUNC_BT709: - case TRANSFER_FUNC_BT1886: - case TRANSFER_FUNC_PQ2084: - case TRANSFER_FUNC_LINEAR: - output_tf->tf = output_transfer_function; - break; - default: - VPE_ASSERT(0); - break; - } - - for (uint32_t i = 0; i < vpe_priv->pub.caps->resource_caps.num_dpp; i++) { - if (vpe_priv->init.debug.disable_lut_caching || - (output_tf->cache_info[i].cm_gamma_type != output_tf->cm_gamma_type) || - (output_tf->cache_info[i].tf != output_tf->tf) || - (output_tf->cache_info[i].x_scale.value != x_scale.value) || - (output_tf->cache_info[i].y_scale.value != y_scale.value) || - (output_tf->cache_info[i].y_bias.value != y_bias.value)) { - // if gamma points have been previously generated, - // skip the re-gen no matter it was config cached or not - update = true; - } - } - - if (update) { - ret = vpe_color_calculate_regamma_params( - vpe_priv, x_scale, y_scale, &vpe_priv->cal_buffer, output_tf); - if (ret) { - for (uint32_t i = 0; i < vpe_priv->pub.caps->resource_caps.num_dpp; i++) { - // reset the cache status and mark as dirty to let hw layer to re-cache - output_tf->dirty[i] = true; - output_tf->config_cache[i].cached = false; - output_tf->cache_info[i].cm_gamma_type = output_tf->cm_gamma_type; - output_tf->cache_info[i].tf = output_tf->tf; - output_tf->cache_info[i].x_scale = x_scale; - output_tf->cache_info[i].y_scale = y_scale; - output_tf->cache_info[i].y_bias = y_bias; - } - } - } - return ret; -} - -static bool color_update_degamma_tf(struct vpe_priv *vpe_priv, - enum color_transfer_func color_input_tf, struct fixed31_32 x_scale, struct fixed31_32 y_scale, - struct fixed31_32 y_bias, bool can_bypass, struct transfer_func *input_tf) -{ - bool ret = true; - struct pwl_params *params = NULL; - bool update = false; - - if (can_bypass || color_input_tf == TRANSFER_FUNC_HLG) { - input_tf->type = TF_TYPE_BYPASS; - return true; - } - - input_tf->cm_gamma_type = CM_DEGAM; - input_tf->type = TF_TYPE_DISTRIBUTED_POINTS; - input_tf->start_base = y_bias; - - switch (color_input_tf) { - case TRANSFER_FUNC_SRGB: - case TRANSFER_FUNC_BT709: - case TRANSFER_FUNC_BT1886: - case TRANSFER_FUNC_PQ2084: - case TRANSFER_FUNC_NORMALIZED_PQ: - case TRANSFER_FUNC_LINEAR: - input_tf->tf = color_input_tf; - break; - default: - VPE_ASSERT(0); - break; - } - - for (uint32_t i = 0; i < vpe_priv->pub.caps->resource_caps.num_dpp; i++) { - if (vpe_priv->init.debug.disable_lut_caching || - (input_tf->cache_info[i].cm_gamma_type != input_tf->cm_gamma_type) || - (input_tf->cache_info[i].tf != input_tf->tf) || - (input_tf->cache_info[i].x_scale.value != x_scale.value) || - (input_tf->cache_info[i].y_scale.value != y_scale.value) || - (input_tf->cache_info[i].y_bias.value != y_bias.value)) { - // if gamma points have been previously generated, - // skip the re-gen no matter it was config cached or not - update = true; - } - } - - if (update) { - ret = vpe_color_calculate_degamma_params(vpe_priv, x_scale, y_scale, input_tf); - if (ret) { - for (uint32_t i = 0; i < vpe_priv->pub.caps->resource_caps.num_dpp; i++) { - // reset the cache status and mark as dirty to let hw layer to re-cache - input_tf->dirty[i] = true; - input_tf->config_cache[i].cached = false; - input_tf->cache_info[i].cm_gamma_type = input_tf->cm_gamma_type; - input_tf->cache_info[i].tf = color_input_tf; - input_tf->cache_info[i].x_scale = x_scale; - input_tf->cache_info[i].y_scale = y_scale; - input_tf->cache_info[i].y_bias = y_bias; - } - } - } - return ret; -} - static enum vpe_status vpe_allocate_cm_memory( struct vpe_priv *vpe_priv, const struct vpe_build_param *param) { @@ -407,91 +272,6 @@ static bool color_update_input_cs(struct vpe_priv *vpe_priv, enum color_space in return true; } -/* This function generates software points for the blnd gam programming block. - The logic for the blndgam/ogam programming sequence is a function of: - 1. Output Range (Studio Full) - 2. 3DLUT usage - 3. Output format (HDR SDR) - - SDR Out or studio range out - TM Case - BLNDGAM : NL -> NL*S + B - OGAM : Bypass - Non TM Case - BLNDGAM : L -> NL*S + B - OGAM : Bypass - Full range HDR Out - TM Case - BLNDGAM : NL -> L - OGAM : L -> NL - Non TM Case - BLNDGAM : Bypass - OGAM : L -> NL - -*/ -static enum vpe_status vpe_update_blnd_gamma(struct vpe_priv *vpe_priv, - const struct vpe_build_param *param, const struct vpe_stream *stream, - struct transfer_func *blnd_tf) -{ - struct output_ctx *output_ctx; - struct vpe_color_space tm_out_cs; - struct fixed31_32 x_scale = vpe_fixpt_one; - struct fixed31_32 y_scale = vpe_fixpt_one; - struct fixed31_32 y_bias = vpe_fixpt_zero; - bool is_studio = false; - bool can_bypass = false; - bool lut3d_enabled = false; - enum color_space cs = COLOR_SPACE_2020_RGB_FULLRANGE; - enum color_transfer_func tf = TRANSFER_FUNC_LINEAR; - enum vpe_status status = VPE_STATUS_OK; - const struct vpe_tonemap_params *tm_params = &stream->tm_params; - - is_studio = (param->dst_surface.cs.range == VPE_COLOR_RANGE_STUDIO); - output_ctx = &vpe_priv->output_ctx; - lut3d_enabled = tm_params->UID != 0 || tm_params->enable_3dlut; - - if (stream->flags.geometric_scaling) { - color_update_degamma_tf(vpe_priv, tf, x_scale, y_scale, y_bias, true, blnd_tf); - } else { - if (is_studio) { - - if (vpe_is_rgb8(param->dst_surface.format)) { - y_scale = STUDIO_RANGE_SCALE_8_BIT; - y_bias = STUDIO_RANGE_FOOT_ROOM_8_BIT; - } else { - y_scale = STUDIO_RANGE_SCALE_10_BIT; - y_bias = STUDIO_RANGE_FOOT_ROOM_10_BIT; - } - } - - // If SDR out -> Blend should be NL - // If studio out -> No choice but to blend in NL - if (!vpe_is_HDR(output_ctx->tf) || is_studio) { - if (lut3d_enabled) { - tf = TRANSFER_FUNC_LINEAR; - } else { - tf = output_ctx->tf; - } - - if (vpe_is_fp16(param->dst_surface.format)) { - y_scale = vpe_fixpt_mul_int(y_scale, CCCS_NORM); - } - color_update_regamma_tf(vpe_priv, tf, x_scale, y_scale, y_bias, can_bypass, blnd_tf); - } else { - - if (lut3d_enabled) { - vpe_color_build_tm_cs(tm_params, param->dst_surface, &tm_out_cs); - vpe_color_get_color_space_and_tf(&tm_out_cs, &cs, &tf); - } else { - can_bypass = true; - } - - color_update_degamma_tf(vpe_priv, tf, x_scale, y_scale, y_bias, can_bypass, blnd_tf); - } - } - return status; -} - /* This function generates software points for the ogam gamma programming block. The logic for the blndgam/ogam programming sequence is a function of: 1. Output Range (Studio Full) @@ -532,7 +312,7 @@ static enum vpe_status vpe_update_output_gamma(struct vpe_priv *vpe_priv, else can_bypass = true; - color_update_regamma_tf( + vpe_color_update_regamma_tf( vpe_priv, output_ctx->tf, vpe_fixpt_one, y_scale, vpe_fixpt_zero, can_bypass, output_tf); return status; @@ -663,6 +443,132 @@ static bool build_scale_and_bias(struct bias_and_scale *bias_and_scale, return true; } +bool vpe_color_update_regamma_tf(struct vpe_priv *vpe_priv, + enum color_transfer_func output_transfer_function, struct fixed31_32 x_scale, + struct fixed31_32 y_scale, struct fixed31_32 y_bias, bool can_bypass, + struct transfer_func *output_tf) +{ + struct pwl_params* params = NULL; + bool ret = true; + bool update = false; + + if (can_bypass || output_transfer_function == TRANSFER_FUNC_HLG) { + output_tf->type = TF_TYPE_BYPASS; + return true; + } + + output_tf->sdr_ref_white_level = 80; + output_tf->cm_gamma_type = CM_REGAM; + output_tf->type = TF_TYPE_DISTRIBUTED_POINTS; + output_tf->start_base = y_bias; + + switch (output_transfer_function) { + case TRANSFER_FUNC_SRGB: + case TRANSFER_FUNC_BT709: + case TRANSFER_FUNC_BT1886: + case TRANSFER_FUNC_PQ2084: + case TRANSFER_FUNC_LINEAR: + output_tf->tf = output_transfer_function; + break; + default: + VPE_ASSERT(0); + break; + } + + for (uint32_t i = 0; i < vpe_priv->pub.caps->resource_caps.num_dpp; i++) { + if (vpe_priv->init.debug.disable_lut_caching || + (output_tf->cache_info[i].cm_gamma_type != output_tf->cm_gamma_type) || + (output_tf->cache_info[i].tf != output_tf->tf) || + (output_tf->cache_info[i].x_scale.value != x_scale.value) || + (output_tf->cache_info[i].y_scale.value != y_scale.value) || + (output_tf->cache_info[i].y_bias.value != y_bias.value)) { + // if gamma points have been previously generated, + // skip the re-gen no matter it was config cached or not + update = true; + } + } + + if (update) { + ret = vpe_color_calculate_regamma_params( + vpe_priv, x_scale, y_scale, &vpe_priv->cal_buffer, output_tf); + if (ret) { + for (uint32_t i = 0; i < vpe_priv->pub.caps->resource_caps.num_dpp; i++) { + // reset the cache status and mark as dirty to let hw layer to re-cache + output_tf->dirty[i] = true; + output_tf->config_cache[i].cached = false; + output_tf->cache_info[i].cm_gamma_type = output_tf->cm_gamma_type; + output_tf->cache_info[i].tf = output_tf->tf; + output_tf->cache_info[i].x_scale = x_scale; + output_tf->cache_info[i].y_scale = y_scale; + output_tf->cache_info[i].y_bias = y_bias; + } + } + } + return ret; +} + +bool vpe_color_update_degamma_tf(struct vpe_priv *vpe_priv, enum color_transfer_func color_input_tf, + struct fixed31_32 x_scale, struct fixed31_32 y_scale, struct fixed31_32 y_bias, bool can_bypass, + struct transfer_func *input_tf) +{ + bool ret = true; + struct pwl_params* params = NULL; + bool update = false; + + if (can_bypass || color_input_tf == TRANSFER_FUNC_HLG) { + input_tf->type = TF_TYPE_BYPASS; + return true; + } + + input_tf->cm_gamma_type = CM_DEGAM; + input_tf->type = TF_TYPE_DISTRIBUTED_POINTS; + input_tf->start_base = y_bias; + + switch (color_input_tf) { + case TRANSFER_FUNC_SRGB: + case TRANSFER_FUNC_BT709: + case TRANSFER_FUNC_BT1886: + case TRANSFER_FUNC_PQ2084: + case TRANSFER_FUNC_NORMALIZED_PQ: + case TRANSFER_FUNC_LINEAR: + input_tf->tf = color_input_tf; + break; + default: + VPE_ASSERT(0); + break; + } + + for (uint32_t i = 0; i < vpe_priv->pub.caps->resource_caps.num_dpp; i++) { + if (vpe_priv->init.debug.disable_lut_caching || + (input_tf->cache_info[i].cm_gamma_type != input_tf->cm_gamma_type) || + (input_tf->cache_info[i].tf != input_tf->tf) || + (input_tf->cache_info[i].x_scale.value != x_scale.value) || + (input_tf->cache_info[i].y_scale.value != y_scale.value) || + (input_tf->cache_info[i].y_bias.value != y_bias.value)) { + // if gamma points have been previously generated, + // skip the re-gen no matter it was config cached or not + update = true; + } + } + + if (update) { + ret = vpe_color_calculate_degamma_params(vpe_priv, x_scale, y_scale, input_tf); + if (ret) { + for (uint32_t i = 0; i < vpe_priv->pub.caps->resource_caps.num_dpp; i++) { + // reset the cache status and mark as dirty to let hw layer to re-cache + input_tf->dirty[i] = true; + input_tf->config_cache[i].cached = false; + input_tf->cache_info[i].cm_gamma_type = input_tf->cm_gamma_type; + input_tf->cache_info[i].tf = color_input_tf; + input_tf->cache_info[i].x_scale = x_scale; + input_tf->cache_info[i].y_scale = y_scale; + input_tf->cache_info[i].y_bias = y_bias; + } + } + } + return ret; +} + enum vpe_status vpe_color_build_tm_cs(const struct vpe_tonemap_params *tm_params, struct vpe_surface_info surface_info, struct vpe_color_space *tm_out_cs) { @@ -769,7 +675,7 @@ enum vpe_status vpe_color_update_color_space_and_tf( y_scale = vpe_fixpt_div_int(y_scale, CCCS_NORM); } - color_update_degamma_tf(vpe_priv, stream_ctx->tf, + vpe_color_update_degamma_tf(vpe_priv, stream_ctx->tf, vpe_priv->stream_ctx->tf_scaling_factor, y_scale, vpe_fixpt_zero, is_3dlut_enable || geometric_scaling, // By Pass degamma if 3DLUT is enabled stream_ctx->input_tf); @@ -782,7 +688,7 @@ enum vpe_status vpe_color_update_color_space_and_tf( if (output_ctx->dirty_bits.transfer_function || output_ctx->dirty_bits.color_space || require_update) { - vpe_update_blnd_gamma(vpe_priv, param, &stream_ctx->stream, stream_ctx->blend_tf); + vpe_priv->resource.update_blnd_gamma(vpe_priv, param, &stream_ctx->stream, stream_ctx->blend_tf); } } @@ -1129,3 +1035,44 @@ enum vpe_status vpe_color_update_whitepoint( } return VPE_STATUS_OK; } + +enum color_range_type vpe_get_range_type( + enum color_space color_space, enum vpe_surface_pixel_format format) +{ + bool is_limited = false; + + switch (color_space) { + case COLOR_SPACE_SRGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_RGB601: + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR_JFIF: + case COLOR_SPACE_RGB_JFIF: + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_YCBCR: + is_limited = false; + break; + case COLOR_SPACE_SRGB_LIMITED: + case COLOR_SPACE_RGB601_LIMITED: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_YCBCR_LIMITED: + is_limited = true; + break; + default: + VPE_ASSERT(false); + break; + } + + if (!is_limited) + return COLOR_RANGE_FULL; + + if (vpe_is_8bit(format)) + return COLOR_RANGE_LIMITED_8BPC; + else if (vpe_is_10bit(format)) + return COLOR_RANGE_LIMITED_10BPC; + else + return COLOR_RANGE_LIMITED_16BPC; +} diff --git a/src/amd/vpelib/src/core/color_bg.c b/src/amd/vpelib/src/core/color_bg.c index b9645cc4904..bc97a1a44d3 100644 --- a/src/amd/vpelib/src/core/color_bg.c +++ b/src/amd/vpelib/src/core/color_bg.c @@ -55,7 +55,6 @@ const double bt_2020_xyz_rgb_matrix[] = { 0.053616587979668, -0.130001864005497, 2.863535322904176 }; - static struct csc_table bgcolor_to_rgbfull_table[COLOR_SPACE_MAX] = { [COLOR_SPACE_YCBCR601] = { @@ -501,59 +500,11 @@ static void vpe_bg_inverse_gamut_remap(enum color_space output_cs, } -static void inverse_output_csc(enum color_space output_cs, struct vpe_color* bg_color) -{ - enum color_space bgcolor_cs = COLOR_SPACE_YCBCR709; - - switch (output_cs) { - // output is ycbr cs, follow output's setting - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR601_LIMITED: - case COLOR_SPACE_YCBCR709_LIMITED: - case COLOR_SPACE_2020_YCBCR: - case COLOR_SPACE_2020_YCBCR_LIMITED: - bgcolor_cs = output_cs; - break; - // output is RGB cs, follow output's range - // but need yuv to rgb csc - case COLOR_SPACE_SRGB_LIMITED: - case COLOR_SPACE_RGB601_LIMITED: - bgcolor_cs = COLOR_SPACE_YCBCR709_LIMITED; - break; - case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - bgcolor_cs = COLOR_SPACE_2020_YCBCR_LIMITED; - break; - case COLOR_SPACE_SRGB: - case COLOR_SPACE_MSREF_SCRGB: - case COLOR_SPACE_RGB601: - bgcolor_cs = COLOR_SPACE_YCBCR709; - break; - case COLOR_SPACE_2020_RGB_FULLRANGE: - bgcolor_cs = COLOR_SPACE_2020_YCBCR; - break; - default: - // should revise the newly added CS - // and set corresponding bgcolor_cs accordingly - VPE_ASSERT(0); - bgcolor_cs = COLOR_SPACE_YCBCR709; - break; - } - - // input is [0-0xffff] - // convert bg color to RGB full range for use inside pipe - bg_csc(bg_color, bgcolor_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, struct vpe_color *bg_color, bool enable_3dlut) + 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) { - // inverse OCSC - if (bg_color->is_ycbcr) - inverse_output_csc(output_cs, bg_color); - if (output_tf->type != TF_TYPE_BYPASS) { // inverse degam if (output_tf->tf == TRANSFER_FUNC_PQ2084 && !is_limited_cs(output_cs)) diff --git a/src/amd/vpelib/src/core/common.c b/src/amd/vpelib/src/core/common.c index f1b8b07c93f..763d7893713 100644 --- a/src/amd/vpelib/src/core/common.c +++ b/src/amd/vpelib/src/core/common.c @@ -74,6 +74,18 @@ bool vpe_is_32bit_packed_rgb(enum vpe_surface_pixel_format format) } } +bool vpe_is_8bit(enum vpe_surface_pixel_format format) { + return vpe_is_rgb8(format) || + vpe_is_yuv420_8(format) || + vpe_is_yuv444_8(format); +} + +bool vpe_is_10bit(enum vpe_surface_pixel_format format) { + return vpe_is_rgb10(format) || + vpe_is_yuv420_10(format) || + vpe_is_yuv444_10(format); +} + bool vpe_is_rgb8(enum vpe_surface_pixel_format format) { switch (format) { diff --git a/src/amd/vpelib/src/core/inc/color.h b/src/amd/vpelib/src/core/inc/color.h index 035bcd60634..5550350505f 100644 --- a/src/amd/vpelib/src/core/inc/color.h +++ b/src/amd/vpelib/src/core/inc/color.h @@ -58,6 +58,13 @@ enum color_depth { COLOR_DEPTH_COUNT }; +enum color_range_type { + COLOR_RANGE_FULL, + COLOR_RANGE_LIMITED_8BPC, + COLOR_RANGE_LIMITED_10BPC, + COLOR_RANGE_LIMITED_16BPC +}; + enum color_transfer_func { TRANSFER_FUNC_UNKNOWN, TRANSFER_FUNC_SRGB, @@ -280,6 +287,18 @@ enum vpe_status vpe_color_build_tm_cs(const struct vpe_tonemap_params *tm_params enum vpe_status vpe_color_update_3dlut( struct vpe_priv *vpe_priv, struct stream_ctx *stream_ctx, bool enable_3dlut); +bool vpe_color_update_regamma_tf(struct vpe_priv *vpe_priv, + enum color_transfer_func output_transfer_function, struct fixed31_32 x_scale, + struct fixed31_32 y_scale, struct fixed31_32 y_bias, bool can_bypass, + struct transfer_func *output_tf); + +bool vpe_color_update_degamma_tf(struct vpe_priv *vpe_priv, enum color_transfer_func color_input_tf, + struct fixed31_32 x_scale, struct fixed31_32 y_scale, struct fixed31_32 y_bias, bool can_bypass, + struct transfer_func *input_tf); + +enum color_range_type vpe_get_range_type( + enum color_space color_space, enum vpe_surface_pixel_format format); + #ifdef __cplusplus } #endif diff --git a/src/amd/vpelib/src/core/inc/color_bg.h b/src/amd/vpelib/src/core/inc/color_bg.h index bc7ee8834d9..7a045f471a1 100644 --- a/src/amd/vpelib/src/core/inc/color_bg.h +++ b/src/amd/vpelib/src/core/inc/color_bg.h @@ -27,7 +27,7 @@ #include "color.h" void vpe_bg_color_convert( - enum color_space cs, struct transfer_func *output_tf, struct vpe_color *bg_color, bool enable_3dlut); + enum color_space cs, struct transfer_func *output_tf, enum vpe_surface_pixel_format pixel_format, struct vpe_color *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); diff --git a/src/amd/vpelib/src/core/inc/common.h b/src/amd/vpelib/src/core/inc/common.h index 3162c38ce51..5bfecf54b18 100644 --- a/src/amd/vpelib/src/core/inc/common.h +++ b/src/amd/vpelib/src/core/inc/common.h @@ -77,6 +77,10 @@ bool vpe_is_yuv444(enum vpe_surface_pixel_format format); bool vpe_is_yuv(enum vpe_surface_pixel_format format); +bool vpe_is_8bit(enum vpe_surface_pixel_format format); + +bool vpe_is_10bit(enum vpe_surface_pixel_format format); + enum color_depth vpe_get_color_depth(enum vpe_surface_pixel_format format); bool vpe_has_per_pixel_alpha(enum vpe_surface_pixel_format format); diff --git a/src/amd/vpelib/src/core/inc/resource.h b/src/amd/vpelib/src/core/inc/resource.h index 491a2f3aea5..ec9d7e8cf56 100644 --- a/src/amd/vpelib/src/core/inc/resource.h +++ b/src/amd/vpelib/src/core/inc/resource.h @@ -102,6 +102,10 @@ struct resource { enum vpe_status (*check_mirror_rotation_support)(const struct vpe_stream *stream); + enum vpe_status (*update_blnd_gamma)(struct vpe_priv *vpe_priv, + const struct vpe_build_param *param, const struct vpe_stream *stream, + struct transfer_func *blnd_tf); + // Indicates the nominal range hdr input content should be in during processing. int internal_hdr_normalization; diff --git a/src/amd/vpelib/src/core/mpc.c b/src/amd/vpelib/src/core/mpc.c index 9e8f1e9f877..fcf1c5f4952 100644 --- a/src/amd/vpelib/src/core/mpc.c +++ b/src/amd/vpelib/src/core/mpc.c @@ -27,133 +27,96 @@ #include "common.h" #include "mpc.h" -enum mpc_color_space_type { - COLOR_SPACE_RGB_TYPE, - COLOR_SPACE_RGB_LIMITED_8PBC_TYPE, - COLOR_SPACE_RGB_LIMITED_10PBC_TYPE, - COLOR_SPACE_YCBCR601_TYPE, - COLOR_SPACE_YCBCR709_TYPE, - COLOR_SPACE_YCBCR2020_TYPE, - COLOR_SPACE_YCBCR601_LIMITED_TYPE, - COLOR_SPACE_YCBCR709_LIMITED_TYPE, - // COLOR_SPACE_YCBCR709_BLACK_TYPE, +enum mpc_color_gamut_type { + COLOR_GAMUT_RGB_TYPE, + COLOR_GAMUT_YCBCR601_TYPE, + COLOR_GAMUT_YCBCR709_TYPE, + COLOR_GAMUT_YCBCR2020_TYPE }; -struct out_csc_color_matrix_type { - enum mpc_color_space_type color_space_type; + +struct out_csc_2d_color_matrix_type { + enum mpc_color_gamut_type color_gamut_type; + enum color_range_type color_range_type; uint16_t regval[12]; }; -static const struct out_csc_color_matrix_type output_csc_matrix[] = { - {COLOR_SPACE_RGB_TYPE, {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0}}, - {COLOR_SPACE_RGB_LIMITED_8PBC_TYPE, - {0x1B7B, 0, 0, 0x202, 0, 0x1B7B, 0, 0x202, 0, 0, 0x1B7B, 0x202}}, - {COLOR_SPACE_RGB_LIMITED_10PBC_TYPE, - {0x1B66, 0, 0, 0x200, 0, 0x1B66, 0, 0x200, 0, 0, 0x1B66, 0x200}}, - {COLOR_SPACE_YCBCR601_TYPE, {0xE04, 0xF444, 0xFDB9, 0x1004, 0x831, 0x1016, 0x320, 0x201, 0xFB45, - 0xF6B7, 0xE04, 0x1004}}, - {COLOR_SPACE_YCBCR709_TYPE, {0xE04, 0xF345, 0xFEB7, 0x1004, 0x5D3, 0x1399, 0x1FA, 0x201, 0xFCCA, - 0xF533, 0xE04, 0x1004}}, - {COLOR_SPACE_YCBCR601_LIMITED_TYPE, {0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, 0x12C9, 0x3A6, 0x200, - 0xFB47, 0xF6B9, 0xE00, 0x1000}}, - {COLOR_SPACE_YCBCR709_LIMITED_TYPE, {0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, 0x24F, 0x200, - 0xFCCB, 0xF535, 0xE00, 0x1000}}, - {COLOR_SPACE_YCBCR2020_TYPE, {0x1000, 0xF149, 0xFEB7, 0x0000, 0x0868, 0x15B2, 0x01E6, 0x0000, - 0xFB88, 0xF478, 0x1000, 0x0000}}, -}; +static const struct out_csc_2d_color_matrix_type output_csc_2d_matrix[] = { + {COLOR_GAMUT_RGB_TYPE, COLOR_RANGE_FULL, {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0}}, + {COLOR_GAMUT_RGB_TYPE, COLOR_RANGE_LIMITED_8BPC, + {0x1b7b, 0, 0, 0x202, 0, 0x1b7b, 0, 0x202, 0, 0, 0x1b7b, 0x202}}, + {COLOR_GAMUT_RGB_TYPE, COLOR_RANGE_LIMITED_10BPC, + {0x1b67, 0, 0, 0x201, 0, 0x1b67, 0, 0x201, 0, 0, 0x1b67, 0x201}}, + {COLOR_GAMUT_RGB_TYPE, COLOR_RANGE_LIMITED_16BPC, + {0x1b60, 0, 0, 0x200, 0, 0x1b60, 0, 0x200, 0, 0, 0x1b60, 0x200}}, -static bool is_rgb_full_type(enum color_space color_space) + {COLOR_GAMUT_YCBCR601_TYPE, COLOR_RANGE_FULL, + {0x1000, 0xf29a, 0xfd66, 0x1000, 0x0991, 0x12c9, 0x03a6, 0x0000, 0xfa9a, 0xf566, 0x1000, + 0x1000}}, + {COLOR_GAMUT_YCBCR601_TYPE, COLOR_RANGE_LIMITED_8BPC, + {0x0e0e, 0xf43b, 0xfdb7, 0x1010, 0x0838, 0x1022, 0x0322, 0x0202, 0xfb42, 0xf6b0, 0x0e0e, + 0x1010}}, + {COLOR_GAMUT_YCBCR601_TYPE, COLOR_RANGE_LIMITED_10BPC, + {0x0e03, 0xf444, 0xfdb9, 0x1004, 0x0831, 0x1016, 0x0320, 0x0201, 0xfb45, 0xf6b8, 0x0e03, + 0x1004}}, + {COLOR_GAMUT_YCBCR601_TYPE, COLOR_RANGE_LIMITED_16BPC, + {0x0db0, 0xf48a, 0xfdc6, 0x0fb0, 0x0830, 0x1012, 0x031f, 0x0200, 0xfb61, 0xf6ee, 0x0db0, + 0x0fb0}}, + + {COLOR_GAMUT_YCBCR709_TYPE, COLOR_RANGE_FULL, + {0x1000, 0xf177, 0xfe89, 0x1000, 0x06ce, 0x16e3, 0x024f, 0x0000, 0xfc55, 0xf3ab, 0x1000, + 0x1000}}, + {COLOR_GAMUT_YCBCR709_TYPE, COLOR_RANGE_LIMITED_8BPC, + {0x0e0e, 0xf33c, 0xfeb6, 0x1010, 0x05d8, 0x13a8, 0x01fc, 0x0202, 0xfcc8, 0xf52a, 0x0e0e, + 0x1010}}, + {COLOR_GAMUT_YCBCR709_TYPE, COLOR_RANGE_LIMITED_10BPC, + {0x0e03, 0xf345, 0xfeb7, 0x1004, 0x05d4, 0x1399, 0x01fa, 0x0201, 0xfcca, 0xf532, 0x0e03, + 0x1004}}, + {COLOR_GAMUT_YCBCR709_TYPE, COLOR_RANGE_LIMITED_16BPC, + {0x0db0, 0xf391, 0xfebf, 0x0fb0, 0x05d2, 0x1394, 0x01fa, 0x0200, 0xfcdd, 0xf573, 0x0db0, + 0x0fb0}}, + + {COLOR_GAMUT_YCBCR2020_TYPE, COLOR_RANGE_FULL, + {0x1000, 0xf149, 0xfeb7, 0x1000, 0x0868, 0x15b2, 0x01e6, 0x0000, 0xfb88, 0xf478, 0x1000, + 0x1000}}, + {COLOR_GAMUT_YCBCR2020_TYPE, COLOR_RANGE_LIMITED_8BPC, + {0x0e0e, 0xf313, 0xfedf, 0x1010, 0x0738, 0x12a2, 0x01a1, 0x0202, 0xfc13, 0xf5de, 0x0e0e, + 0x1010}}, + {COLOR_GAMUT_YCBCR2020_TYPE, COLOR_RANGE_LIMITED_10BPC, + {0x0e03, 0xf31d, 0xfee0, 0x1004, 0x0733, 0x1294, 0x01a0, 0x0201, 0xfc16, 0xf5e7, 0x0e03, + 0x1004}}, + {COLOR_GAMUT_YCBCR2020_TYPE, COLOR_RANGE_LIMITED_16BPC, + {0x0db0, 0xf36a, 0xfee6, 0x0fb0, 0x0731, 0x128f, 0x019f, 0x0200, 0xfc2d, 0xf622, 0x0db0, + 0x0fb0}}}; + +static bool is_ycbcr2020_limited_type(enum color_space color_space) { - bool ret = false; - - if (color_space == COLOR_SPACE_SRGB || color_space == COLOR_SPACE_MSREF_SCRGB || - color_space == COLOR_SPACE_2020_RGB_FULLRANGE) - ret = true; - - return ret; + return color_space == COLOR_SPACE_2020_YCBCR_LIMITED; } -static bool is_rgb_limited_type(enum color_space color_space) +static enum mpc_color_gamut_type get_color_gamut_type(enum color_space color_space) { - bool ret = false; - - if (color_space == COLOR_SPACE_SRGB_LIMITED || color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) - ret = true; - - return ret; -} - -static bool is_ycbcr601_full_type(enum color_space color_space) -{ - bool ret = false; - - if (color_space == COLOR_SPACE_YCBCR601) - ret = true; - - return ret; -} - -static bool is_ycbcr601_limited_type(enum color_space color_space) -{ - bool ret = false; - - if (color_space == COLOR_SPACE_YCBCR601_LIMITED) - ret = true; - - return ret; -} - -static bool is_ycbcr709_full_type(enum color_space color_space) -{ - bool ret = false; - - if (color_space == COLOR_SPACE_YCBCR709) - ret = true; - - return ret; -} - -static bool is_ycbcr709_limited_type(enum color_space color_space) -{ - bool ret = false; - - if (color_space == COLOR_SPACE_YCBCR709_LIMITED) - ret = true; - - return ret; -} - -static bool is_ycbcr2020_type(enum color_space color_space) -{ - bool ret = false; - - if (color_space == COLOR_SPACE_2020_YCBCR) - ret = true; - - return ret; -} - -static enum mpc_color_space_type get_color_space_type( - enum color_space color_space, enum vpe_surface_pixel_format pixel_format) -{ - enum mpc_color_space_type type = COLOR_SPACE_RGB_TYPE; - - if (is_rgb_full_type(color_space)) - type = COLOR_SPACE_RGB_TYPE; - else if (is_rgb_limited_type(color_space)) - type = vpe_is_rgb8(pixel_format) ? COLOR_SPACE_RGB_LIMITED_8PBC_TYPE - : COLOR_SPACE_RGB_LIMITED_10PBC_TYPE; - else if (is_ycbcr601_full_type(color_space)) - type = COLOR_SPACE_YCBCR601_TYPE; - else if (is_ycbcr709_full_type(color_space)) - type = COLOR_SPACE_YCBCR709_TYPE; - else if (is_ycbcr601_limited_type(color_space)) - type = COLOR_SPACE_YCBCR601_LIMITED_TYPE; - else if (is_ycbcr709_limited_type(color_space)) - type = COLOR_SPACE_YCBCR709_LIMITED_TYPE; - else if (is_ycbcr2020_type(color_space)) - type = COLOR_SPACE_YCBCR2020_TYPE; - - return type; + switch (color_space) { + case COLOR_SPACE_SRGB: + case COLOR_SPACE_SRGB_LIMITED: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_RGB601: + case COLOR_SPACE_RGB601_LIMITED: + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + return COLOR_GAMUT_RGB_TYPE; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + return COLOR_GAMUT_YCBCR601_TYPE; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + return COLOR_GAMUT_YCBCR709_TYPE; + case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_2020_YCBCR_LIMITED: + return COLOR_GAMUT_YCBCR2020_TYPE; + default: + VPE_ASSERT(false); + return COLOR_GAMUT_RGB_TYPE; + } } #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) @@ -161,18 +124,19 @@ static enum mpc_color_space_type get_color_space_type( const uint16_t *vpe_find_color_matrix( enum color_space color_space, enum vpe_surface_pixel_format pixel_format, uint32_t *array_size) { - int i; - enum mpc_color_space_type type; - const uint16_t *val = NULL; - int arr_size = NUM_ELEMENTS(output_csc_matrix); + const uint16_t *val = NULL; + enum mpc_color_gamut_type gamut = get_color_gamut_type(color_space); + enum color_range_type range = vpe_get_range_type(color_space, pixel_format); - type = get_color_space_type(color_space, pixel_format); + int i; + int arr_size = NUM_ELEMENTS(output_csc_2d_matrix); + for (i = 0; i < arr_size; i++) - if (output_csc_matrix[i].color_space_type == type) { - val = output_csc_matrix[i].regval; + if (output_csc_2d_matrix[i].color_gamut_type == gamut && + output_csc_2d_matrix[i].color_range_type == range) { + val = output_csc_2d_matrix[i].regval; *array_size = 12; break; } - return val; } diff --git a/src/amd/vpelib/src/core/vpe_visual_confirm.c b/src/amd/vpelib/src/core/vpe_visual_confirm.c index 4c9229ac855..1bb293d8964 100644 --- a/src/amd/vpelib/src/core/vpe_visual_confirm.c +++ b/src/amd/vpelib/src/core/vpe_visual_confirm.c @@ -158,7 +158,7 @@ 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, &visual_confirm_color, enable_3dlut); + vpe_bg_color_convert(output_cs, output_tf, output_format, &visual_confirm_color, enable_3dlut); // Experimental: To make FP16 Linear color looks more visually ok if (vpe_is_fp16(output_format)) { diff --git a/src/amd/vpelib/src/core/vpelib.c b/src/amd/vpelib/src/core/vpelib.c index e37e5b75b9c..67a37b775df 100644 --- a/src/amd/vpelib/src/core/vpelib.c +++ b/src/amd/vpelib/src/core/vpelib.c @@ -776,7 +776,7 @@ 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_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); if (vpe_priv->collaboration_mode == true) {