Next commit makes degamma PQ and SRGB EOTF halving distribute points per region which fits better the perceptually uniform shape of inputs, with 9 regions, and a region needs up to 128 samples from TF points (from 2^0 to 2^7). As a preparation, enable up to 256 samples per region (instead of 16). Create a function to linearly interpolate between neighboring TF points for readability.
Co-developed-by: Harry Wentland <[email protected]> Signed-off-by: Harry Wentland <[email protected]> Signed-off-by: Melissa Wen <[email protected]> --- .../amd/display/dc/dcn30/dcn30_cm_common.c | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c index a439bb6c5e56..b5cb2cd312ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c @@ -303,6 +303,22 @@ bool cm3_helper_translate_curve_to_hw_format(struct dc_context *ctx, #define NUM_DEGAMMA_REGIONS 12 +/* Linear interpolation of tf_pts entries, where (i >> 4) is the integer tf_pts + * index, (i & 0xf) is the 1/16 sub-position. + */ +static struct fixed31_32 interp_tf_pts(const struct fixed31_32 *output_tf_channel, int i) +{ + struct fixed31_32 in_plus_one, in, value; + uint32_t t = i & 0xf; + + in_plus_one = output_tf_channel[(i >> 4) + 1]; + in = output_tf_channel[i >> 4]; + value = dc_fixpt_sub(in_plus_one, in); + value = dc_fixpt_shr(dc_fixpt_mul_int(value, t), 4); + value = dc_fixpt_add(in, value); + + return value; +} bool cm3_helper_translate_curve_to_degamma_hw_format( const struct dc_transfer_func *output_tf, @@ -346,18 +362,20 @@ bool cm3_helper_translate_curve_to_degamma_hw_format( j = 0; for (k = 0; k < (region_end - region_start); k++) { - increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]); + increment = (NUMBER_SW_SEGMENTS << 4) / (1 << seg_distr[k]); start_index = (region_start + k + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS; - for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS; - i += increment) { + for (i = (start_index << 4); + i < (start_index << 4) + (NUMBER_SW_SEGMENTS << 4); + i += increment) { if (j == hw_points - 1) break; - if (i >= TRANSFER_FUNC_POINTS) + if ((i >> 4) + 1 >= TRANSFER_FUNC_POINTS) return false; - rgb_resulted[j].red = output_tf->tf_pts.red[i]; - rgb_resulted[j].green = output_tf->tf_pts.green[i]; - rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; + + rgb_resulted[j].red = interp_tf_pts(output_tf->tf_pts.red, i); + rgb_resulted[j].green = interp_tf_pts(output_tf->tf_pts.green, i); + rgb_resulted[j].blue = interp_tf_pts(output_tf->tf_pts.blue, i); j++; } } -- 2.53.0
