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 #include "color_gamut.h"
25
26 #define DIVIDER 10000
27
28 struct gamut_space_entry {
29 unsigned int redX;
30 unsigned int redY;
31 unsigned int greenX;
32 unsigned int greenY;
33 unsigned int blueX;
34 unsigned int blueY;
35
36 int a0;
37 int a1;
38 int a2;
39 int a3;
40 int gamma;
41 };
42
43 struct white_point_coodinates_entry {
44 unsigned int temperature;
45 unsigned int whiteX;
46 unsigned int whiteY;
47 };
48
49 static const struct gamut_space_entry predefined_gamuts[] = {
50 /* x_red y_red x_gr y_gr x_blue y_blue a0 a1 a2 a3 gamma
51 */
52 [gamut_type_bt709] = {6400, 3300, 3000, 6000, 1500, 600, 180000, 4500, 99, 99, 2222},
53 [gamut_type_bt601] = {6300, 3400, 3100, 5950, 1550, 700, 180000, 4500, 99, 99, 2200},
54 [gamut_type_adobe_rgb] = {6400, 3300, 2100, 7100, 1500, 600, 180000, 4500, 99, 99, 2200},
55 [gamut_type_srgb] = {6400, 3300, 3000, 6000, 1500, 600, 31308, 12920, 55, 55, 2400},
56 [gamut_type_bt2020] = {7080, 2920, 1700, 7970, 1310, 460, 180000, 4500, 99, 99, 2200},
57 [gamut_type_dcip3] = {6800, 3200, 2650, 6900, 1500, 600, 0, 0, 0, 0, 2600}};
58
59 static const struct white_point_coodinates_entry predefined_white_points[] = {
60 [white_point_type_5000k_horizon] = {5000, 3473, 3561},
61 [white_point_type_6500k_noon] = {6500, 3127, 3290},
62 [white_point_type_7500k_north_sky] = {7500, 3022, 3129},
63 [white_point_type_9300k] = {9300, 2866, 2950}};
64
65 struct gamut_src_dst_matrix {
66 struct fixed31_32 rgbCoeffDst[9];
67 struct fixed31_32 whiteCoeffDst[3];
68 struct fixed31_32 rgbCoeffSrc[9];
69 struct fixed31_32 whiteCoeffSrc[3];
70 struct fixed31_32 xyzMatrix[9];
71 struct fixed31_32 xyzOffset[3];
72 struct fixed31_32 bradford[9];
73 };
74
75 struct gamut_calculation_matrix {
76 struct fixed31_32 MTransposed[9];
77 struct fixed31_32 XYZtoRGB_Custom[9];
78 struct fixed31_32 XYZtoRGB_Ref[9];
79 struct fixed31_32 RGBtoXYZ_Final[9];
80
81 struct fixed31_32 MResult[9];
82 struct fixed31_32 fXYZofWhiteRef[9];
83 struct fixed31_32 fXYZofRGBRef[9];
84 struct fixed31_32 fXYZofRGBRefCopy[9];
85 struct fixed31_32 MResultOffset[3];
86 };
87
color_find_predefined_gamut(struct color_space_coordinates * out_gamut,enum predefined_gamut_type type)88 static void color_find_predefined_gamut(
89 struct color_space_coordinates *out_gamut, enum predefined_gamut_type type)
90 {
91 out_gamut->redX = predefined_gamuts[type].redX;
92 out_gamut->redY = predefined_gamuts[type].redY;
93 out_gamut->greenX = predefined_gamuts[type].greenX;
94 out_gamut->greenY = predefined_gamuts[type].greenY;
95 out_gamut->blueX = predefined_gamuts[type].blueX;
96 out_gamut->blueY = predefined_gamuts[type].blueY;
97 }
98
color_find_predefined_white_point(struct color_space_coordinates * out_white_point,enum predefined_white_point_type type)99 static void color_find_predefined_white_point(
100 struct color_space_coordinates *out_white_point, enum predefined_white_point_type type)
101 {
102 out_white_point->whiteX = predefined_white_points[type].whiteX;
103 out_white_point->whiteY = predefined_white_points[type].whiteY;
104 }
105
color_transpose_matrix(const struct fixed31_32 * M,unsigned int Rows,unsigned int Cols,struct fixed31_32 * MTransposed)106 static void color_transpose_matrix(const struct fixed31_32 *M, unsigned int Rows, unsigned int Cols,
107 struct fixed31_32 *MTransposed)
108 {
109 unsigned int i, j;
110
111 for (i = 0; i < Rows; i++) {
112 for (j = 0; j < Cols; j++)
113 MTransposed[(j * Rows) + i] = M[(i * Cols) + j];
114 }
115 }
116
color_multiply_matrices(struct fixed31_32 * mResult,const struct fixed31_32 * M1,const struct fixed31_32 * M2,unsigned int Rows1,unsigned int Cols1,unsigned int Cols2)117 static void color_multiply_matrices(struct fixed31_32 *mResult, const struct fixed31_32 *M1,
118 const struct fixed31_32 *M2, unsigned int Rows1, unsigned int Cols1, unsigned int Cols2)
119 {
120 unsigned int i, j, k;
121
122 for (i = 0; i < Rows1; i++) {
123 for (j = 0; j < Cols2; j++) {
124 mResult[(i * Cols2) + j] = vpe_fixpt_zero;
125 for (k = 0; k < Cols1; k++)
126 mResult[(i * Cols2) + j] = vpe_fixpt_add(mResult[(i * Cols2) + j],
127 vpe_fixpt_mul(M1[(i * Cols1) + k], M2[(k * Cols2) + j]));
128 }
129 }
130 }
131
color_space_to_predefined_gamut_types(enum color_space color_space)132 static enum predefined_gamut_type color_space_to_predefined_gamut_types(
133 enum color_space color_space)
134 {
135 switch (color_space) {
136 case COLOR_SPACE_YCBCR_JFIF:
137 case COLOR_SPACE_RGB_JFIF:
138 case COLOR_SPACE_YCBCR709:
139 case COLOR_SPACE_YCBCR709_LIMITED:
140 return gamut_type_bt709;
141 case COLOR_SPACE_YCBCR601:
142 case COLOR_SPACE_YCBCR601_LIMITED:
143 case COLOR_SPACE_RGB601:
144 case COLOR_SPACE_RGB601_LIMITED:
145 return gamut_type_bt601;
146 case COLOR_SPACE_SRGB:
147 case COLOR_SPACE_SRGB_LIMITED:
148 case COLOR_SPACE_MSREF_SCRGB:
149 return gamut_type_srgb;
150 case COLOR_SPACE_2020_RGB_FULLRANGE:
151 case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
152 case COLOR_SPACE_2020_YCBCR:
153 case COLOR_SPACE_2020_YCBCR_LIMITED:
154 return gamut_type_bt2020;
155 default:
156 VPE_ASSERT(0);
157 return gamut_type_unknown;
158 }
159 }
160
find_predefined_gamut_and_white_point(struct vpe_priv * vpe_priv,struct color_gamut_data * gamut,enum color_space color_space)161 static enum vpe_status find_predefined_gamut_and_white_point(
162 struct vpe_priv *vpe_priv, struct color_gamut_data *gamut, enum color_space color_space)
163 {
164 enum predefined_gamut_type gamut_type;
165
166 gamut->color_space = color_space;
167
168 gamut_type = color_space_to_predefined_gamut_types(color_space);
169 if (gamut_type == gamut_type_unknown) {
170 vpe_log("err: color space not supported! %d %d\n", (int)color_space, (int)gamut_type);
171 return VPE_STATUS_COLOR_SPACE_VALUE_NOT_SUPPORTED;
172 }
173
174 color_find_predefined_gamut(&gamut->gamut, gamut_type);
175 gamut->white_point = color_white_point_type_6500k_noon;
176 color_find_predefined_white_point(&gamut->gamut, white_point_type_6500k_noon);
177
178 return VPE_STATUS_OK;
179 }
180
build_gamut_remap_matrix(struct color_space_coordinates gamut_description,struct fixed31_32 * rgb_matrix,struct fixed31_32 * white_point_matrix)181 static bool build_gamut_remap_matrix(struct color_space_coordinates gamut_description,
182 struct fixed31_32 *rgb_matrix, struct fixed31_32 *white_point_matrix)
183 {
184 struct fixed31_32 fixed_blueX = vpe_fixpt_from_fraction(gamut_description.blueX, DIVIDER);
185 struct fixed31_32 fixed_blueY = vpe_fixpt_from_fraction(gamut_description.blueY, DIVIDER);
186 struct fixed31_32 fixed_greenX = vpe_fixpt_from_fraction(gamut_description.greenX, DIVIDER);
187 struct fixed31_32 fixed_greenY = vpe_fixpt_from_fraction(gamut_description.greenY, DIVIDER);
188 struct fixed31_32 fixed_redX = vpe_fixpt_from_fraction(gamut_description.redX, DIVIDER);
189 struct fixed31_32 fixed_redY = vpe_fixpt_from_fraction(gamut_description.redY, DIVIDER);
190 struct fixed31_32 fixed_whiteX = vpe_fixpt_from_fraction(gamut_description.whiteX, DIVIDER);
191 struct fixed31_32 fixed_whiteY = vpe_fixpt_from_fraction(gamut_description.whiteY, DIVIDER);
192
193 rgb_matrix[0] = vpe_fixpt_div(fixed_redX, fixed_redY);
194 rgb_matrix[1] = vpe_fixpt_one;
195 rgb_matrix[2] = vpe_fixpt_div(
196 vpe_fixpt_sub(vpe_fixpt_sub(vpe_fixpt_one, fixed_redX), fixed_redY), fixed_redY);
197
198 rgb_matrix[3] = vpe_fixpt_div(fixed_greenX, fixed_greenY);
199 rgb_matrix[4] = vpe_fixpt_one;
200 rgb_matrix[5] = vpe_fixpt_div(
201 vpe_fixpt_sub(vpe_fixpt_sub(vpe_fixpt_one, fixed_greenX), fixed_greenY), fixed_greenY);
202
203 rgb_matrix[6] = vpe_fixpt_div(fixed_blueX, fixed_blueY);
204 rgb_matrix[7] = vpe_fixpt_one;
205 rgb_matrix[8] = vpe_fixpt_div(
206 vpe_fixpt_sub(vpe_fixpt_sub(vpe_fixpt_one, fixed_blueX), fixed_blueY), fixed_blueY);
207
208 white_point_matrix[0] = vpe_fixpt_div(fixed_whiteX, fixed_whiteY);
209 white_point_matrix[1] = vpe_fixpt_one;
210 white_point_matrix[2] = vpe_fixpt_div(
211 vpe_fixpt_sub(vpe_fixpt_sub(vpe_fixpt_one, fixed_whiteX), fixed_whiteY), fixed_whiteY);
212
213 return true;
214 }
215
find_3X3_det(const struct fixed31_32 * m)216 static struct fixed31_32 find_3X3_det(const struct fixed31_32 *m)
217 {
218 struct fixed31_32 det, A1, A2, A3;
219
220 A1 = vpe_fixpt_mul(m[0], vpe_fixpt_sub(vpe_fixpt_mul(m[4], m[8]), vpe_fixpt_mul(m[5], m[7])));
221 A2 = vpe_fixpt_mul(m[1], vpe_fixpt_sub(vpe_fixpt_mul(m[3], m[8]), vpe_fixpt_mul(m[5], m[6])));
222 A3 = vpe_fixpt_mul(m[2], vpe_fixpt_sub(vpe_fixpt_mul(m[3], m[7]), vpe_fixpt_mul(m[4], m[6])));
223 det = vpe_fixpt_add(vpe_fixpt_sub(A1, A2), A3);
224 return det;
225 }
226
compute_inverse_matrix_3x3(const struct fixed31_32 * m,struct fixed31_32 * im)227 static bool compute_inverse_matrix_3x3(const struct fixed31_32 *m, struct fixed31_32 *im)
228 {
229 struct fixed31_32 determinant = find_3X3_det(m);
230
231 if (vpe_fixpt_eq(determinant, vpe_fixpt_zero) == false) {
232 im[0] = vpe_fixpt_div(
233 vpe_fixpt_sub(vpe_fixpt_mul(m[4], m[8]), vpe_fixpt_mul(m[5], m[7])), determinant);
234 im[1] = vpe_fixpt_neg(vpe_fixpt_div(
235 vpe_fixpt_sub(vpe_fixpt_mul(m[1], m[8]), vpe_fixpt_mul(m[2], m[7])), determinant));
236 im[2] = vpe_fixpt_div(
237 vpe_fixpt_sub(vpe_fixpt_mul(m[1], m[5]), vpe_fixpt_mul(m[2], m[4])), determinant);
238 im[3] = vpe_fixpt_neg(vpe_fixpt_div(
239 vpe_fixpt_sub(vpe_fixpt_mul(m[3], m[8]), vpe_fixpt_mul(m[5], m[6])), determinant));
240 im[4] = vpe_fixpt_div(
241 vpe_fixpt_sub(vpe_fixpt_mul(m[0], m[8]), vpe_fixpt_mul(m[2], m[6])), determinant);
242 im[5] = vpe_fixpt_neg(vpe_fixpt_div(
243 vpe_fixpt_sub(vpe_fixpt_mul(m[0], m[5]), vpe_fixpt_mul(m[2], m[3])), determinant));
244 im[6] = vpe_fixpt_div(
245 vpe_fixpt_sub(vpe_fixpt_mul(m[3], m[7]), vpe_fixpt_mul(m[4], m[6])), determinant);
246 im[7] = vpe_fixpt_neg(vpe_fixpt_div(
247 vpe_fixpt_sub(vpe_fixpt_mul(m[0], m[7]), vpe_fixpt_mul(m[1], m[6])), determinant));
248 im[8] = vpe_fixpt_div(
249 vpe_fixpt_sub(vpe_fixpt_mul(m[0], m[4]), vpe_fixpt_mul(m[1], m[3])), determinant);
250 return true;
251 }
252 return false;
253 }
254
calculate_XYZ_to_RGB_3x3(const struct fixed31_32 * XYZofRGB,const struct fixed31_32 * XYZofWhite,struct fixed31_32 * XYZtoRGB)255 static bool calculate_XYZ_to_RGB_3x3(const struct fixed31_32 *XYZofRGB,
256 const struct fixed31_32 *XYZofWhite, struct fixed31_32 *XYZtoRGB)
257 {
258
259 struct fixed31_32 MInversed[9];
260 struct fixed31_32 SVector[3];
261
262 /*1. Find Inverse matrix 3x3 of MTransposed*/
263 if (!compute_inverse_matrix_3x3(XYZofRGB, MInversed))
264 return false;
265
266 /*2. Calculate vector: |Sr Sg Sb| = [MInversed] * |Wx Wy Wz|*/
267 color_multiply_matrices(SVector, MInversed, XYZofWhite, 3, 3, 1);
268
269 /*3. Calculate matrix XYZtoRGB 3x3*/
270 XYZtoRGB[0] = vpe_fixpt_mul(XYZofRGB[0], SVector[0]);
271 XYZtoRGB[1] = vpe_fixpt_mul(XYZofRGB[1], SVector[1]);
272 XYZtoRGB[2] = vpe_fixpt_mul(XYZofRGB[2], SVector[2]);
273
274 XYZtoRGB[3] = vpe_fixpt_mul(XYZofRGB[3], SVector[0]);
275 XYZtoRGB[4] = vpe_fixpt_mul(XYZofRGB[4], SVector[1]);
276 XYZtoRGB[5] = vpe_fixpt_mul(XYZofRGB[5], SVector[2]);
277
278 XYZtoRGB[6] = vpe_fixpt_mul(XYZofRGB[6], SVector[0]);
279 XYZtoRGB[7] = vpe_fixpt_mul(XYZofRGB[7], SVector[1]);
280 XYZtoRGB[8] = vpe_fixpt_mul(XYZofRGB[8], SVector[2]);
281
282 return true;
283 }
284
gamut_to_color_matrix(struct vpe_priv * vpe_priv,const struct gamut_src_dst_matrix * matrices,bool invert,struct fixed31_32 * tempMatrix3X3,struct fixed31_32 * tempOffset)285 static bool gamut_to_color_matrix(struct vpe_priv *vpe_priv,
286 const struct gamut_src_dst_matrix *matrices, bool invert, struct fixed31_32 *tempMatrix3X3,
287 struct fixed31_32 *tempOffset)
288 {
289 int i = 0;
290 struct gamut_calculation_matrix *matrix = vpe_zalloc(sizeof(struct gamut_calculation_matrix));
291
292 const struct fixed31_32 *pXYZofRGB = matrices->rgbCoeffDst; /*destination gamut*/
293 const struct fixed31_32 *pXYZofWhite = matrices->whiteCoeffDst; /*destination of white point*/
294 const struct fixed31_32 *pRefXYZofRGB = matrices->rgbCoeffSrc; /*source gamut*/
295 const struct fixed31_32 *pRefXYZofWhite = matrices->whiteCoeffSrc; /*source of white point*/
296 const struct fixed31_32 *pColorTransformXYZ = matrices->xyzMatrix; /*additional XYZ->XYZ tfm*/
297 const struct fixed31_32 *pColorTransformXYZOffset = matrices->xyzOffset; /*XYZ tfm offset*/
298 const struct fixed31_32 *pBradford = matrices->bradford; /*Bradford chromatic adaptation*/
299
300 struct fixed31_32 *pXYZtoRGB_Temp;
301 struct fixed31_32 *pXYZtoRGB_Final;
302
303 if (!matrix)
304 return false;
305
306 matrix->fXYZofWhiteRef[0] = pRefXYZofWhite[0];
307 matrix->fXYZofWhiteRef[1] = pRefXYZofWhite[1];
308 matrix->fXYZofWhiteRef[2] = pRefXYZofWhite[2];
309
310 matrix->fXYZofRGBRef[0] = pRefXYZofRGB[0];
311 matrix->fXYZofRGBRef[1] = pRefXYZofRGB[1];
312 matrix->fXYZofRGBRef[2] = pRefXYZofRGB[2];
313
314 matrix->fXYZofRGBRef[3] = pRefXYZofRGB[3];
315 matrix->fXYZofRGBRef[4] = pRefXYZofRGB[4];
316 matrix->fXYZofRGBRef[5] = pRefXYZofRGB[5];
317
318 matrix->fXYZofRGBRef[6] = pRefXYZofRGB[6];
319 matrix->fXYZofRGBRef[7] = pRefXYZofRGB[7];
320 matrix->fXYZofRGBRef[8] = pRefXYZofRGB[8];
321
322 /*default values - unity matrix*/
323 while (i < 9) {
324 if (i == 0 || i == 4 || i == 8)
325 tempMatrix3X3[i] = vpe_fixpt_one;
326 else
327 tempMatrix3X3[i] = vpe_fixpt_zero;
328 i++;
329 }
330
331 /*1. Decide about the order of calculation.
332 * bInvert == FALSE --> RGBtoXYZ_Ref * XYZtoRGB_Custom
333 * bInvert == TRUE --> RGBtoXYZ_Custom * XYZtoRGB_Ref */
334 if (invert) {
335 pXYZtoRGB_Temp = matrix->XYZtoRGB_Custom;
336 pXYZtoRGB_Final = matrix->XYZtoRGB_Ref;
337 } else {
338 pXYZtoRGB_Temp = matrix->XYZtoRGB_Ref;
339 pXYZtoRGB_Final = matrix->XYZtoRGB_Custom;
340 }
341
342 /*2. Calculate XYZtoRGB_Ref*/
343 color_transpose_matrix(matrix->fXYZofRGBRef, 3, 3, matrix->MTransposed);
344
345 if (!calculate_XYZ_to_RGB_3x3(
346 matrix->MTransposed, matrix->fXYZofWhiteRef, matrix->XYZtoRGB_Ref))
347 goto function_fail;
348
349 /*3. Calculate XYZtoRGB_Custom*/
350 color_transpose_matrix(pXYZofRGB, 3, 3, matrix->MTransposed);
351
352 if (!calculate_XYZ_to_RGB_3x3(matrix->MTransposed, pXYZofWhite, matrix->XYZtoRGB_Custom))
353 goto function_fail;
354
355 /*4. Calculate RGBtoXYZ -
356 * inverse matrix 3x3 of XYZtoRGB_Ref or XYZtoRGB_Custom*/
357 if (!compute_inverse_matrix_3x3(pXYZtoRGB_Temp, matrix->RGBtoXYZ_Final))
358 goto function_fail;
359
360 /* The naming is a bit confusing here (and earlier as well if you're
361 * trying to follow RP 177-1993...), so in short:
362 * S - source->XYZ
363 * D - dest->XYZ
364 * At this point:
365 * D^-1 = RGBtoXYZ_Final
366 * S = XYZtoRGB_Ref == pXYZtoRGB_Final
367 */
368
369 /*5. Calculate M(3x3) = RGBtoXYZ * XYZtoRGB*/
370 color_multiply_matrices(matrix->MResult, matrix->RGBtoXYZ_Final, pXYZtoRGB_Final, 3, 3, 3);
371
372 /*7. Calculate offsets */
373 for (i = 0; i < 9; i++)
374 tempMatrix3X3[i] = matrix->MResult[i];
375
376 for (i = 0; i < 3; i++)
377 tempOffset[i] = vpe_fixpt_zero;
378
379 vpe_free(matrix);
380 return true;
381
382 function_fail:
383 vpe_free(matrix);
384 return false;
385 }
386
color_build_gamut_remap_matrix(struct vpe_priv * vpe_priv,struct color_gamut_data * source_gamut,struct color_gamut_data * destination_gamut,struct colorspace_transform * gamut_remap_matrix)387 static bool color_build_gamut_remap_matrix(struct vpe_priv *vpe_priv,
388 struct color_gamut_data *source_gamut, struct color_gamut_data *destination_gamut,
389 struct colorspace_transform *gamut_remap_matrix)
390 {
391 struct gamut_src_dst_matrix *matrix = NULL;
392 struct fixed31_32 gamut_result[12];
393 struct fixed31_32 temp_matrix[9];
394 struct fixed31_32 temp_offset[3];
395 int j;
396
397 matrix = vpe_zalloc(sizeof(struct gamut_src_dst_matrix));
398 if (matrix == NULL)
399 return false;
400
401 build_gamut_remap_matrix(source_gamut->gamut, matrix->rgbCoeffSrc, matrix->whiteCoeffSrc);
402 build_gamut_remap_matrix(destination_gamut->gamut, matrix->rgbCoeffDst, matrix->whiteCoeffDst);
403
404 if (!gamut_to_color_matrix(vpe_priv, matrix, true, temp_matrix, temp_offset))
405 goto function_fail;
406
407 gamut_result[0] = temp_matrix[0];
408 gamut_result[1] = temp_matrix[1];
409 gamut_result[2] = temp_matrix[2];
410 gamut_result[4] = temp_matrix[3];
411 gamut_result[5] = temp_matrix[4];
412 gamut_result[6] = temp_matrix[5];
413 gamut_result[8] = temp_matrix[6];
414 gamut_result[9] = temp_matrix[7];
415 gamut_result[10] = temp_matrix[8];
416
417 gamut_result[3] = temp_offset[0];
418 gamut_result[7] = temp_offset[1];
419 gamut_result[11] = temp_offset[2];
420
421 gamut_remap_matrix->enable_remap = true;
422
423 for (j = 0; j < 12; j++)
424 gamut_remap_matrix->matrix[j] = gamut_result[j];
425
426 vpe_free(matrix);
427 return true;
428
429 function_fail:
430 vpe_free(matrix);
431 vpe_log("err: build gamut remap fails!\n");
432 return false;
433 }
434
vpe_color_update_gamut(struct vpe_priv * vpe_priv,enum color_space in_color,enum color_space outColor,struct colorspace_transform * gamut_remap,bool bypass_remap)435 enum vpe_status vpe_color_update_gamut(struct vpe_priv *vpe_priv, enum color_space in_color,
436 enum color_space outColor, struct colorspace_transform *gamut_remap, bool bypass_remap)
437 {
438 struct output_ctx *output_ctx = &vpe_priv->output_ctx;
439 struct color_gamut_data src_gamut;
440 struct color_gamut_data dst_gamut;
441 enum vpe_status status;
442
443 if (bypass_remap || in_color == outColor) {
444 gamut_remap->enable_remap = false;
445 return VPE_STATUS_OK;
446 }
447
448 status = find_predefined_gamut_and_white_point(vpe_priv, &src_gamut, in_color);
449 if (status != VPE_STATUS_OK)
450 return status;
451
452 status = find_predefined_gamut_and_white_point(vpe_priv, &dst_gamut, outColor);
453 if (status != VPE_STATUS_OK)
454 return status;
455
456 if (!color_build_gamut_remap_matrix(vpe_priv, &src_gamut, &dst_gamut, gamut_remap)) {
457 vpe_log("err: build gamut remap failure!");
458 VPE_ASSERT(0);
459 return VPE_STATUS_ERROR;
460 }
461
462 return VPE_STATUS_OK;
463 }
464