xref: /aosp_15_r20/external/mesa3d/src/amd/vpelib/src/core/shaper_builder.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 shaper_setup_out {
30     int exp_begin_raw;
31     int exp_end_raw;
32     int begin_custom_1_6_12;
33     int end_custom_0_6_10;
34     int end_base_fixed_0_14;
35 };
36 
calculate_shaper_properties_const_hdr_mult(const struct vpe_shaper_setup_in * shaper_in,struct shaper_setup_out * shaper_out)37 static bool calculate_shaper_properties_const_hdr_mult(
38     const struct vpe_shaper_setup_in *shaper_in, struct shaper_setup_out *shaper_out)
39 {
40     double                          x;
41     struct vpe_custom_float_format2 fmt;
42     struct vpe_custom_float_value2  custom_float;
43     int                             num_exp;
44 
45     bool   ret     = false;
46     int    isize   = 1 << 14;
47     double divider = isize - 1;
48     double x_double_begin;
49 
50     double multiplyer = shaper_in->source_luminance / 10000.0 * shaper_in->shaper_in_max;
51 
52     fmt.flags.Uint      = 0;
53     fmt.flags.bits.sign = 1;
54     fmt.mantissaBits    = 12;
55     fmt.exponentaBits   = 6;
56 
57     x = pow(1.0 / divider, 2.2) * multiplyer;
58     if (!vpe_convert_to_custom_float_ex_generic(x, &fmt, &custom_float))
59         goto release;
60     shaper_out->exp_begin_raw = custom_float.exponenta;
61 
62     if (!vpe_from_1_6_12_to_double(false, custom_float.exponenta, 0, &x_double_begin))
63         goto release;
64 
65     if (!vpe_convert_to_custom_float_generic(
66             x_double_begin, &fmt, &shaper_out->begin_custom_1_6_12))
67         goto release;
68 
69     fmt.flags.bits.sign = 0;
70     fmt.mantissaBits    = 10;
71     if (!vpe_convert_to_custom_float_ex_generic(multiplyer, &fmt, &custom_float))
72         goto release;
73     shaper_out->exp_end_raw = custom_float.exponenta;
74     if (!vpe_convert_to_custom_float_generic(multiplyer, &fmt, &shaper_out->end_custom_0_6_10))
75         goto release;
76     shaper_out->end_base_fixed_0_14 = isize - 1;
77     num_exp                         = shaper_out->exp_end_raw - shaper_out->exp_begin_raw + 1;
78     if (num_exp > 34)
79         goto release;
80     ret = true;
81 release:
82     return ret;
83 }
84 
calculate_shaper_properties_variable_hdr_mult(const struct vpe_shaper_setup_in * shaper_in,struct shaper_setup_out * shaper_out)85 static bool calculate_shaper_properties_variable_hdr_mult(
86     const struct vpe_shaper_setup_in *shaper_in, struct shaper_setup_out *shaper_out)
87 {
88     struct vpe_custom_float_format2 fmt;
89     struct vpe_custom_float_value2  custom_float;
90     int                             num_exp;
91 
92     bool   ret            = false;
93     int    isize          = 1 << 14;
94     double divider        = isize - 1;
95     double x_double_begin = 0;
96 
97     fmt.flags.Uint    = 0;
98     fmt.exponentaBits = 6;
99     fmt.mantissaBits  = 10;
100     if (!vpe_convert_to_custom_float_ex_generic(shaper_in->shaper_in_max, &fmt, &custom_float))
101         goto release;
102 
103     if (!vpe_convert_to_custom_float_generic(
104             shaper_in->shaper_in_max, &fmt, &shaper_out->end_custom_0_6_10))
105         goto release;
106 
107     shaper_out->exp_end_raw   = custom_float.exponenta;
108     shaper_out->exp_begin_raw = shaper_out->exp_end_raw - 33;
109 
110     shaper_out->end_base_fixed_0_14 = isize - 1;
111 
112     if (!vpe_from_1_6_12_to_double(false, shaper_out->exp_begin_raw, 0, &x_double_begin))
113         goto release;
114 
115     fmt.mantissaBits    = 12;
116     fmt.flags.bits.sign = 1;
117 
118     if (!vpe_convert_to_custom_float_generic(
119             x_double_begin, &fmt, &shaper_out->begin_custom_1_6_12))
120         goto release;
121 
122     num_exp = shaper_out->exp_end_raw - shaper_out->exp_begin_raw + 1;
123     if (num_exp > 34)
124         goto release;
125     ret = true;
126 release:
127     return ret;
128 }
129 
build_shaper_2_2_segments_distribution(int num_regions,int * arr_segments)130 static int build_shaper_2_2_segments_distribution(int num_regions, int *arr_segments)
131 {
132     int       i;
133     int       counter;
134     int       num_segments                = 0;
135     int       num_segments_total          = 0;
136     const int proposed_2_2_distribution[] = {5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 3, 2, 2, 1, 1, 1, 0, 0,
137         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
138     int proposed_regions = ARRAY_SIZE(proposed_2_2_distribution);
139 
140     if (proposed_regions < num_regions)
141         goto release;
142     counter = 0;
143 
144     for (i = num_regions - 1; i >= 0; i--) {
145         arr_segments[counter] = proposed_2_2_distribution[i];
146         num_segments += 1 << proposed_2_2_distribution[i];
147         counter++;
148     }
149 release:
150     return num_segments;
151 }
152 
vpe_build_shaper(const struct vpe_shaper_setup_in * shaper_in,struct pwl_params * shaper)153 enum vpe_status vpe_build_shaper(
154     const struct vpe_shaper_setup_in *shaper_in, struct pwl_params *shaper)
155 {
156     enum vpe_status ret = VPE_STATUS_ERROR;
157 
158     int                     num_points = 0;
159     int                     arr_regions[34];
160     struct shaper_setup_out shaper_params;
161     int                     i, j;
162     int                     num_exp;
163 
164     unsigned int exp;
165     double       x, delta_segments;
166     int          lut_counter = 0;
167     int          segments_current;
168     int          segments_offset;
169 
170     unsigned int decimalBits = 14;
171 
172     unsigned int mask    = (1 << decimalBits) - 1;
173     double       d_norm  = mask;
174     double       divider = shaper_in->shaper_in_max;
175 
176     if (shaper_in->use_const_hdr_mult &&
177         !calculate_shaper_properties_const_hdr_mult(shaper_in, &shaper_params))
178         goto release;
179     else if (!calculate_shaper_properties_variable_hdr_mult(shaper_in, &shaper_params))
180         goto release;
181 
182     exp = shaper_params.exp_begin_raw;
183 
184     num_exp    = shaper_params.exp_end_raw - shaper_params.exp_begin_raw + 1;
185     num_points = build_shaper_2_2_segments_distribution(num_exp, arr_regions);
186 
187     segments_offset = 0;
188 
189     for (i = 0; i < num_exp; i++) {
190         segments_current                         = 1 << arr_regions[i];
191         shaper->arr_curve_points[i].segments_num = arr_regions[i];
192         shaper->arr_curve_points[i].offset       = segments_offset;
193         segments_offset                          = segments_offset + segments_current;
194         if (!vpe_from_1_6_12_to_double(false, exp, 0, &x))
195             goto release;
196         x /= divider;
197         shaper->rgb_resulted[lut_counter].red_reg =
198             vpe_to_fixed_point(decimalBits, x, mask, d_norm);
199         shaper->rgb_resulted[lut_counter].green_reg = shaper->rgb_resulted[lut_counter].red_reg;
200         shaper->rgb_resulted[lut_counter].blue_reg  = shaper->rgb_resulted[lut_counter].red_reg;
201 
202         delta_segments = x / segments_current;
203         lut_counter++;
204         for (j = 0; j < segments_current - 1; j++) {
205             x += delta_segments;
206             shaper->rgb_resulted[lut_counter].red_reg =
207                 vpe_to_fixed_point(decimalBits, x, mask, d_norm);
208             shaper->rgb_resulted[lut_counter].green_reg = shaper->rgb_resulted[lut_counter].red_reg;
209             shaper->rgb_resulted[lut_counter].blue_reg  = shaper->rgb_resulted[lut_counter].red_reg;
210             lut_counter++;
211         }
212         exp++;
213     }
214 
215     shaper->corner_points[0].red.custom_float_x   = shaper_params.begin_custom_1_6_12;
216     shaper->corner_points[0].green.custom_float_x = shaper->corner_points[0].red.custom_float_x;
217     shaper->corner_points[0].blue.custom_float_x  = shaper->corner_points[0].red.custom_float_x;
218 
219     shaper->corner_points[1].red.custom_float_x   = shaper_params.end_custom_0_6_10;
220     shaper->corner_points[1].green.custom_float_x = shaper->corner_points[1].red.custom_float_x;
221     shaper->corner_points[1].blue.custom_float_x  = shaper->corner_points[1].red.custom_float_x;
222 
223     shaper->corner_points[1].red.custom_float_y   = shaper_params.end_base_fixed_0_14;
224     shaper->corner_points[1].green.custom_float_y = shaper->corner_points[1].red.custom_float_y;
225     shaper->corner_points[1].blue.custom_float_y  = shaper->corner_points[1].red.custom_float_y;
226 
227     for (i = 1; i < num_points; i++) {
228         shaper->rgb_resulted[i - 1].delta_red_reg =
229             shaper->rgb_resulted[i].red_reg - shaper->rgb_resulted[i - 1].red_reg;
230         shaper->rgb_resulted[i - 1].delta_green_reg = shaper->rgb_resulted[i - 1].delta_red_reg;
231         shaper->rgb_resulted[i - 1].delta_blue_reg  = shaper->rgb_resulted[i - 1].delta_red_reg;
232     }
233 
234     shaper->hw_points_num = num_points;
235     ret                   = VPE_STATUS_OK;
236 
237 release:
238     return ret;
239 }
240