xref: /aosp_15_r20/external/mesa3d/src/amd/vpelib/src/core/color_gamut.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 #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         return gamut_type_bt2020;
154     default:
155         VPE_ASSERT(0);
156         return gamut_type_unknown;
157     }
158 }
159 
find_predefined_gamut_and_white_point(struct vpe_priv * vpe_priv,struct color_gamut_data * gamut,enum color_space color_space)160 static enum vpe_status find_predefined_gamut_and_white_point(
161     struct vpe_priv *vpe_priv, struct color_gamut_data *gamut, enum color_space color_space)
162 {
163     enum predefined_gamut_type gamut_type;
164 
165     gamut->color_space = color_space;
166 
167     gamut_type = color_space_to_predefined_gamut_types(color_space);
168     if (gamut_type == gamut_type_unknown) {
169         vpe_log("err: color space not supported! %d %d\n", (int)color_space, (int)gamut_type);
170         return VPE_STATUS_COLOR_SPACE_VALUE_NOT_SUPPORTED;
171     }
172 
173     color_find_predefined_gamut(&gamut->gamut, gamut_type);
174     gamut->white_point = color_white_point_type_6500k_noon;
175     color_find_predefined_white_point(&gamut->gamut, white_point_type_6500k_noon);
176 
177     return VPE_STATUS_OK;
178 }
179 
build_gamut_remap_matrix(struct color_space_coordinates gamut_description,struct fixed31_32 * rgb_matrix,struct fixed31_32 * white_point_matrix)180 static bool build_gamut_remap_matrix(struct color_space_coordinates gamut_description,
181     struct fixed31_32 *rgb_matrix, struct fixed31_32 *white_point_matrix)
182 {
183     struct fixed31_32 fixed_blueX  = vpe_fixpt_from_fraction(gamut_description.blueX, DIVIDER);
184     struct fixed31_32 fixed_blueY  = vpe_fixpt_from_fraction(gamut_description.blueY, DIVIDER);
185     struct fixed31_32 fixed_greenX = vpe_fixpt_from_fraction(gamut_description.greenX, DIVIDER);
186     struct fixed31_32 fixed_greenY = vpe_fixpt_from_fraction(gamut_description.greenY, DIVIDER);
187     struct fixed31_32 fixed_redX   = vpe_fixpt_from_fraction(gamut_description.redX, DIVIDER);
188     struct fixed31_32 fixed_redY   = vpe_fixpt_from_fraction(gamut_description.redY, DIVIDER);
189     struct fixed31_32 fixed_whiteX = vpe_fixpt_from_fraction(gamut_description.whiteX, DIVIDER);
190     struct fixed31_32 fixed_whiteY = vpe_fixpt_from_fraction(gamut_description.whiteY, DIVIDER);
191 
192     rgb_matrix[0] = vpe_fixpt_div(fixed_redX, fixed_redY);
193     rgb_matrix[1] = vpe_fixpt_one;
194     rgb_matrix[2] = vpe_fixpt_div(
195         vpe_fixpt_sub(vpe_fixpt_sub(vpe_fixpt_one, fixed_redX), fixed_redY), fixed_redY);
196 
197     rgb_matrix[3] = vpe_fixpt_div(fixed_greenX, fixed_greenY);
198     rgb_matrix[4] = vpe_fixpt_one;
199     rgb_matrix[5] = vpe_fixpt_div(
200         vpe_fixpt_sub(vpe_fixpt_sub(vpe_fixpt_one, fixed_greenX), fixed_greenY), fixed_greenY);
201 
202     rgb_matrix[6] = vpe_fixpt_div(fixed_blueX, fixed_blueY);
203     rgb_matrix[7] = vpe_fixpt_one;
204     rgb_matrix[8] = vpe_fixpt_div(
205         vpe_fixpt_sub(vpe_fixpt_sub(vpe_fixpt_one, fixed_blueX), fixed_blueY), fixed_blueY);
206 
207     white_point_matrix[0] = vpe_fixpt_div(fixed_whiteX, fixed_whiteY);
208     white_point_matrix[1] = vpe_fixpt_one;
209     white_point_matrix[2] = vpe_fixpt_div(
210         vpe_fixpt_sub(vpe_fixpt_sub(vpe_fixpt_one, fixed_whiteX), fixed_whiteY), fixed_whiteY);
211 
212     return true;
213 }
214 
find_3X3_det(const struct fixed31_32 * m)215 static struct fixed31_32 find_3X3_det(const struct fixed31_32 *m)
216 {
217     struct fixed31_32 det, A1, A2, A3;
218 
219     A1  = vpe_fixpt_mul(m[0], vpe_fixpt_sub(vpe_fixpt_mul(m[4], m[8]), vpe_fixpt_mul(m[5], m[7])));
220     A2  = vpe_fixpt_mul(m[1], vpe_fixpt_sub(vpe_fixpt_mul(m[3], m[8]), vpe_fixpt_mul(m[5], m[6])));
221     A3  = vpe_fixpt_mul(m[2], vpe_fixpt_sub(vpe_fixpt_mul(m[3], m[7]), vpe_fixpt_mul(m[4], m[6])));
222     det = vpe_fixpt_add(vpe_fixpt_sub(A1, A2), A3);
223     return det;
224 }
225 
compute_inverse_matrix_3x3(const struct fixed31_32 * m,struct fixed31_32 * im)226 static bool compute_inverse_matrix_3x3(const struct fixed31_32 *m, struct fixed31_32 *im)
227 {
228     struct fixed31_32 determinant = find_3X3_det(m);
229 
230     if (vpe_fixpt_eq(determinant, vpe_fixpt_zero) == false) {
231         im[0] = vpe_fixpt_div(
232             vpe_fixpt_sub(vpe_fixpt_mul(m[4], m[8]), vpe_fixpt_mul(m[5], m[7])), determinant);
233         im[1] = vpe_fixpt_neg(vpe_fixpt_div(
234             vpe_fixpt_sub(vpe_fixpt_mul(m[1], m[8]), vpe_fixpt_mul(m[2], m[7])), determinant));
235         im[2] = vpe_fixpt_div(
236             vpe_fixpt_sub(vpe_fixpt_mul(m[1], m[5]), vpe_fixpt_mul(m[2], m[4])), determinant);
237         im[3] = vpe_fixpt_neg(vpe_fixpt_div(
238             vpe_fixpt_sub(vpe_fixpt_mul(m[3], m[8]), vpe_fixpt_mul(m[5], m[6])), determinant));
239         im[4] = vpe_fixpt_div(
240             vpe_fixpt_sub(vpe_fixpt_mul(m[0], m[8]), vpe_fixpt_mul(m[2], m[6])), determinant);
241         im[5] = vpe_fixpt_neg(vpe_fixpt_div(
242             vpe_fixpt_sub(vpe_fixpt_mul(m[0], m[5]), vpe_fixpt_mul(m[2], m[3])), determinant));
243         im[6] = vpe_fixpt_div(
244             vpe_fixpt_sub(vpe_fixpt_mul(m[3], m[7]), vpe_fixpt_mul(m[4], m[6])), determinant);
245         im[7] = vpe_fixpt_neg(vpe_fixpt_div(
246             vpe_fixpt_sub(vpe_fixpt_mul(m[0], m[7]), vpe_fixpt_mul(m[1], m[6])), determinant));
247         im[8] = vpe_fixpt_div(
248             vpe_fixpt_sub(vpe_fixpt_mul(m[0], m[4]), vpe_fixpt_mul(m[1], m[3])), determinant);
249         return true;
250     }
251     return false;
252 }
253 
calculate_XYZ_to_RGB_3x3(const struct fixed31_32 * XYZofRGB,const struct fixed31_32 * XYZofWhite,struct fixed31_32 * XYZtoRGB)254 static bool calculate_XYZ_to_RGB_3x3(const struct fixed31_32 *XYZofRGB,
255     const struct fixed31_32 *XYZofWhite, struct fixed31_32 *XYZtoRGB)
256 {
257 
258     struct fixed31_32 MInversed[9];
259     struct fixed31_32 SVector[3];
260 
261     /*1. Find Inverse matrix 3x3 of MTransposed*/
262     if (!compute_inverse_matrix_3x3(XYZofRGB, MInversed))
263         return false;
264 
265     /*2. Calculate vector: |Sr Sg Sb| = [MInversed] * |Wx Wy Wz|*/
266     color_multiply_matrices(SVector, MInversed, XYZofWhite, 3, 3, 1);
267 
268     /*3. Calculate matrix XYZtoRGB 3x3*/
269     XYZtoRGB[0] = vpe_fixpt_mul(XYZofRGB[0], SVector[0]);
270     XYZtoRGB[1] = vpe_fixpt_mul(XYZofRGB[1], SVector[1]);
271     XYZtoRGB[2] = vpe_fixpt_mul(XYZofRGB[2], SVector[2]);
272 
273     XYZtoRGB[3] = vpe_fixpt_mul(XYZofRGB[3], SVector[0]);
274     XYZtoRGB[4] = vpe_fixpt_mul(XYZofRGB[4], SVector[1]);
275     XYZtoRGB[5] = vpe_fixpt_mul(XYZofRGB[5], SVector[2]);
276 
277     XYZtoRGB[6] = vpe_fixpt_mul(XYZofRGB[6], SVector[0]);
278     XYZtoRGB[7] = vpe_fixpt_mul(XYZofRGB[7], SVector[1]);
279     XYZtoRGB[8] = vpe_fixpt_mul(XYZofRGB[8], SVector[2]);
280 
281     return true;
282 }
283 
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)284 static bool gamut_to_color_matrix(struct vpe_priv *vpe_priv,
285     const struct gamut_src_dst_matrix *matrices, bool invert, struct fixed31_32 *tempMatrix3X3,
286     struct fixed31_32 *tempOffset)
287 {
288     int                              i      = 0;
289     struct gamut_calculation_matrix *matrix = vpe_zalloc(sizeof(struct gamut_calculation_matrix));
290 
291     const struct fixed31_32 *pXYZofRGB    = matrices->rgbCoeffDst;   /*destination gamut*/
292     const struct fixed31_32 *pXYZofWhite  = matrices->whiteCoeffDst; /*destination of white point*/
293     const struct fixed31_32 *pRefXYZofRGB = matrices->rgbCoeffSrc;   /*source gamut*/
294     const struct fixed31_32 *pRefXYZofWhite     = matrices->whiteCoeffSrc; /*source of white point*/
295     const struct fixed31_32 *pColorTransformXYZ = matrices->xyzMatrix; /*additional XYZ->XYZ tfm*/
296     const struct fixed31_32 *pColorTransformXYZOffset = matrices->xyzOffset; /*XYZ tfm offset*/
297     const struct fixed31_32 *pBradford = matrices->bradford; /*Bradford chromatic adaptation*/
298 
299     struct fixed31_32 *pXYZtoRGB_Temp;
300     struct fixed31_32 *pXYZtoRGB_Final;
301 
302     if (!matrix)
303         return false;
304 
305     matrix->fXYZofWhiteRef[0] = pRefXYZofWhite[0];
306     matrix->fXYZofWhiteRef[1] = pRefXYZofWhite[1];
307     matrix->fXYZofWhiteRef[2] = pRefXYZofWhite[2];
308 
309     matrix->fXYZofRGBRef[0] = pRefXYZofRGB[0];
310     matrix->fXYZofRGBRef[1] = pRefXYZofRGB[1];
311     matrix->fXYZofRGBRef[2] = pRefXYZofRGB[2];
312 
313     matrix->fXYZofRGBRef[3] = pRefXYZofRGB[3];
314     matrix->fXYZofRGBRef[4] = pRefXYZofRGB[4];
315     matrix->fXYZofRGBRef[5] = pRefXYZofRGB[5];
316 
317     matrix->fXYZofRGBRef[6] = pRefXYZofRGB[6];
318     matrix->fXYZofRGBRef[7] = pRefXYZofRGB[7];
319     matrix->fXYZofRGBRef[8] = pRefXYZofRGB[8];
320 
321     /*default values -  unity matrix*/
322     while (i < 9) {
323         if (i == 0 || i == 4 || i == 8)
324             tempMatrix3X3[i] = vpe_fixpt_one;
325         else
326             tempMatrix3X3[i] = vpe_fixpt_zero;
327         i++;
328     }
329 
330     /*1. Decide about the order of calculation.
331      * bInvert == FALSE --> RGBtoXYZ_Ref * XYZtoRGB_Custom
332      * bInvert == TRUE  --> RGBtoXYZ_Custom * XYZtoRGB_Ref */
333     if (invert) {
334         pXYZtoRGB_Temp  = matrix->XYZtoRGB_Custom;
335         pXYZtoRGB_Final = matrix->XYZtoRGB_Ref;
336     } else {
337         pXYZtoRGB_Temp  = matrix->XYZtoRGB_Ref;
338         pXYZtoRGB_Final = matrix->XYZtoRGB_Custom;
339     }
340 
341     /*2. Calculate XYZtoRGB_Ref*/
342     color_transpose_matrix(matrix->fXYZofRGBRef, 3, 3, matrix->MTransposed);
343 
344     if (!calculate_XYZ_to_RGB_3x3(
345             matrix->MTransposed, matrix->fXYZofWhiteRef, matrix->XYZtoRGB_Ref))
346         goto function_fail;
347 
348     /*3. Calculate XYZtoRGB_Custom*/
349     color_transpose_matrix(pXYZofRGB, 3, 3, matrix->MTransposed);
350 
351     if (!calculate_XYZ_to_RGB_3x3(matrix->MTransposed, pXYZofWhite, matrix->XYZtoRGB_Custom))
352         goto function_fail;
353 
354     /*4. Calculate RGBtoXYZ -
355      * inverse matrix 3x3 of XYZtoRGB_Ref or XYZtoRGB_Custom*/
356     if (!compute_inverse_matrix_3x3(pXYZtoRGB_Temp, matrix->RGBtoXYZ_Final))
357         goto function_fail;
358 
359     /* The naming is a bit confusing here (and earlier as well if you're
360      * trying to follow RP 177-1993...), so in short:
361      *      S - source->XYZ
362      *      D - dest->XYZ
363      *      At this point:
364      *      D^-1 = RGBtoXYZ_Final
365      *      S = XYZtoRGB_Ref == pXYZtoRGB_Final
366      */
367 
368     /*5. Calculate M(3x3) = RGBtoXYZ * XYZtoRGB*/
369     color_multiply_matrices(matrix->MResult, matrix->RGBtoXYZ_Final, pXYZtoRGB_Final, 3, 3, 3);
370 
371     /*7. Calculate offsets */
372     for (i = 0; i < 9; i++)
373         tempMatrix3X3[i] = matrix->MResult[i];
374 
375     for (i = 0; i < 3; i++)
376         tempOffset[i] = vpe_fixpt_zero;
377 
378     vpe_free(matrix);
379     return true;
380 
381 function_fail:
382     vpe_free(matrix);
383     return false;
384 }
385 
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)386 static bool color_build_gamut_remap_matrix(struct vpe_priv *vpe_priv,
387     struct color_gamut_data *source_gamut, struct color_gamut_data *destination_gamut,
388     struct colorspace_transform *gamut_remap_matrix)
389 {
390     struct gamut_src_dst_matrix *matrix = NULL;
391     struct fixed31_32            gamut_result[12];
392     struct fixed31_32            temp_matrix[9];
393     struct fixed31_32            temp_offset[3];
394     int                          j;
395 
396     matrix = vpe_zalloc(sizeof(struct gamut_src_dst_matrix));
397     if (matrix == NULL)
398         return false;
399 
400     build_gamut_remap_matrix(source_gamut->gamut, matrix->rgbCoeffSrc, matrix->whiteCoeffSrc);
401     build_gamut_remap_matrix(destination_gamut->gamut, matrix->rgbCoeffDst, matrix->whiteCoeffDst);
402 
403     if (!gamut_to_color_matrix(vpe_priv, matrix, true, temp_matrix, temp_offset))
404         goto function_fail;
405 
406     gamut_result[0]  = temp_matrix[0];
407     gamut_result[1]  = temp_matrix[1];
408     gamut_result[2]  = temp_matrix[2];
409     gamut_result[4]  = temp_matrix[3];
410     gamut_result[5]  = temp_matrix[4];
411     gamut_result[6]  = temp_matrix[5];
412     gamut_result[8]  = temp_matrix[6];
413     gamut_result[9]  = temp_matrix[7];
414     gamut_result[10] = temp_matrix[8];
415 
416     gamut_result[3]  = temp_offset[0];
417     gamut_result[7]  = temp_offset[1];
418     gamut_result[11] = temp_offset[2];
419 
420     gamut_remap_matrix->enable_remap = true;
421 
422     for (j = 0; j < 12; j++)
423         gamut_remap_matrix->matrix[j] = gamut_result[j];
424 
425     vpe_free(matrix);
426     return true;
427 
428 function_fail:
429     vpe_free(matrix);
430     vpe_log("err: build gamut remap fails!\n");
431     return false;
432 }
433 
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)434 enum vpe_status vpe_color_update_gamut(struct vpe_priv *vpe_priv, enum color_space in_color,
435     enum color_space outColor, struct colorspace_transform *gamut_remap, bool bypass_remap)
436 {
437     struct output_ctx      *output_ctx = &vpe_priv->output_ctx;
438     struct color_gamut_data src_gamut;
439     struct color_gamut_data dst_gamut;
440     enum vpe_status         status;
441 
442     if (bypass_remap || in_color == outColor) {
443         gamut_remap->enable_remap = false;
444         return VPE_STATUS_OK;
445     }
446 
447     status = find_predefined_gamut_and_white_point(vpe_priv, &src_gamut, in_color);
448     if (status != VPE_STATUS_OK)
449         return status;
450 
451     status = find_predefined_gamut_and_white_point(vpe_priv, &dst_gamut, outColor);
452     if (status != VPE_STATUS_OK)
453         return status;
454 
455     if (!color_build_gamut_remap_matrix(vpe_priv, &src_gamut, &dst_gamut, gamut_remap)) {
456         vpe_log("err: build gamut remap failure!");
457         VPE_ASSERT(0);
458         return VPE_STATUS_ERROR;
459     }
460 
461     return VPE_STATUS_OK;
462 }
463