amd/vpelib: Refactor OCSC and update missing check

Missing check for 601 in limited format check, updated that.
Refactored OCSC to use specific limited depths.
Cleaned up general color processing.

Co-authored-by: Brendan <breleder@amd.com>
Reviewed-by: Jesse Agate <Jesse.Agate@amd.com>
Reviewed-by: Krunoslav Kovac <Krunoslav.Kovac@amd.com>
Acked-by: Chenyu Chen <Chen-Yu.Chen@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32075>
This commit is contained in:
Leder, Brendan Steve 2024-10-18 17:46:45 -04:00 committed by Chenyu Chen
parent dc1fe83aa5
commit 891c4694ba
13 changed files with 395 additions and 402 deletions

View file

@ -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);

View file

@ -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;
}

View file

@ -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:

View file

@ -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;
}

View file

@ -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))

View file

@ -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) {

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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)) {

View file

@ -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) {