|
@@ -1,1481 +0,0 @@
|
|
|
-/*
|
|
|
- * Copyright 2015 Advanced Micro Devices, Inc.
|
|
|
- *
|
|
|
- * Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
- * copy of this software and associated documentation files (the "Software"),
|
|
|
- * to deal in the Software without restriction, including without limitation
|
|
|
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
- * and/or sell copies of the Software, and to permit persons to whom the
|
|
|
- * Software is furnished to do so, subject to the following conditions:
|
|
|
- *
|
|
|
- * The above copyright notice and this permission notice shall be included in
|
|
|
- * all copies or substantial portions of the Software.
|
|
|
- *
|
|
|
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
- * OTHER DEALINGS IN THE SOFTWARE.
|
|
|
- *
|
|
|
- * Authors: AMD
|
|
|
- *
|
|
|
- */
|
|
|
-
|
|
|
-#include "dm_services.h"
|
|
|
-#include "gamma_calcs.h"
|
|
|
-
|
|
|
-struct curve_config {
|
|
|
- uint32_t offset;
|
|
|
- int8_t segments[16];
|
|
|
- int8_t begin;
|
|
|
-};
|
|
|
-
|
|
|
-static bool build_custom_float(
|
|
|
- struct fixed31_32 value,
|
|
|
- const struct custom_float_format *format,
|
|
|
- bool *negative,
|
|
|
- uint32_t *mantissa,
|
|
|
- uint32_t *exponenta)
|
|
|
-{
|
|
|
- uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
|
|
|
-
|
|
|
- const struct fixed31_32 mantissa_constant_plus_max_fraction =
|
|
|
- dal_fixed31_32_from_fraction(
|
|
|
- (1LL << (format->mantissa_bits + 1)) - 1,
|
|
|
- 1LL << format->mantissa_bits);
|
|
|
-
|
|
|
- struct fixed31_32 mantiss;
|
|
|
-
|
|
|
- if (dal_fixed31_32_eq(
|
|
|
- value,
|
|
|
- dal_fixed31_32_zero)) {
|
|
|
- *negative = false;
|
|
|
- *mantissa = 0;
|
|
|
- *exponenta = 0;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (dal_fixed31_32_lt(
|
|
|
- value,
|
|
|
- dal_fixed31_32_zero)) {
|
|
|
- *negative = format->sign;
|
|
|
- value = dal_fixed31_32_neg(value);
|
|
|
- } else {
|
|
|
- *negative = false;
|
|
|
- }
|
|
|
-
|
|
|
- if (dal_fixed31_32_lt(
|
|
|
- value,
|
|
|
- dal_fixed31_32_one)) {
|
|
|
- uint32_t i = 1;
|
|
|
-
|
|
|
- do {
|
|
|
- value = dal_fixed31_32_shl(value, 1);
|
|
|
- ++i;
|
|
|
- } while (dal_fixed31_32_lt(
|
|
|
- value,
|
|
|
- dal_fixed31_32_one));
|
|
|
-
|
|
|
- --i;
|
|
|
-
|
|
|
- if (exp_offset <= i) {
|
|
|
- *mantissa = 0;
|
|
|
- *exponenta = 0;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- *exponenta = exp_offset - i;
|
|
|
- } else if (dal_fixed31_32_le(
|
|
|
- mantissa_constant_plus_max_fraction,
|
|
|
- value)) {
|
|
|
- uint32_t i = 1;
|
|
|
-
|
|
|
- do {
|
|
|
- value = dal_fixed31_32_shr(value, 1);
|
|
|
- ++i;
|
|
|
- } while (dal_fixed31_32_lt(
|
|
|
- mantissa_constant_plus_max_fraction,
|
|
|
- value));
|
|
|
-
|
|
|
- *exponenta = exp_offset + i - 1;
|
|
|
- } else {
|
|
|
- *exponenta = exp_offset;
|
|
|
- }
|
|
|
-
|
|
|
- mantiss = dal_fixed31_32_sub(
|
|
|
- value,
|
|
|
- dal_fixed31_32_one);
|
|
|
-
|
|
|
- if (dal_fixed31_32_lt(
|
|
|
- mantiss,
|
|
|
- dal_fixed31_32_zero) ||
|
|
|
- dal_fixed31_32_lt(
|
|
|
- dal_fixed31_32_one,
|
|
|
- mantiss))
|
|
|
- mantiss = dal_fixed31_32_zero;
|
|
|
- else
|
|
|
- mantiss = dal_fixed31_32_shl(
|
|
|
- mantiss,
|
|
|
- format->mantissa_bits);
|
|
|
-
|
|
|
- *mantissa = dal_fixed31_32_floor(mantiss);
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-static bool setup_custom_float(
|
|
|
- const struct custom_float_format *format,
|
|
|
- bool negative,
|
|
|
- uint32_t mantissa,
|
|
|
- uint32_t exponenta,
|
|
|
- uint32_t *result)
|
|
|
-{
|
|
|
- uint32_t i = 0;
|
|
|
- uint32_t j = 0;
|
|
|
-
|
|
|
- uint32_t value = 0;
|
|
|
-
|
|
|
- /* verification code:
|
|
|
- * once calculation is ok we can remove it
|
|
|
- */
|
|
|
-
|
|
|
- const uint32_t mantissa_mask =
|
|
|
- (1 << (format->mantissa_bits + 1)) - 1;
|
|
|
-
|
|
|
- const uint32_t exponenta_mask =
|
|
|
- (1 << (format->exponenta_bits + 1)) - 1;
|
|
|
-
|
|
|
- if (mantissa & ~mantissa_mask) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- mantissa = mantissa_mask;
|
|
|
- }
|
|
|
-
|
|
|
- if (exponenta & ~exponenta_mask) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- exponenta = exponenta_mask;
|
|
|
- }
|
|
|
-
|
|
|
- /* end of verification code */
|
|
|
-
|
|
|
- while (i < format->mantissa_bits) {
|
|
|
- uint32_t mask = 1 << i;
|
|
|
-
|
|
|
- if (mantissa & mask)
|
|
|
- value |= mask;
|
|
|
-
|
|
|
- ++i;
|
|
|
- }
|
|
|
-
|
|
|
- while (j < format->exponenta_bits) {
|
|
|
- uint32_t mask = 1 << j;
|
|
|
-
|
|
|
- if (exponenta & mask)
|
|
|
- value |= mask << i;
|
|
|
-
|
|
|
- ++j;
|
|
|
- }
|
|
|
-
|
|
|
- if (negative && format->sign)
|
|
|
- value |= 1 << (i + j);
|
|
|
-
|
|
|
- *result = value;
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-static bool build_hw_curve_configuration(
|
|
|
- const struct curve_config *curve_config,
|
|
|
- struct gamma_curve *gamma_curve,
|
|
|
- struct curve_points *curve_points,
|
|
|
- struct hw_x_point *points,
|
|
|
- uint32_t *number_of_points)
|
|
|
-{
|
|
|
- const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments);
|
|
|
-
|
|
|
- int8_t i;
|
|
|
-
|
|
|
- uint8_t segments_calculation[8] = { 0 };
|
|
|
-
|
|
|
- struct fixed31_32 region1 = dal_fixed31_32_zero;
|
|
|
- struct fixed31_32 region2;
|
|
|
- struct fixed31_32 increment;
|
|
|
-
|
|
|
- uint32_t index = 0;
|
|
|
- uint32_t segments = 0;
|
|
|
- uint32_t max_number;
|
|
|
-
|
|
|
- int8_t num_regions = 0;
|
|
|
-
|
|
|
- bool result = false;
|
|
|
-
|
|
|
- if (!number_of_points) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- max_number = *number_of_points;
|
|
|
-
|
|
|
- i = 0;
|
|
|
-
|
|
|
- while (i != max_regions_number) {
|
|
|
- gamma_curve[i].offset = 0;
|
|
|
- gamma_curve[i].segments_num = 0;
|
|
|
-
|
|
|
- ++i;
|
|
|
- }
|
|
|
-
|
|
|
- i = 0;
|
|
|
-
|
|
|
- while (i != max_regions_number) {
|
|
|
- /* number should go in uninterruptible sequence */
|
|
|
- if (curve_config->segments[i] == -1)
|
|
|
- break;
|
|
|
-
|
|
|
- ASSERT(curve_config->segments[i] >= 0);
|
|
|
-
|
|
|
- segments += (1 << curve_config->segments[i]);
|
|
|
- ++num_regions;
|
|
|
-
|
|
|
- ++i;
|
|
|
- }
|
|
|
-
|
|
|
- if (segments > max_number) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- } else {
|
|
|
- int32_t divisor;
|
|
|
- uint32_t offset = 0;
|
|
|
- int8_t begin = curve_config->begin;
|
|
|
- int32_t region_number = 0;
|
|
|
-
|
|
|
- i = begin;
|
|
|
-
|
|
|
- while ((index < max_number) &&
|
|
|
- (region_number < max_regions_number) &&
|
|
|
- (i < (begin + num_regions))) {
|
|
|
- int32_t j = 0;
|
|
|
-
|
|
|
- segments = curve_config->segments[region_number];
|
|
|
- divisor = 1 << segments;
|
|
|
-
|
|
|
- if (segments == -1) {
|
|
|
- if (i > 0) {
|
|
|
- region1 = dal_fixed31_32_shl(
|
|
|
- dal_fixed31_32_one,
|
|
|
- i - 1);
|
|
|
- region2 = dal_fixed31_32_shl(
|
|
|
- dal_fixed31_32_one,
|
|
|
- i);
|
|
|
- } else {
|
|
|
- region1 = dal_fixed31_32_shr(
|
|
|
- dal_fixed31_32_one,
|
|
|
- -(i - 1));
|
|
|
- region2 = dal_fixed31_32_shr(
|
|
|
- dal_fixed31_32_one,
|
|
|
- -i);
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (i > -1) {
|
|
|
- region1 = dal_fixed31_32_shl(
|
|
|
- dal_fixed31_32_one,
|
|
|
- i);
|
|
|
- region2 = dal_fixed31_32_shl(
|
|
|
- dal_fixed31_32_one,
|
|
|
- i + 1);
|
|
|
- } else {
|
|
|
- region1 = dal_fixed31_32_shr(
|
|
|
- dal_fixed31_32_one,
|
|
|
- -i);
|
|
|
- region2 = dal_fixed31_32_shr(
|
|
|
- dal_fixed31_32_one,
|
|
|
- -(i + 1));
|
|
|
- }
|
|
|
-
|
|
|
- gamma_curve[region_number].offset = offset;
|
|
|
- gamma_curve[region_number].segments_num = segments;
|
|
|
-
|
|
|
- offset += divisor;
|
|
|
-
|
|
|
- ++segments_calculation[segments];
|
|
|
-
|
|
|
- increment = dal_fixed31_32_div_int(
|
|
|
- dal_fixed31_32_sub(
|
|
|
- region2,
|
|
|
- region1),
|
|
|
- divisor);
|
|
|
-
|
|
|
- points[index].x = region1;
|
|
|
- points[index].adjusted_x = region1;
|
|
|
-
|
|
|
- ++index;
|
|
|
- ++region_number;
|
|
|
-
|
|
|
- while ((index < max_number) && (j < divisor - 1)) {
|
|
|
- region1 = dal_fixed31_32_add(
|
|
|
- region1,
|
|
|
- increment);
|
|
|
-
|
|
|
- points[index].x = region1;
|
|
|
- points[index].adjusted_x = region1;
|
|
|
-
|
|
|
- ++index;
|
|
|
- ++j;
|
|
|
- }
|
|
|
-
|
|
|
- ++i;
|
|
|
- }
|
|
|
-
|
|
|
- points[index].x = region1;
|
|
|
- points[index].adjusted_x = region1;
|
|
|
-
|
|
|
- *number_of_points = index;
|
|
|
-
|
|
|
- result = true;
|
|
|
- }
|
|
|
-
|
|
|
- curve_points[0].x = points[0].adjusted_x;
|
|
|
- curve_points[0].offset = dal_fixed31_32_zero;
|
|
|
-
|
|
|
- curve_points[1].x = points[index - 1].adjusted_x;
|
|
|
- curve_points[1].offset = dal_fixed31_32_zero;
|
|
|
-
|
|
|
- curve_points[2].x = points[index].adjusted_x;
|
|
|
- curve_points[2].offset = dal_fixed31_32_zero;
|
|
|
-
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-static bool setup_distribution_points_pq(
|
|
|
- struct gamma_curve *arr_curve_points,
|
|
|
- struct curve_points *arr_points,
|
|
|
- uint32_t *hw_points_num,
|
|
|
- struct hw_x_point *coordinates_x,
|
|
|
- enum surface_pixel_format format)
|
|
|
-{
|
|
|
- struct curve_config cfg;
|
|
|
-
|
|
|
- cfg.offset = 0;
|
|
|
- cfg.segments[0] = 2;
|
|
|
- cfg.segments[1] = 2;
|
|
|
- cfg.segments[2] = 2;
|
|
|
- cfg.segments[3] = 2;
|
|
|
- cfg.segments[4] = 2;
|
|
|
- cfg.segments[5] = 2;
|
|
|
- cfg.segments[6] = 3;
|
|
|
- cfg.segments[7] = 4;
|
|
|
- cfg.segments[8] = 4;
|
|
|
- cfg.segments[9] = 4;
|
|
|
- cfg.segments[10] = 4;
|
|
|
- cfg.segments[11] = 5;
|
|
|
- cfg.segments[12] = 5;
|
|
|
- cfg.segments[13] = 5;
|
|
|
- cfg.segments[14] = 5;
|
|
|
- cfg.segments[15] = 5;
|
|
|
-
|
|
|
- if (format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F ||
|
|
|
- format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F)
|
|
|
- cfg.begin = -11;
|
|
|
- else
|
|
|
- cfg.begin = -16;
|
|
|
-
|
|
|
- if (!build_hw_curve_configuration(
|
|
|
- &cfg, arr_curve_points,
|
|
|
- arr_points,
|
|
|
- coordinates_x, hw_points_num)) {
|
|
|
- ASSERT_CRITICAL(false);
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-static bool setup_distribution_points(
|
|
|
- struct gamma_curve *arr_curve_points,
|
|
|
- struct curve_points *arr_points,
|
|
|
- uint32_t *hw_points_num,
|
|
|
- struct hw_x_point *coordinates_x)
|
|
|
-{
|
|
|
- struct curve_config cfg;
|
|
|
-
|
|
|
- cfg.offset = 0;
|
|
|
- cfg.segments[0] = 3;
|
|
|
- cfg.segments[1] = 4;
|
|
|
- cfg.segments[2] = 4;
|
|
|
- cfg.segments[3] = 4;
|
|
|
- cfg.segments[4] = 4;
|
|
|
- cfg.segments[5] = 4;
|
|
|
- cfg.segments[6] = 4;
|
|
|
- cfg.segments[7] = 4;
|
|
|
- cfg.segments[8] = 5;
|
|
|
- cfg.segments[9] = 5;
|
|
|
- cfg.segments[10] = 0;
|
|
|
- cfg.segments[11] = -1;
|
|
|
- cfg.segments[12] = -1;
|
|
|
- cfg.segments[13] = -1;
|
|
|
- cfg.segments[14] = -1;
|
|
|
- cfg.segments[15] = -1;
|
|
|
-
|
|
|
- cfg.begin = -10;
|
|
|
-
|
|
|
- if (!build_hw_curve_configuration(
|
|
|
- &cfg, arr_curve_points,
|
|
|
- arr_points,
|
|
|
- coordinates_x, hw_points_num)) {
|
|
|
- ASSERT_CRITICAL(false);
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-struct dividers {
|
|
|
- struct fixed31_32 divider1;
|
|
|
- struct fixed31_32 divider2;
|
|
|
- struct fixed31_32 divider3;
|
|
|
-};
|
|
|
-
|
|
|
-static void build_regamma_coefficients(struct gamma_coefficients *coefficients)
|
|
|
-{
|
|
|
- /* sRGB should apply 2.4 */
|
|
|
- static const int32_t numerator01[3] = { 31308, 31308, 31308 };
|
|
|
- static const int32_t numerator02[3] = { 12920, 12920, 12920 };
|
|
|
- static const int32_t numerator03[3] = { 55, 55, 55 };
|
|
|
- static const int32_t numerator04[3] = { 55, 55, 55 };
|
|
|
- static const int32_t numerator05[3] = { 2400, 2400, 2400 };
|
|
|
-
|
|
|
- const int32_t *numerator1;
|
|
|
- const int32_t *numerator2;
|
|
|
- const int32_t *numerator3;
|
|
|
- const int32_t *numerator4;
|
|
|
- const int32_t *numerator5;
|
|
|
-
|
|
|
- uint32_t i = 0;
|
|
|
-
|
|
|
- numerator1 = numerator01;
|
|
|
- numerator2 = numerator02;
|
|
|
- numerator3 = numerator03;
|
|
|
- numerator4 = numerator04;
|
|
|
- numerator5 = numerator05;
|
|
|
-
|
|
|
- do {
|
|
|
- coefficients->a0[i] = dal_fixed31_32_from_fraction(
|
|
|
- numerator1[i], 10000000);
|
|
|
- coefficients->a1[i] = dal_fixed31_32_from_fraction(
|
|
|
- numerator2[i], 1000);
|
|
|
- coefficients->a2[i] = dal_fixed31_32_from_fraction(
|
|
|
- numerator3[i], 1000);
|
|
|
- coefficients->a3[i] = dal_fixed31_32_from_fraction(
|
|
|
- numerator4[i], 1000);
|
|
|
- coefficients->user_gamma[i] = dal_fixed31_32_from_fraction(
|
|
|
- numerator5[i], 1000);
|
|
|
-
|
|
|
- ++i;
|
|
|
- } while (i != ARRAY_SIZE(coefficients->a0));
|
|
|
-}
|
|
|
-
|
|
|
-static struct fixed31_32 translate_from_linear_space(
|
|
|
- struct fixed31_32 arg,
|
|
|
- struct fixed31_32 a0,
|
|
|
- struct fixed31_32 a1,
|
|
|
- struct fixed31_32 a2,
|
|
|
- struct fixed31_32 a3,
|
|
|
- struct fixed31_32 gamma)
|
|
|
-{
|
|
|
- const struct fixed31_32 one = dal_fixed31_32_from_int(1);
|
|
|
-
|
|
|
- if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0)))
|
|
|
- return dal_fixed31_32_sub(
|
|
|
- a2,
|
|
|
- dal_fixed31_32_mul(
|
|
|
- dal_fixed31_32_add(
|
|
|
- one,
|
|
|
- a3),
|
|
|
- dal_fixed31_32_pow(
|
|
|
- dal_fixed31_32_neg(arg),
|
|
|
- dal_fixed31_32_recip(gamma))));
|
|
|
- else if (dal_fixed31_32_le(a0, arg))
|
|
|
- return dal_fixed31_32_sub(
|
|
|
- dal_fixed31_32_mul(
|
|
|
- dal_fixed31_32_add(
|
|
|
- one,
|
|
|
- a3),
|
|
|
- dal_fixed31_32_pow(
|
|
|
- arg,
|
|
|
- dal_fixed31_32_recip(gamma))),
|
|
|
- a2);
|
|
|
- else
|
|
|
- return dal_fixed31_32_mul(
|
|
|
- arg,
|
|
|
- a1);
|
|
|
-}
|
|
|
-
|
|
|
-static inline struct fixed31_32 translate_from_linear_space_ex(
|
|
|
- struct fixed31_32 arg,
|
|
|
- struct gamma_coefficients *coeff,
|
|
|
- uint32_t color_index)
|
|
|
-{
|
|
|
- return translate_from_linear_space(
|
|
|
- arg,
|
|
|
- coeff->a0[color_index],
|
|
|
- coeff->a1[color_index],
|
|
|
- coeff->a2[color_index],
|
|
|
- coeff->a3[color_index],
|
|
|
- coeff->user_gamma[color_index]);
|
|
|
-}
|
|
|
-
|
|
|
-static bool find_software_points(
|
|
|
- const struct gamma_pixel *axis_x_256,
|
|
|
- struct fixed31_32 hw_point,
|
|
|
- enum channel_name channel,
|
|
|
- uint32_t *index_to_start,
|
|
|
- uint32_t *index_left,
|
|
|
- uint32_t *index_right,
|
|
|
- enum hw_point_position *pos)
|
|
|
-{
|
|
|
- const uint32_t max_number = INPUT_LUT_ENTRIES + 3;
|
|
|
-
|
|
|
- struct fixed31_32 left, right;
|
|
|
-
|
|
|
- uint32_t i = *index_to_start;
|
|
|
-
|
|
|
- while (i < max_number) {
|
|
|
- if (channel == CHANNEL_NAME_RED) {
|
|
|
- left = axis_x_256[i].r;
|
|
|
-
|
|
|
- if (i < max_number - 1)
|
|
|
- right = axis_x_256[i + 1].r;
|
|
|
- else
|
|
|
- right = axis_x_256[max_number - 1].r;
|
|
|
- } else if (channel == CHANNEL_NAME_GREEN) {
|
|
|
- left = axis_x_256[i].g;
|
|
|
-
|
|
|
- if (i < max_number - 1)
|
|
|
- right = axis_x_256[i + 1].g;
|
|
|
- else
|
|
|
- right = axis_x_256[max_number - 1].g;
|
|
|
- } else {
|
|
|
- left = axis_x_256[i].b;
|
|
|
-
|
|
|
- if (i < max_number - 1)
|
|
|
- right = axis_x_256[i + 1].b;
|
|
|
- else
|
|
|
- right = axis_x_256[max_number - 1].b;
|
|
|
- }
|
|
|
-
|
|
|
- if (dal_fixed31_32_le(left, hw_point) &&
|
|
|
- dal_fixed31_32_le(hw_point, right)) {
|
|
|
- *index_to_start = i;
|
|
|
- *index_left = i;
|
|
|
-
|
|
|
- if (i < max_number - 1)
|
|
|
- *index_right = i + 1;
|
|
|
- else
|
|
|
- *index_right = max_number - 1;
|
|
|
-
|
|
|
- *pos = HW_POINT_POSITION_MIDDLE;
|
|
|
-
|
|
|
- return true;
|
|
|
- } else if ((i == *index_to_start) &&
|
|
|
- dal_fixed31_32_le(hw_point, left)) {
|
|
|
- *index_to_start = i;
|
|
|
- *index_left = i;
|
|
|
- *index_right = i;
|
|
|
-
|
|
|
- *pos = HW_POINT_POSITION_LEFT;
|
|
|
-
|
|
|
- return true;
|
|
|
- } else if ((i == max_number - 1) &&
|
|
|
- dal_fixed31_32_le(right, hw_point)) {
|
|
|
- *index_to_start = i;
|
|
|
- *index_left = i;
|
|
|
- *index_right = i;
|
|
|
-
|
|
|
- *pos = HW_POINT_POSITION_RIGHT;
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- ++i;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-static bool build_custom_gamma_mapping_coefficients_worker(
|
|
|
- struct pixel_gamma_point *coeff,
|
|
|
- const struct hw_x_point *coordinates_x,
|
|
|
- const struct gamma_pixel *axis_x_256,
|
|
|
- enum channel_name channel,
|
|
|
- uint32_t number_of_points,
|
|
|
- enum surface_pixel_format pixel_format)
|
|
|
-{
|
|
|
- uint32_t i = 0;
|
|
|
-
|
|
|
- while (i <= number_of_points) {
|
|
|
- struct fixed31_32 coord_x;
|
|
|
-
|
|
|
- uint32_t index_to_start = 0;
|
|
|
- uint32_t index_left = 0;
|
|
|
- uint32_t index_right = 0;
|
|
|
-
|
|
|
- enum hw_point_position hw_pos;
|
|
|
-
|
|
|
- struct gamma_point *point;
|
|
|
-
|
|
|
- struct fixed31_32 left_pos;
|
|
|
- struct fixed31_32 right_pos;
|
|
|
-
|
|
|
- /*
|
|
|
- * TODO: confirm enum in surface_pixel_format
|
|
|
- * if (pixel_format == PIXEL_FORMAT_FP16)
|
|
|
- *coord_x = coordinates_x[i].adjusted_x;
|
|
|
- *else
|
|
|
- */
|
|
|
- if (channel == CHANNEL_NAME_RED)
|
|
|
- coord_x = coordinates_x[i].regamma_y_red;
|
|
|
- else if (channel == CHANNEL_NAME_GREEN)
|
|
|
- coord_x = coordinates_x[i].regamma_y_green;
|
|
|
- else
|
|
|
- coord_x = coordinates_x[i].regamma_y_blue;
|
|
|
-
|
|
|
- if (!find_software_points(
|
|
|
- axis_x_256, coord_x, channel,
|
|
|
- &index_to_start, &index_left, &index_right, &hw_pos)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (index_left >= INPUT_LUT_ENTRIES + 3) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (index_right >= INPUT_LUT_ENTRIES + 3) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (channel == CHANNEL_NAME_RED) {
|
|
|
- point = &coeff[i].r;
|
|
|
-
|
|
|
- left_pos = axis_x_256[index_left].r;
|
|
|
- right_pos = axis_x_256[index_right].r;
|
|
|
- } else if (channel == CHANNEL_NAME_GREEN) {
|
|
|
- point = &coeff[i].g;
|
|
|
-
|
|
|
- left_pos = axis_x_256[index_left].g;
|
|
|
- right_pos = axis_x_256[index_right].g;
|
|
|
- } else {
|
|
|
- point = &coeff[i].b;
|
|
|
-
|
|
|
- left_pos = axis_x_256[index_left].b;
|
|
|
- right_pos = axis_x_256[index_right].b;
|
|
|
- }
|
|
|
-
|
|
|
- if (hw_pos == HW_POINT_POSITION_MIDDLE)
|
|
|
- point->coeff = dal_fixed31_32_div(
|
|
|
- dal_fixed31_32_sub(
|
|
|
- coord_x,
|
|
|
- left_pos),
|
|
|
- dal_fixed31_32_sub(
|
|
|
- right_pos,
|
|
|
- left_pos));
|
|
|
- else if (hw_pos == HW_POINT_POSITION_LEFT)
|
|
|
- point->coeff = dal_fixed31_32_zero;
|
|
|
- else if (hw_pos == HW_POINT_POSITION_RIGHT)
|
|
|
- point->coeff = dal_fixed31_32_from_int(2);
|
|
|
- else {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- point->left_index = index_left;
|
|
|
- point->right_index = index_right;
|
|
|
- point->pos = hw_pos;
|
|
|
-
|
|
|
- ++i;
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-static inline bool build_oem_custom_gamma_mapping_coefficients(
|
|
|
- struct pixel_gamma_point *coeff128_oem,
|
|
|
- const struct hw_x_point *coordinates_x,
|
|
|
- const struct gamma_pixel *axis_x_256,
|
|
|
- uint32_t number_of_points,
|
|
|
- enum surface_pixel_format pixel_format)
|
|
|
-{
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < 3; i++) {
|
|
|
- if (!build_custom_gamma_mapping_coefficients_worker(
|
|
|
- coeff128_oem, coordinates_x, axis_x_256, i,
|
|
|
- number_of_points, pixel_format))
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-static struct fixed31_32 calculate_mapped_value(
|
|
|
- struct pwl_float_data *rgb,
|
|
|
- const struct pixel_gamma_point *coeff,
|
|
|
- enum channel_name channel,
|
|
|
- uint32_t max_index)
|
|
|
-{
|
|
|
- const struct gamma_point *point;
|
|
|
-
|
|
|
- struct fixed31_32 result;
|
|
|
-
|
|
|
- if (channel == CHANNEL_NAME_RED)
|
|
|
- point = &coeff->r;
|
|
|
- else if (channel == CHANNEL_NAME_GREEN)
|
|
|
- point = &coeff->g;
|
|
|
- else
|
|
|
- point = &coeff->b;
|
|
|
-
|
|
|
- if ((point->left_index < 0) || (point->left_index > max_index)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return dal_fixed31_32_zero;
|
|
|
- }
|
|
|
-
|
|
|
- if ((point->right_index < 0) || (point->right_index > max_index)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return dal_fixed31_32_zero;
|
|
|
- }
|
|
|
-
|
|
|
- if (point->pos == HW_POINT_POSITION_MIDDLE)
|
|
|
- if (channel == CHANNEL_NAME_RED)
|
|
|
- result = dal_fixed31_32_add(
|
|
|
- dal_fixed31_32_mul(
|
|
|
- point->coeff,
|
|
|
- dal_fixed31_32_sub(
|
|
|
- rgb[point->right_index].r,
|
|
|
- rgb[point->left_index].r)),
|
|
|
- rgb[point->left_index].r);
|
|
|
- else if (channel == CHANNEL_NAME_GREEN)
|
|
|
- result = dal_fixed31_32_add(
|
|
|
- dal_fixed31_32_mul(
|
|
|
- point->coeff,
|
|
|
- dal_fixed31_32_sub(
|
|
|
- rgb[point->right_index].g,
|
|
|
- rgb[point->left_index].g)),
|
|
|
- rgb[point->left_index].g);
|
|
|
- else
|
|
|
- result = dal_fixed31_32_add(
|
|
|
- dal_fixed31_32_mul(
|
|
|
- point->coeff,
|
|
|
- dal_fixed31_32_sub(
|
|
|
- rgb[point->right_index].b,
|
|
|
- rgb[point->left_index].b)),
|
|
|
- rgb[point->left_index].b);
|
|
|
- else if (point->pos == HW_POINT_POSITION_LEFT) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- result = dal_fixed31_32_zero;
|
|
|
- } else {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- result = dal_fixed31_32_one;
|
|
|
- }
|
|
|
-
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-static inline struct fixed31_32 calculate_oem_mapped_value(
|
|
|
- struct pwl_float_data *rgb_oem,
|
|
|
- const struct pixel_gamma_point *coeff,
|
|
|
- uint32_t index,
|
|
|
- enum channel_name channel,
|
|
|
- uint32_t max_index)
|
|
|
-{
|
|
|
- return calculate_mapped_value(
|
|
|
- rgb_oem,
|
|
|
- coeff + index,
|
|
|
- channel,
|
|
|
- max_index);
|
|
|
-}
|
|
|
-
|
|
|
-static void compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y)
|
|
|
-{
|
|
|
- /* consts for PQ gamma formula. */
|
|
|
- const struct fixed31_32 m1 =
|
|
|
- dal_fixed31_32_from_fraction(159301758, 1000000000);
|
|
|
- const struct fixed31_32 m2 =
|
|
|
- dal_fixed31_32_from_fraction(7884375, 100000);
|
|
|
- const struct fixed31_32 c1 =
|
|
|
- dal_fixed31_32_from_fraction(8359375, 10000000);
|
|
|
- const struct fixed31_32 c2 =
|
|
|
- dal_fixed31_32_from_fraction(188515625, 10000000);
|
|
|
- const struct fixed31_32 c3 =
|
|
|
- dal_fixed31_32_from_fraction(186875, 10000);
|
|
|
-
|
|
|
- struct fixed31_32 l_pow_m1;
|
|
|
- struct fixed31_32 base;
|
|
|
-
|
|
|
- if (dal_fixed31_32_lt(in_x, dal_fixed31_32_zero))
|
|
|
- in_x = dal_fixed31_32_zero;
|
|
|
-
|
|
|
- l_pow_m1 = dal_fixed31_32_pow(in_x, m1);
|
|
|
- base = dal_fixed31_32_div(
|
|
|
- dal_fixed31_32_add(c1,
|
|
|
- (dal_fixed31_32_mul(c2, l_pow_m1))),
|
|
|
- dal_fixed31_32_add(dal_fixed31_32_one,
|
|
|
- (dal_fixed31_32_mul(c3, l_pow_m1))));
|
|
|
- *out_y = dal_fixed31_32_pow(base, m2);
|
|
|
-}
|
|
|
-
|
|
|
-static void build_regamma_curve_pq(struct pwl_float_data_ex *rgb_regamma,
|
|
|
- struct pwl_float_data *rgb_oem,
|
|
|
- struct pixel_gamma_point *coeff128_oem,
|
|
|
- const struct core_gamma *ramp,
|
|
|
- const struct core_surface *surface,
|
|
|
- uint32_t hw_points_num,
|
|
|
- const struct hw_x_point *coordinate_x,
|
|
|
- const struct gamma_pixel *axis_x,
|
|
|
- struct dividers dividers)
|
|
|
-{
|
|
|
- uint32_t i;
|
|
|
-
|
|
|
- struct pwl_float_data_ex *rgb = rgb_regamma;
|
|
|
- const struct hw_x_point *coord_x = coordinate_x;
|
|
|
- struct fixed31_32 x;
|
|
|
- struct fixed31_32 output;
|
|
|
- struct fixed31_32 scaling_factor =
|
|
|
- dal_fixed31_32_from_fraction(8, 1000);
|
|
|
-
|
|
|
- /* use coord_x to retrieve coordinates chosen base on given user curve
|
|
|
- * the x values are exponentially distributed and currently it is hard
|
|
|
- * coded, the user curve shape is ignored. Need to recalculate coord_x
|
|
|
- * based on input curve, translation from 256/1025 to 128 PWL points.
|
|
|
- */
|
|
|
- for (i = 0; i <= hw_points_num; i++) {
|
|
|
- /* Multiply 0.008 as regamma is 0-1 and FP16 input is 0-125.
|
|
|
- * FP 1.0 = 80nits
|
|
|
- */
|
|
|
- x = dal_fixed31_32_mul(coord_x->adjusted_x, scaling_factor);
|
|
|
-
|
|
|
- compute_pq(x, &output);
|
|
|
-
|
|
|
- /* should really not happen? */
|
|
|
- if (dal_fixed31_32_lt(output, dal_fixed31_32_zero))
|
|
|
- output = dal_fixed31_32_zero;
|
|
|
- else if (dal_fixed31_32_lt(dal_fixed31_32_one, output))
|
|
|
- output = dal_fixed31_32_one;
|
|
|
-
|
|
|
- rgb->r = output;
|
|
|
- rgb->g = output;
|
|
|
- rgb->b = output;
|
|
|
-
|
|
|
- ++coord_x;
|
|
|
- ++rgb;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma,
|
|
|
- struct pwl_float_data *rgb_oem,
|
|
|
- struct pixel_gamma_point *coeff128_oem,
|
|
|
- const struct core_gamma *ramp,
|
|
|
- const struct core_surface *surface,
|
|
|
- uint32_t hw_points_num,
|
|
|
- const struct hw_x_point *coordinate_x,
|
|
|
- const struct gamma_pixel *axis_x,
|
|
|
- struct dividers dividers)
|
|
|
-{
|
|
|
- uint32_t i;
|
|
|
-
|
|
|
- struct gamma_coefficients coeff;
|
|
|
- struct pwl_float_data_ex *rgb = rgb_regamma;
|
|
|
- const struct hw_x_point *coord_x = coordinate_x;
|
|
|
-
|
|
|
- build_regamma_coefficients(&coeff);
|
|
|
-
|
|
|
- /* Use opp110->regamma.coordinates_x to retrieve
|
|
|
- * coordinates chosen base on given user curve (future task).
|
|
|
- * The x values are exponentially distributed and currently
|
|
|
- * it is hard-coded, the user curve shape is ignored.
|
|
|
- * The future task is to recalculate opp110-
|
|
|
- * regamma.coordinates_x based on input/user curve,
|
|
|
- * translation from 256/1025 to 128 pwl points.
|
|
|
- */
|
|
|
-
|
|
|
- i = 0;
|
|
|
-
|
|
|
- while (i != hw_points_num + 1) {
|
|
|
- rgb->r = translate_from_linear_space_ex(
|
|
|
- coord_x->adjusted_x, &coeff, 0);
|
|
|
- rgb->g = translate_from_linear_space_ex(
|
|
|
- coord_x->adjusted_x, &coeff, 1);
|
|
|
- rgb->b = translate_from_linear_space_ex(
|
|
|
- coord_x->adjusted_x, &coeff, 2);
|
|
|
-
|
|
|
- ++coord_x;
|
|
|
- ++rgb;
|
|
|
- ++i;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static bool scale_gamma(struct pwl_float_data *pwl_rgb,
|
|
|
- const struct core_gamma *ramp,
|
|
|
- struct dividers dividers)
|
|
|
-{
|
|
|
- const struct dc_gamma *gamma = &ramp->public;
|
|
|
- const uint16_t max_driver = 0xFFFF;
|
|
|
- const uint16_t max_os = 0xFF00;
|
|
|
- uint16_t scaler = max_os;
|
|
|
- uint32_t i = 0;
|
|
|
- struct pwl_float_data *rgb = pwl_rgb;
|
|
|
- struct pwl_float_data *rgb_last = rgb + INPUT_LUT_ENTRIES - 1;
|
|
|
-
|
|
|
- do {
|
|
|
- if ((gamma->red[i] > max_os) ||
|
|
|
- (gamma->green[i] > max_os) ||
|
|
|
- (gamma->blue[i] > max_os)) {
|
|
|
- scaler = max_driver;
|
|
|
- break;
|
|
|
- }
|
|
|
- ++i;
|
|
|
- } while (i != INPUT_LUT_ENTRIES);
|
|
|
-
|
|
|
- i = 0;
|
|
|
-
|
|
|
- do {
|
|
|
- rgb->r = dal_fixed31_32_from_fraction(
|
|
|
- gamma->red[i], scaler);
|
|
|
- rgb->g = dal_fixed31_32_from_fraction(
|
|
|
- gamma->green[i], scaler);
|
|
|
- rgb->b = dal_fixed31_32_from_fraction(
|
|
|
- gamma->blue[i], scaler);
|
|
|
-
|
|
|
- ++rgb;
|
|
|
- ++i;
|
|
|
- } while (i != INPUT_LUT_ENTRIES);
|
|
|
-
|
|
|
- rgb->r = dal_fixed31_32_mul(rgb_last->r,
|
|
|
- dividers.divider1);
|
|
|
- rgb->g = dal_fixed31_32_mul(rgb_last->g,
|
|
|
- dividers.divider1);
|
|
|
- rgb->b = dal_fixed31_32_mul(rgb_last->b,
|
|
|
- dividers.divider1);
|
|
|
-
|
|
|
- ++rgb;
|
|
|
-
|
|
|
- rgb->r = dal_fixed31_32_mul(rgb_last->r,
|
|
|
- dividers.divider2);
|
|
|
- rgb->g = dal_fixed31_32_mul(rgb_last->g,
|
|
|
- dividers.divider2);
|
|
|
- rgb->b = dal_fixed31_32_mul(rgb_last->b,
|
|
|
- dividers.divider2);
|
|
|
-
|
|
|
- ++rgb;
|
|
|
-
|
|
|
- rgb->r = dal_fixed31_32_mul(rgb_last->r,
|
|
|
- dividers.divider3);
|
|
|
- rgb->g = dal_fixed31_32_mul(rgb_last->g,
|
|
|
- dividers.divider3);
|
|
|
- rgb->b = dal_fixed31_32_mul(rgb_last->b,
|
|
|
- dividers.divider3);
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-static void build_evenly_distributed_points(
|
|
|
- struct gamma_pixel *points,
|
|
|
- uint32_t numberof_points,
|
|
|
- struct fixed31_32 max_value,
|
|
|
- struct dividers dividers)
|
|
|
-{
|
|
|
- struct gamma_pixel *p = points;
|
|
|
- struct gamma_pixel *p_last = p + numberof_points - 1;
|
|
|
-
|
|
|
- uint32_t i = 0;
|
|
|
-
|
|
|
- do {
|
|
|
- struct fixed31_32 value = dal_fixed31_32_div_int(
|
|
|
- dal_fixed31_32_mul_int(max_value, i),
|
|
|
- numberof_points - 1);
|
|
|
-
|
|
|
- p->r = value;
|
|
|
- p->g = value;
|
|
|
- p->b = value;
|
|
|
-
|
|
|
- ++p;
|
|
|
- ++i;
|
|
|
- } while (i != numberof_points);
|
|
|
-
|
|
|
- p->r = dal_fixed31_32_div(p_last->r, dividers.divider1);
|
|
|
- p->g = dal_fixed31_32_div(p_last->g, dividers.divider1);
|
|
|
- p->b = dal_fixed31_32_div(p_last->b, dividers.divider1);
|
|
|
-
|
|
|
- ++p;
|
|
|
-
|
|
|
- p->r = dal_fixed31_32_div(p_last->r, dividers.divider2);
|
|
|
- p->g = dal_fixed31_32_div(p_last->g, dividers.divider2);
|
|
|
- p->b = dal_fixed31_32_div(p_last->b, dividers.divider2);
|
|
|
-
|
|
|
- ++p;
|
|
|
-
|
|
|
- p->r = dal_fixed31_32_div(p_last->r, dividers.divider3);
|
|
|
- p->g = dal_fixed31_32_div(p_last->g, dividers.divider3);
|
|
|
- p->b = dal_fixed31_32_div(p_last->b, dividers.divider3);
|
|
|
-}
|
|
|
-
|
|
|
-static inline void copy_rgb_regamma_to_coordinates_x(
|
|
|
- struct hw_x_point *coordinates_x,
|
|
|
- uint32_t hw_points_num,
|
|
|
- const struct pwl_float_data_ex *rgb_ex)
|
|
|
-{
|
|
|
- struct hw_x_point *coords = coordinates_x;
|
|
|
- uint32_t i = 0;
|
|
|
- const struct pwl_float_data_ex *rgb_regamma = rgb_ex;
|
|
|
-
|
|
|
- while (i <= hw_points_num) {
|
|
|
- coords->regamma_y_red = rgb_regamma->r;
|
|
|
- coords->regamma_y_green = rgb_regamma->g;
|
|
|
- coords->regamma_y_blue = rgb_regamma->b;
|
|
|
-
|
|
|
- ++coords;
|
|
|
- ++rgb_regamma;
|
|
|
- ++i;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static bool calculate_interpolated_hardware_curve(
|
|
|
- struct pwl_result_data *rgb,
|
|
|
- struct pixel_gamma_point *coeff128,
|
|
|
- struct pwl_float_data *rgb_user,
|
|
|
- const struct hw_x_point *coordinates_x,
|
|
|
- const struct gamma_pixel *axis_x_256,
|
|
|
- uint32_t number_of_points,
|
|
|
- enum surface_pixel_format pixel_format)
|
|
|
-{
|
|
|
-
|
|
|
- const struct pixel_gamma_point *coeff;
|
|
|
- struct pixel_gamma_point *coeff_128 = coeff128;
|
|
|
- uint32_t max_entries = 3 - 1;
|
|
|
- struct pwl_result_data *rgb_resulted = rgb;
|
|
|
-
|
|
|
- uint32_t i = 0;
|
|
|
-
|
|
|
- if (!build_oem_custom_gamma_mapping_coefficients(
|
|
|
- coeff_128, coordinates_x, axis_x_256,
|
|
|
- number_of_points,
|
|
|
- pixel_format))
|
|
|
- return false;
|
|
|
-
|
|
|
- coeff = coeff128;
|
|
|
- max_entries += INPUT_LUT_ENTRIES;
|
|
|
-
|
|
|
- /* TODO: float point case */
|
|
|
-
|
|
|
- while (i <= number_of_points) {
|
|
|
- rgb_resulted->red = calculate_mapped_value(
|
|
|
- rgb_user, coeff, CHANNEL_NAME_RED, max_entries);
|
|
|
- rgb_resulted->green = calculate_mapped_value(
|
|
|
- rgb_user, coeff, CHANNEL_NAME_GREEN, max_entries);
|
|
|
- rgb_resulted->blue = calculate_mapped_value(
|
|
|
- rgb_user, coeff, CHANNEL_NAME_BLUE, max_entries);
|
|
|
-
|
|
|
- ++coeff;
|
|
|
- ++rgb_resulted;
|
|
|
- ++i;
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-static bool map_regamma_hw_to_x_user(
|
|
|
- struct pixel_gamma_point *coeff128,
|
|
|
- struct pwl_float_data *rgb_oem,
|
|
|
- struct pwl_result_data *rgb_resulted,
|
|
|
- struct pwl_float_data *rgb_user,
|
|
|
- struct hw_x_point *coords_x,
|
|
|
- const struct gamma_pixel *axis_x,
|
|
|
- const struct dc_gamma *gamma,
|
|
|
- const struct pwl_float_data_ex *rgb_regamma,
|
|
|
- struct dividers dividers,
|
|
|
- uint32_t hw_points_num,
|
|
|
- const struct core_surface *surface)
|
|
|
-{
|
|
|
- /* setup to spare calculated ideal regamma values */
|
|
|
-
|
|
|
- struct pixel_gamma_point *coeff = coeff128;
|
|
|
-
|
|
|
- struct hw_x_point *coords = coords_x;
|
|
|
-
|
|
|
- copy_rgb_regamma_to_coordinates_x(coords, hw_points_num, rgb_regamma);
|
|
|
-
|
|
|
- return calculate_interpolated_hardware_curve(
|
|
|
- rgb_resulted, coeff, rgb_user, coords, axis_x,
|
|
|
- hw_points_num, surface->public.format);
|
|
|
-}
|
|
|
-
|
|
|
-static void build_new_custom_resulted_curve(
|
|
|
- struct pwl_result_data *rgb_resulted,
|
|
|
- uint32_t hw_points_num)
|
|
|
-{
|
|
|
- struct pwl_result_data *rgb = rgb_resulted;
|
|
|
- struct pwl_result_data *rgb_plus_1 = rgb + 1;
|
|
|
-
|
|
|
- uint32_t i;
|
|
|
-
|
|
|
- i = 0;
|
|
|
-
|
|
|
- while (i != hw_points_num + 1) {
|
|
|
- rgb->red = dal_fixed31_32_clamp(
|
|
|
- rgb->red, dal_fixed31_32_zero,
|
|
|
- dal_fixed31_32_one);
|
|
|
- rgb->green = dal_fixed31_32_clamp(
|
|
|
- rgb->green, dal_fixed31_32_zero,
|
|
|
- dal_fixed31_32_one);
|
|
|
- rgb->blue = dal_fixed31_32_clamp(
|
|
|
- rgb->blue, dal_fixed31_32_zero,
|
|
|
- dal_fixed31_32_one);
|
|
|
-
|
|
|
- ++rgb;
|
|
|
- ++i;
|
|
|
- }
|
|
|
-
|
|
|
- rgb = rgb_resulted;
|
|
|
-
|
|
|
- i = 1;
|
|
|
-
|
|
|
- while (i != hw_points_num + 1) {
|
|
|
- if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
|
|
|
- rgb_plus_1->red = rgb->red;
|
|
|
- if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
|
|
|
- rgb_plus_1->green = rgb->green;
|
|
|
- if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
|
|
|
- rgb_plus_1->blue = rgb->blue;
|
|
|
-
|
|
|
- rgb->delta_red = dal_fixed31_32_sub(
|
|
|
- rgb_plus_1->red,
|
|
|
- rgb->red);
|
|
|
- rgb->delta_green = dal_fixed31_32_sub(
|
|
|
- rgb_plus_1->green,
|
|
|
- rgb->green);
|
|
|
- rgb->delta_blue = dal_fixed31_32_sub(
|
|
|
- rgb_plus_1->blue,
|
|
|
- rgb->blue);
|
|
|
-
|
|
|
- ++rgb_plus_1;
|
|
|
- ++rgb;
|
|
|
- ++i;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void rebuild_curve_configuration_magic(
|
|
|
- struct curve_points *arr_points,
|
|
|
- struct pwl_result_data *rgb_resulted,
|
|
|
- const struct hw_x_point *coordinates_x,
|
|
|
- uint32_t hw_points_num,
|
|
|
- enum dc_transfer_func_predefined tf)
|
|
|
-{
|
|
|
- struct fixed31_32 y_r;
|
|
|
- struct fixed31_32 y_g;
|
|
|
- struct fixed31_32 y_b;
|
|
|
-
|
|
|
- struct fixed31_32 y1_min;
|
|
|
- struct fixed31_32 y3_max;
|
|
|
-
|
|
|
- y_r = rgb_resulted[0].red;
|
|
|
- y_g = rgb_resulted[0].green;
|
|
|
- y_b = rgb_resulted[0].blue;
|
|
|
-
|
|
|
- y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
|
|
|
-
|
|
|
- arr_points[0].x = coordinates_x[0].adjusted_x;
|
|
|
- arr_points[0].y = y1_min;
|
|
|
- arr_points[0].slope = dal_fixed31_32_div(
|
|
|
- arr_points[0].y,
|
|
|
- arr_points[0].x);
|
|
|
-
|
|
|
- /* this should be cleaned up as it's confusing my understanding (KK) is
|
|
|
- * that REGAMMA_CNTLA_EXP_REGION_END is the X value for the region end
|
|
|
- * REGAMMA_CNTLA_EXP_REGION_END_BASE is Y value for the above X
|
|
|
- * REGAMMA_CNTLA_EXP_REGION_END_SLOPE is the slope beyond (X,Y) above
|
|
|
- * currently when programming REGION_END = m_arrPoints[1].x,
|
|
|
- * REGION_END_BASE = m_arrPoints[1].y, REGION_END_SLOPE=1
|
|
|
- * we don't use m_arrPoints[2] at all after this function,
|
|
|
- * and its purpose isn't clear to me
|
|
|
- */
|
|
|
- arr_points[1].x = coordinates_x[hw_points_num].adjusted_x;
|
|
|
- arr_points[2].x = coordinates_x[hw_points_num].adjusted_x;
|
|
|
-
|
|
|
- y_r = rgb_resulted[hw_points_num].red;
|
|
|
- y_g = rgb_resulted[hw_points_num].green;
|
|
|
- y_b = rgb_resulted[hw_points_num].blue;
|
|
|
-
|
|
|
- /* see comment above, m_arrPoints[1].y should be the Y value for the
|
|
|
- * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
|
|
|
- */
|
|
|
- y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
|
|
|
-
|
|
|
- arr_points[1].y = y3_max;
|
|
|
- arr_points[2].y = y3_max;
|
|
|
-
|
|
|
- arr_points[2].slope = dal_fixed31_32_zero;
|
|
|
-
|
|
|
- /* for PQ, we want to have a straight line from last HW X point, and the
|
|
|
- * slope to be such that we hit 1.0 at 10000 nits.
|
|
|
- */
|
|
|
- if (tf == TRANSFER_FUNCTION_PQ) {
|
|
|
- const struct fixed31_32 end_value =
|
|
|
- dal_fixed31_32_from_int(125);
|
|
|
-
|
|
|
- arr_points[2].slope = dal_fixed31_32_div(
|
|
|
- dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
|
|
|
- dal_fixed31_32_sub(end_value, arr_points[1].x));
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static bool convert_to_custom_float_format(
|
|
|
- struct fixed31_32 value,
|
|
|
- const struct custom_float_format *format,
|
|
|
- uint32_t *result)
|
|
|
-{
|
|
|
- uint32_t mantissa;
|
|
|
- uint32_t exponenta;
|
|
|
- bool negative;
|
|
|
-
|
|
|
- return build_custom_float(
|
|
|
- value, format, &negative, &mantissa, &exponenta) &&
|
|
|
- setup_custom_float(
|
|
|
- format, negative, mantissa, exponenta, result);
|
|
|
-}
|
|
|
-
|
|
|
-static bool convert_to_custom_float(
|
|
|
- struct pwl_result_data *rgb_resulted,
|
|
|
- struct curve_points *arr_points,
|
|
|
- uint32_t hw_points_num)
|
|
|
-{
|
|
|
- struct custom_float_format fmt;
|
|
|
-
|
|
|
- struct pwl_result_data *rgb = rgb_resulted;
|
|
|
-
|
|
|
- uint32_t i = 0;
|
|
|
-
|
|
|
- fmt.exponenta_bits = 6;
|
|
|
- fmt.mantissa_bits = 12;
|
|
|
- fmt.sign = true;
|
|
|
-
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- arr_points[0].x,
|
|
|
- &fmt,
|
|
|
- &arr_points[0].custom_float_x)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- arr_points[0].offset,
|
|
|
- &fmt,
|
|
|
- &arr_points[0].custom_float_offset)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- arr_points[0].slope,
|
|
|
- &fmt,
|
|
|
- &arr_points[0].custom_float_slope)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- fmt.mantissa_bits = 10;
|
|
|
- fmt.sign = false;
|
|
|
-
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- arr_points[1].x,
|
|
|
- &fmt,
|
|
|
- &arr_points[1].custom_float_x)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- arr_points[1].y,
|
|
|
- &fmt,
|
|
|
- &arr_points[1].custom_float_y)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- arr_points[2].slope,
|
|
|
- &fmt,
|
|
|
- &arr_points[2].custom_float_slope)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- fmt.mantissa_bits = 12;
|
|
|
- fmt.sign = true;
|
|
|
-
|
|
|
- while (i != hw_points_num) {
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- rgb->red,
|
|
|
- &fmt,
|
|
|
- &rgb->red_reg)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- rgb->green,
|
|
|
- &fmt,
|
|
|
- &rgb->green_reg)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- rgb->blue,
|
|
|
- &fmt,
|
|
|
- &rgb->blue_reg)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- rgb->delta_red,
|
|
|
- &fmt,
|
|
|
- &rgb->delta_red_reg)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- rgb->delta_green,
|
|
|
- &fmt,
|
|
|
- &rgb->delta_green_reg)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (!convert_to_custom_float_format(
|
|
|
- rgb->delta_blue,
|
|
|
- &fmt,
|
|
|
- &rgb->delta_blue_reg)) {
|
|
|
- BREAK_TO_DEBUGGER();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- ++rgb;
|
|
|
- ++i;
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-bool calculate_regamma_params(struct pwl_params *params,
|
|
|
- const struct core_gamma *ramp,
|
|
|
- const struct core_surface *surface,
|
|
|
- const struct core_stream *stream)
|
|
|
-{
|
|
|
- struct gamma_curve *arr_curve_points = params->arr_curve_points;
|
|
|
- struct curve_points *arr_points = params->arr_points;
|
|
|
- struct pwl_result_data *rgb_resulted = params->rgb_resulted;
|
|
|
- struct dividers dividers;
|
|
|
-
|
|
|
- struct hw_x_point *coordinates_x = NULL;
|
|
|
- struct pwl_float_data *rgb_user = NULL ;
|
|
|
- struct pwl_float_data_ex *rgb_regamma = NULL;
|
|
|
- struct pwl_float_data *rgb_oem = NULL;
|
|
|
- struct gamma_pixel *axix_x_256 = NULL;
|
|
|
- struct pixel_gamma_point *coeff128_oem = NULL;
|
|
|
- struct pixel_gamma_point *coeff128 = NULL;
|
|
|
-
|
|
|
- enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB;
|
|
|
-
|
|
|
- bool ret = false;
|
|
|
-
|
|
|
- coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3));
|
|
|
- if (!coordinates_x)
|
|
|
- goto coordinates_x_alloc_fail;
|
|
|
- rgb_user = dm_alloc(sizeof(*rgb_user) * (TRANSFER_FUNC_POINTS + 3));
|
|
|
- if (!rgb_user)
|
|
|
- goto rgb_user_alloc_fail;
|
|
|
- rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3));
|
|
|
- if (!rgb_regamma)
|
|
|
- goto rgb_regamma_alloc_fail;
|
|
|
- rgb_oem = dm_alloc(sizeof(*rgb_oem) * (TRANSFER_FUNC_POINTS + 3));
|
|
|
- if (!rgb_oem)
|
|
|
- goto rgb_oem_alloc_fail;
|
|
|
- axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3));
|
|
|
- if (!axix_x_256)
|
|
|
- goto axix_x_256_alloc_fail;
|
|
|
- coeff128_oem = dm_alloc(sizeof(*coeff128_oem) * (256 + 3));
|
|
|
- if (!coeff128_oem)
|
|
|
- goto coeff128_oem_alloc_fail;
|
|
|
- coeff128 = dm_alloc(sizeof(*coeff128) * (256 + 3));
|
|
|
- if (!coeff128)
|
|
|
- goto coeff128_alloc_fail;
|
|
|
-
|
|
|
- dividers.divider1 = dal_fixed31_32_from_fraction(3, 2);
|
|
|
- dividers.divider2 = dal_fixed31_32_from_int(2);
|
|
|
- dividers.divider3 = dal_fixed31_32_from_fraction(5, 2);
|
|
|
-
|
|
|
- if (stream->public.out_transfer_func)
|
|
|
- tf = stream->public.out_transfer_func->tf;
|
|
|
-
|
|
|
- build_evenly_distributed_points(
|
|
|
- axix_x_256,
|
|
|
- 256,
|
|
|
- dal_fixed31_32_one,
|
|
|
- dividers);
|
|
|
-
|
|
|
- scale_gamma(rgb_user, ramp, dividers);
|
|
|
-
|
|
|
- if (tf == TRANSFER_FUNCTION_PQ) {
|
|
|
- setup_distribution_points_pq(arr_curve_points, arr_points,
|
|
|
- ¶ms->hw_points_num, coordinates_x,
|
|
|
- surface->public.format);
|
|
|
- build_regamma_curve_pq(rgb_regamma, rgb_oem, coeff128_oem,
|
|
|
- ramp, surface, params->hw_points_num,
|
|
|
- coordinates_x, axix_x_256, dividers);
|
|
|
- } else {
|
|
|
- setup_distribution_points(arr_curve_points, arr_points,
|
|
|
- ¶ms->hw_points_num, coordinates_x);
|
|
|
- build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem,
|
|
|
- ramp, surface, params->hw_points_num,
|
|
|
- coordinates_x, axix_x_256, dividers);
|
|
|
- }
|
|
|
-
|
|
|
- map_regamma_hw_to_x_user(coeff128, rgb_oem, rgb_resulted, rgb_user,
|
|
|
- coordinates_x, axix_x_256, &ramp->public, rgb_regamma,
|
|
|
- dividers, params->hw_points_num, surface);
|
|
|
-
|
|
|
- build_new_custom_resulted_curve(rgb_resulted, params->hw_points_num);
|
|
|
-
|
|
|
- rebuild_curve_configuration_magic(
|
|
|
- arr_points,
|
|
|
- rgb_resulted,
|
|
|
- coordinates_x,
|
|
|
- params->hw_points_num,
|
|
|
- tf);
|
|
|
-
|
|
|
- convert_to_custom_float(rgb_resulted, arr_points,
|
|
|
- params->hw_points_num);
|
|
|
-
|
|
|
- ret = true;
|
|
|
-
|
|
|
- dm_free(coeff128);
|
|
|
-coeff128_alloc_fail:
|
|
|
- dm_free(coeff128_oem);
|
|
|
-coeff128_oem_alloc_fail:
|
|
|
- dm_free(axix_x_256);
|
|
|
-axix_x_256_alloc_fail:
|
|
|
- dm_free(rgb_oem);
|
|
|
-rgb_oem_alloc_fail:
|
|
|
- dm_free(rgb_regamma);
|
|
|
-rgb_regamma_alloc_fail:
|
|
|
- dm_free(rgb_user);
|
|
|
-rgb_user_alloc_fail:
|
|
|
- dm_free(coordinates_x);
|
|
|
-coordinates_x_alloc_fail:
|
|
|
- return ret;
|
|
|
-
|
|
|
-}
|
|
|
-
|