• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2022 Advanced Micro Devices, Inc.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a
4  * copy of this software and associated documentation files (the "Software"),
5  * to deal in the Software without restriction, including without limitation
6  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7  * and/or sell copies of the Software, and to permit persons to whom the
8  * Software is furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
16  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
17  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
19  * OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * Authors: AMD
22  *
23  */
24 
25 #include "shaper_builder.h"
26 #include "custom_fp16.h"
27 #include "fixed31_32.h"
28 
29 struct x_axis_config {
30     int offset;
31     int segments_num;
32 };
33 
34 struct point_config {
35     int custom_float_x;
36     int custom_float_y;
37     int custom_float_slope;
38 };
39 
40 struct curve_points32 {
41     struct point_config red;
42     struct point_config green;
43     struct point_config blue;
44 };
45 
46 struct lut_point {
47     int red;
48     int green;
49     int blue;
50     int delta_red;
51     int delta_green;
52     int delta_blue;
53 };
54 
55 struct pwl_parameter2 {
56     struct x_axis_config  arr_curve_points[34];
57     struct curve_points32 corner_points[2];
58     struct lut_point      rgb_resulted[256];
59     int                   hw_points_num;
60 };
61 
62 struct shaper_setup_out {
63     int exp_begin_raw;
64     int exp_end_raw;
65     int begin_custom_1_6_12;
66     int end_custom_0_6_10;
67     int end_base_fixed_0_14;
68 };
69 
calculate_shaper_properties_const_hdr_mult(const struct vpe_shaper_setup_in * shaper_in,struct shaper_setup_out * shaper_out)70 static bool calculate_shaper_properties_const_hdr_mult(
71     const struct vpe_shaper_setup_in *shaper_in, struct shaper_setup_out *shaper_out)
72 {
73     double                          x;
74     struct vpe_custom_float_format2 fmt;
75     struct vpe_custom_float_value2  custom_float;
76     int                             num_exp;
77 
78     bool   ret     = false;
79     int    isize   = 1 << 14;
80     double divider = isize - 1;
81     double x_double_begin;
82 
83     double multiplyer = shaper_in->source_luminance / 10000.0 * shaper_in->shaper_in_max;
84 
85     fmt.flags.Uint      = 0;
86     fmt.flags.bits.sign = 1;
87     fmt.mantissaBits    = 12;
88     fmt.exponentaBits   = 6;
89 
90     x = pow(1.0 / divider, 2.2) * multiplyer;
91     if (!vpe_convert_to_custom_float_ex_generic(x, &fmt, &custom_float))
92         goto release;
93     shaper_out->exp_begin_raw = custom_float.exponenta;
94 
95     if (!vpe_from_1_6_12_to_double(false, custom_float.exponenta, 0, &x_double_begin))
96         goto release;
97 
98     if (!vpe_convert_to_custom_float_generic(
99             x_double_begin, &fmt, &shaper_out->begin_custom_1_6_12))
100         goto release;
101 
102     fmt.flags.bits.sign = 0;
103     fmt.mantissaBits    = 10;
104     if (!vpe_convert_to_custom_float_ex_generic(multiplyer, &fmt, &custom_float))
105         goto release;
106     shaper_out->exp_end_raw = custom_float.exponenta;
107     if (!vpe_convert_to_custom_float_generic(multiplyer, &fmt, &shaper_out->end_custom_0_6_10))
108         goto release;
109     shaper_out->end_base_fixed_0_14 = isize - 1;
110     num_exp                         = shaper_out->exp_end_raw - shaper_out->exp_begin_raw + 1;
111     if (num_exp > 34)
112         goto release;
113     ret = true;
114 release:
115     return ret;
116 }
117 
calculate_shaper_properties_variable_hdr_mult(const struct vpe_shaper_setup_in * shaper_in,struct shaper_setup_out * shaper_out)118 static bool calculate_shaper_properties_variable_hdr_mult(
119     const struct vpe_shaper_setup_in *shaper_in, struct shaper_setup_out *shaper_out)
120 {
121     struct vpe_custom_float_format2 fmt;
122     struct vpe_custom_float_value2  custom_float;
123     int                             num_exp;
124 
125     bool   ret            = false;
126     int    isize          = 1 << 14;
127     double divider        = isize - 1;
128     double x_double_begin = 0;
129 
130     fmt.flags.Uint    = 0;
131     fmt.exponentaBits = 6;
132     fmt.mantissaBits  = 10;
133     if (!vpe_convert_to_custom_float_ex_generic(shaper_in->shaper_in_max, &fmt, &custom_float))
134         goto release;
135 
136     if (!vpe_convert_to_custom_float_generic(
137             shaper_in->shaper_in_max, &fmt, &shaper_out->end_custom_0_6_10))
138         goto release;
139 
140     shaper_out->exp_end_raw   = custom_float.exponenta;
141     shaper_out->exp_begin_raw = shaper_out->exp_end_raw - 33;
142 
143     shaper_out->end_base_fixed_0_14 = isize - 1;
144 
145     if (!vpe_from_1_6_12_to_double(false, shaper_out->exp_begin_raw, 0, &x_double_begin))
146         goto release;
147 
148     fmt.mantissaBits    = 12;
149     fmt.flags.bits.sign = 1;
150 
151     if (!vpe_convert_to_custom_float_generic(
152             x_double_begin, &fmt, &shaper_out->begin_custom_1_6_12))
153         goto release;
154 
155     num_exp = shaper_out->exp_end_raw - shaper_out->exp_begin_raw + 1;
156     if (num_exp > 34)
157         goto release;
158     ret = true;
159 release:
160     return ret;
161 }
162 
build_shaper_2_2_segments_distribution(int num_regions,int * arr_segments)163 static int build_shaper_2_2_segments_distribution(int num_regions, int *arr_segments)
164 {
165     int       i;
166     int       counter;
167     int       num_segments                = 0;
168     int       num_segments_total          = 0;
169     const int proposed_2_2_distribution[] = {5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 3, 2, 2, 1, 1, 1, 0, 0,
170         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
171     int proposed_regions = ARRAY_SIZE(proposed_2_2_distribution);
172 
173     if (proposed_regions < num_regions)
174         goto release;
175     counter = 0;
176 
177     for (i = num_regions - 1; i >= 0; i--) {
178         arr_segments[counter] = proposed_2_2_distribution[i];
179         num_segments += 1 << proposed_2_2_distribution[i];
180         counter++;
181     }
182 release:
183     return num_segments;
184 }
185 
vpe_build_shaper(const struct vpe_shaper_setup_in * shaper_in,struct pwl_params * shaper)186 enum vpe_status vpe_build_shaper(
187     const struct vpe_shaper_setup_in *shaper_in, struct pwl_params *shaper)
188 {
189     enum vpe_status ret = VPE_STATUS_ERROR;
190 
191     int                     num_points = 0;
192     int                     arr_regions[34];
193     struct shaper_setup_out shaper_params;
194     int                     i, j;
195     int                     num_exp;
196 
197     unsigned int exp;
198     double       x, delta_segments;
199     int          lut_counter = 0;
200     int          segments_current;
201     int          segments_offset;
202 
203     unsigned int decimalBits = 14;
204 
205     unsigned int mask    = (1 << decimalBits) - 1;
206     double       d_norm  = mask;
207     double       divider = shaper_in->shaper_in_max;
208 
209     if (shaper_in->use_const_hdr_mult &&
210         !calculate_shaper_properties_const_hdr_mult(shaper_in, &shaper_params))
211         goto release;
212     else if (!calculate_shaper_properties_variable_hdr_mult(shaper_in, &shaper_params))
213         goto release;
214 
215     exp = shaper_params.exp_begin_raw;
216 
217     num_exp    = shaper_params.exp_end_raw - shaper_params.exp_begin_raw + 1;
218     num_points = build_shaper_2_2_segments_distribution(num_exp, arr_regions);
219 
220     segments_offset = 0;
221 
222     for (i = 0; i < num_exp; i++) {
223         segments_current                         = 1 << arr_regions[i];
224         shaper->arr_curve_points[i].segments_num = arr_regions[i];
225         shaper->arr_curve_points[i].offset       = segments_offset;
226         segments_offset                          = segments_offset + segments_current;
227         if (!vpe_from_1_6_12_to_double(false, exp, 0, &x))
228             goto release;
229         x /= divider;
230         shaper->rgb_resulted[lut_counter].red_reg =
231             vpe_to_fixed_point(decimalBits, x, mask, d_norm);
232         shaper->rgb_resulted[lut_counter].green_reg = shaper->rgb_resulted[lut_counter].red_reg;
233         shaper->rgb_resulted[lut_counter].blue_reg  = shaper->rgb_resulted[lut_counter].red_reg;
234 
235         delta_segments = x / segments_current;
236         lut_counter++;
237         for (j = 0; j < segments_current - 1; j++) {
238             x += delta_segments;
239             shaper->rgb_resulted[lut_counter].red_reg =
240                 vpe_to_fixed_point(decimalBits, x, mask, d_norm);
241             shaper->rgb_resulted[lut_counter].green_reg = shaper->rgb_resulted[lut_counter].red_reg;
242             shaper->rgb_resulted[lut_counter].blue_reg  = shaper->rgb_resulted[lut_counter].red_reg;
243             lut_counter++;
244         }
245         exp++;
246     }
247 
248     shaper->corner_points[0].red.custom_float_x   = shaper_params.begin_custom_1_6_12;
249     shaper->corner_points[0].green.custom_float_x = shaper->corner_points[0].red.custom_float_x;
250     shaper->corner_points[0].blue.custom_float_x  = shaper->corner_points[0].red.custom_float_x;
251 
252     shaper->corner_points[1].red.custom_float_x   = shaper_params.end_custom_0_6_10;
253     shaper->corner_points[1].green.custom_float_x = shaper->corner_points[1].red.custom_float_x;
254     shaper->corner_points[1].blue.custom_float_x  = shaper->corner_points[1].red.custom_float_x;
255 
256     shaper->corner_points[1].red.custom_float_y   = shaper_params.end_base_fixed_0_14;
257     shaper->corner_points[1].green.custom_float_y = shaper->corner_points[1].red.custom_float_y;
258     shaper->corner_points[1].blue.custom_float_y  = shaper->corner_points[1].red.custom_float_y;
259 
260     for (i = 1; i < num_points; i++) {
261         shaper->rgb_resulted[i - 1].delta_red_reg =
262             shaper->rgb_resulted[i].red_reg - shaper->rgb_resulted[i - 1].red_reg;
263         shaper->rgb_resulted[i - 1].delta_green_reg = shaper->rgb_resulted[i - 1].delta_red_reg;
264         shaper->rgb_resulted[i - 1].delta_blue_reg  = shaper->rgb_resulted[i - 1].delta_red_reg;
265     }
266 
267     shaper->hw_points_num = num_points;
268     ret                   = VPE_STATUS_OK;
269 
270 release:
271     return ret;
272 }
273