• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "rs_base_render_util.h"
17 
18 #include <sys/time.h>
19 #include <unordered_set>
20 #include <parameters.h>
21 
22 #include "common/rs_matrix3.h"
23 #include "common/rs_obj_abs_geometry.h"
24 #include "common/rs_vector2.h"
25 #include "common/rs_vector3.h"
26 #include "include/utils/SkCamera.h"
27 #include "platform/common/rs_log.h"
28 #include "png.h"
29 #include "rs_trace.h"
30 #include "transaction/rs_transaction_data.h"
31 
32 #ifdef USE_ROSEN_DRAWING
33 #include "draw/clip.h"
34 #include "effect/color_filter.h"
35 #include "effect/color_matrix.h"
36 #include "utils/camera3d.h"
37 #endif
38 
39 namespace OHOS {
40 namespace Rosen {
41 namespace Detail {
42 // [PLANNING]: Use GPU to do the gamut conversion instead of these following works.
43 using PixelTransformFunc = std::function<float(float)>;
44 
45 using Offset = std::pair<uint8_t, uint8_t>; // first: offsetSrc; second: offsetDst
46 const int dstLength = 3;
47 using Array3ptr = std::array<uint8_t*, dstLength>;
48 const uint32_t STUB_PIXEL_FMT_RGBA_16161616 = 0X7fff0001;
49 const uint32_t STUB_PIXEL_FMT_RGBA_1010102 = 0X7fff0002;
50 constexpr uint32_t MATRIX_SIZE = 20; // colorMatrix size
51 constexpr int BITMAP_DEPTH = 8;
52 #ifdef USE_ROSEN_DRAWING
53 constexpr int BYTES_PER_PIXEL = 4;
54 #endif
55 
PassThrough(float v)56 inline constexpr float PassThrough(float v)
57 {
58     return v;
59 }
60 
61 template<typename T>
Saturate(T v)62 static constexpr T Saturate(T v) noexcept
63 {
64     return T(std::min(static_cast<T>(1), std::max(static_cast<T>(0), v)));
65 }
66 
ApplyTransForm(const Vector3f & val,const PixelTransformFunc & func)67 inline Vector3f ApplyTransForm(const Vector3f& val, const PixelTransformFunc& func)
68 {
69     return Vector3f {func(val.x_), func(val.y_), func(val.z_)};
70 }
71 
SafePow(float x,float e)72 inline float SafePow(float x, float e)
73 {
74     return powf(x < 0.0f ? 0.0f : x, e);
75 }
76 
GenOETF(float gamma)77 inline PixelTransformFunc GenOETF(float gamma)
78 {
79     if (gamma == 1.0f || gamma == 0.0f) {
80         return PassThrough;
81     }
82 
83     return std::bind(SafePow, std::placeholders::_1, 1.0f / gamma);
84 }
85 
GenEOTF(float gamma)86 inline PixelTransformFunc GenEOTF(float gamma)
87 {
88     if (gamma == 1.0f) {
89         return PassThrough;
90     }
91 
92     return std::bind(SafePow, std::placeholders::_1, gamma);
93 }
94 
95 struct TransferParameters {
96     float g = 0.0f;
97     float a = 0.0f;
98     float b = 0.0f;
99     float c = 0.0f;
100     float d = 0.0f;
101     float e = 0.0f;
102     float f = 0.0f;
103 };
104 
RcpResponsePq(float x,const TransferParameters & p)105 inline float RcpResponsePq(float x, const TransferParameters& p)
106 {
107     float tmp = powf(x, p.a);
108     return std::powf((p.c + p.d * tmp) / (1 + p.e * tmp), p.b);
109 }
110 
ResponsePq(float x,const TransferParameters & p)111 inline float ResponsePq(float x, const TransferParameters& p)
112 {
113     float tmp = powf(x, 1.f / p.b);
114     return std::powf(std::max((tmp - p.c), p.f) / (p.d - p.e * tmp), 1.f / p.a);
115 }
116 
117 
RcpResponse(float x,const TransferParameters & p)118 static constexpr float RcpResponse(float x, const TransferParameters& p)
119 {
120     return x >= p.d * p.c ? (std::pow(x, 1.0f / p.g) - p.b) / p.a : x / p.c;
121 }
122 
Response(float x,const TransferParameters & p)123 inline constexpr float Response(float x, const TransferParameters& p)
124 {
125     return x >= p.d ? std::pow(p.a * x + p.b, p.g) : p.c * x;
126 }
127 
RcpFullResponse(float x,const TransferParameters & p)128 inline constexpr float RcpFullResponse(float x, const TransferParameters& p)
129 {
130     return x >= p.d * p.c ? (std::pow(x - p.e, 1.0f / p.g) - p.b) / p.a : (x - p.f) / p.c;
131 }
132 
FullResponse(float x,const TransferParameters & p)133 inline constexpr float FullResponse(float x, const TransferParameters& p)
134 {
135     return x >= p.d ? std::pow(p.a * x + p.b, p.g) + p.e : p.c * x + p.f;
136 }
137 
GenOETF(const TransferParameters & params)138 inline PixelTransformFunc GenOETF(const TransferParameters& params)
139 {
140     if (params.g < 0) { // HDR
141         return std::bind(RcpResponsePq, std::placeholders::_1, params);
142     }
143 
144     if (params.e == 0.0f && params.f == 0.0f) {
145         return std::bind(RcpResponse, std::placeholders::_1, params);
146     }
147 
148     return std::bind(RcpFullResponse, std::placeholders::_1, params);
149 }
150 
GenEOTF(const TransferParameters & params)151 inline PixelTransformFunc GenEOTF(const TransferParameters& params)
152 {
153     if (params.g < 0) {
154         return std::bind(ResponsePq, std::placeholders::_1, params);
155     }
156 
157     if (params.e == 0.0f && params.f == 0.0f) {
158         return std::bind(Response, std::placeholders::_1, params);
159     }
160 
161     return std::bind(FullResponse, std::placeholders::_1, params);
162 }
163 
ACESToneMapping(float color,float targetLum)164 float ACESToneMapping(float color, float targetLum)
165 {
166     const float a = 2.51f;
167     const float b = 0.03f;
168     const float c = 2.43f;
169     const float d = 0.59f;
170     const float e = 0.14f;
171 
172     color *= targetLum;
173     return (color * (a * color + b)) / (color * (c * color + d) + e);
174 }
175 
GenACESToneMapping(float targetLum)176 inline PixelTransformFunc GenACESToneMapping(float targetLum)
177 {
178     if (targetLum <= 0) {
179         const float defaultLum = 200.f;
180         targetLum = defaultLum;
181     }
182     return std::bind(ACESToneMapping, std::placeholders::_1, targetLum);
183 }
184 
GenRGBToXYZMatrix(const std::array<Vector2f,3> & basePoints,const Vector2f & whitePoint)185 Matrix3f GenRGBToXYZMatrix(const std::array<Vector2f, 3>& basePoints, const Vector2f& whitePoint)
186 {
187     const Vector2f& R = basePoints[0];
188     const Vector2f& G = basePoints[1];
189     const Vector2f& B = basePoints[2];
190 
191     float RxRy = R.x_ / R.y_;
192     float GxGy = G.x_ / G.y_;
193     float BxBy = B.x_ / B.y_;
194     float WxWy = whitePoint.x_ / whitePoint.y_;
195 
196     float oneRxRy = (1 - R.x_) / R.y_;
197     float oneGxGy = (1 - G.x_) / G.y_;
198     float oneBxBy = (1 - B.x_) / B.y_;
199     float oneWxWy = (1 - whitePoint.x_) / whitePoint.y_;
200 
201     float BY =
202         ((oneWxWy - oneRxRy) * (GxGy - RxRy) - (WxWy - RxRy) * (oneGxGy - oneRxRy)) /
203         ((oneBxBy - oneRxRy) * (GxGy - RxRy) - (BxBy - RxRy) * (oneGxGy - oneRxRy));
204     float GY = (WxWy - RxRy - BY * (BxBy - RxRy)) / (GxGy - RxRy);
205     float RY = 1 - GY - BY;
206 
207     float RYRy = RY / R.y_;
208     float GYGy = GY / G.y_;
209     float BYBy = BY / B.y_;
210 
211     return Matrix3f {
212         RYRy * R.x_, RY, RYRy * (1 - R.x_ - R.y_),
213         GYGy * G.x_, GY, GYGy * (1 - G.x_ - G.y_),
214         BYBy * B.x_, BY, BYBy * (1 - B.x_ - B.y_)
215     };
216 }
217 #ifndef USE_ROSEN_DRAWING
InvertColorMat()218 static const sk_sp<SkColorFilter>& InvertColorMat()
219 {
220     static const SkScalar colorMatrix[MATRIX_SIZE] = {
221         0.402,  -1.174, -0.228, 1.0, 0.0,
222         -0.598, -0.174, -0.228, 1.0, 0.0,
223         -0.599, -1.175, 0.772,  1.0, 0.0,
224         0.0,    0.0,    0.0,    1.0, 0.0
225     };
226     static auto invertColorMat = SkColorFilters::Matrix(colorMatrix);
227     return invertColorMat;
228 }
229 #else
InvertColorMat()230 static const std::shared_ptr<Drawing::ColorFilter>& InvertColorMat()
231 {
232     static const Drawing::scalar colorMatrixArray[MATRIX_SIZE] = {
233         0.402,  -1.174, -0.228, 1.0, 0.0,
234         -0.598, -0.174, -0.228, 1.0, 0.0,
235         -0.599, -1.175, 0.772,  1.0, 0.0,
236         0.0,    0.0,    0.0,    1.0, 0.0
237     };
238     Drawing::ColorMatrix colorMatrix;
239     colorMatrix.SetArray(colorMatrixArray);
240     static auto invertColorMat = Drawing::ColorFilter::CreateMatrixColorFilter(colorMatrix);
241     return invertColorMat;
242 }
243 #endif
244 
245 #ifndef USE_ROSEN_DRAWING
ProtanomalyMat()246 static const sk_sp<SkColorFilter>& ProtanomalyMat()
247 {
248     static const SkScalar colorMatrix[MATRIX_SIZE] = {
249         0.622,  0.377,  0.0, 0.0, 0.0,
250         0.264,  0.736,  0.0, 0.0, 0.0,
251         0.217,  -0.217, 1.0, 0.0, 0.0,
252         0.0,    0.0,    0.0, 1.0, 0.0
253     };
254     static auto protanomalyMat = SkColorFilters::Matrix(colorMatrix);
255     return protanomalyMat;
256 }
257 #else
ProtanomalyMat()258 static const std::shared_ptr<Drawing::ColorFilter>& ProtanomalyMat()
259 {
260     static const Drawing::scalar colorMatrixArray[MATRIX_SIZE] = {
261         0.622,  0.377,  0.0, 0.0, 0.0,
262         0.264,  0.736,  0.0, 0.0, 0.0,
263         0.217,  -0.217, 1.0, 0.0, 0.0,
264         0.0,    0.0,    0.0, 1.0, 0.0
265     };
266     Drawing::ColorMatrix colorMatrix;
267     colorMatrix.SetArray(colorMatrixArray);
268     static auto protanomalyMat = Drawing::ColorFilter::CreateMatrixColorFilter(colorMatrix);
269     return protanomalyMat;
270 }
271 #endif
272 
273 #ifndef USE_ROSEN_DRAWING
DeuteranomalyMat()274 static const sk_sp<SkColorFilter>& DeuteranomalyMat()
275 {
276     static const SkScalar colorMatrix[MATRIX_SIZE] = {
277         0.288,  0.712, 0.0, 0.0, 0.0,
278         0.053,  0.947, 0.0, 0.0, 0.0,
279         -0.258, 0.258, 1.0, 0.0, 0.0,
280         0.0,    0.0,   0.0, 1.0, 0.0
281     };
282     static auto deuteranomalyMat = SkColorFilters::Matrix(colorMatrix);
283     return deuteranomalyMat;
284 }
285 #else
DeuteranomalyMat()286 static const std::shared_ptr<Drawing::ColorFilter>& DeuteranomalyMat()
287 {
288     static const Drawing::scalar colorMatrixArray[MATRIX_SIZE] = {
289         0.288,  0.712, 0.0, 0.0, 0.0,
290         0.053,  0.947, 0.0, 0.0, 0.0,
291         -0.258, 0.258, 1.0, 0.0, 0.0,
292         0.0,    0.0,   0.0, 1.0, 0.0
293     };
294     Drawing::ColorMatrix colorMatrix;
295     colorMatrix.SetArray(colorMatrixArray);
296     static auto deuteranomalyMat = Drawing::ColorFilter::CreateMatrixColorFilter(colorMatrix);
297     return deuteranomalyMat;
298 }
299 #endif
300 
301 #ifndef USE_ROSEN_DRAWING
TritanomalyMat()302 static const sk_sp<SkColorFilter>& TritanomalyMat()
303 {
304     static const SkScalar colorMatrix[MATRIX_SIZE] = {
305         1.0, -0.806, 0.806, 0.0, 0.0,
306         0.0, 0.379,  0.621, 0.0, 0.0,
307         0.0, 0.105,  0.895, 0.0, 0.0,
308         0.0, 0.0,    0.0,   1.0, 0.0
309     };
310     static auto tritanomalyMat = SkColorFilters::Matrix(colorMatrix);
311     return tritanomalyMat;
312 }
313 #else
TritanomalyMat()314 static const std::shared_ptr<Drawing::ColorFilter>& TritanomalyMat()
315 {
316     static const Drawing::scalar colorMatrixArray[MATRIX_SIZE] = {
317         1.0, -0.806, 0.806, 0.0, 0.0,
318         0.0, 0.379,  0.621, 0.0, 0.0,
319         0.0, 0.105,  0.895, 0.0, 0.0,
320         0.0, 0.0,    0.0,   1.0, 0.0
321     };
322     Drawing::ColorMatrix colorMatrix;
323     colorMatrix.SetArray(colorMatrixArray);
324     static auto tritanomalyMat = Drawing::ColorFilter::CreateMatrixColorFilter(colorMatrix);
325     return tritanomalyMat;
326 }
327 #endif
328 
329 #ifndef USE_ROSEN_DRAWING
InvertProtanomalyMat()330 static const sk_sp<SkColorFilter>& InvertProtanomalyMat()
331 {
332     static const SkScalar colorMatrix[MATRIX_SIZE] = {
333         -0.109, -0.663, -0.228, 1.0, 0.0,
334         -0.468, -0.304, -0.228, 1.0, 0.0,
335         -0.516, -1.258, 0.772,  1.0, 0.0,
336         0.0,    0.0,    0.0,    1.0, 0.0
337     };
338     static auto invertProtanomalyMat = SkColorFilters::Matrix(colorMatrix);
339     return invertProtanomalyMat;
340 }
341 #else
InvertProtanomalyMat()342 static const std::shared_ptr<Drawing::ColorFilter>& InvertProtanomalyMat()
343 {
344     static const Drawing::scalar colorMatrixArray[MATRIX_SIZE] = {
345         0.025,  -0.796, -0.228, 1.0, 0.0,
346         -0.334, -0.438, -0.228, 1.0, 0.0,
347         -0.382, -1.392, 0.772,  1.0, 0.0,
348         0.0,    0.0,    0.0,    1.0, 0.0
349     };
350     Drawing::ColorMatrix colorMatrix;
351     colorMatrix.SetArray(colorMatrixArray);
352     static auto invertProtanomalyMat = Drawing::ColorFilter::CreateMatrixColorFilter(colorMatrix);
353     return invertProtanomalyMat;
354 }
355 #endif
356 
357 #ifndef USE_ROSEN_DRAWING
InvertDeuteranomalyMat()358 static const sk_sp<SkColorFilter>& InvertDeuteranomalyMat()
359 {
360     static const SkScalar colorMatrix[MATRIX_SIZE] = {
361         0.113,  -0.885, -0.228, 1.0, 0.0,
362         -0.123, -0.649, -0.228, 1.0, 0.0,
363         -0.434, -1.341, 0.772,  1.0, 0.0,
364         0.0,    0.0,    0.0,    1.0, 0.0
365     };
366     static auto invertDeuteranomalyMat = SkColorFilters::Matrix(colorMatrix);
367     return invertDeuteranomalyMat;
368 }
369 #else
InvertDeuteranomalyMat()370 static const std::shared_ptr<Drawing::ColorFilter>& InvertDeuteranomalyMat()
371 {
372     static const Drawing::scalar colorMatrixArray[MATRIX_SIZE] = {
373         -0.31,  -0.462, -0.228, 1.0, 0.0,
374         -0.545, -0.227, -0.228, 1.0, 0.0,
375         -0.857, -0.917, 0.772,  1.0, 0.0,
376         0.0,    0.0,    0.0,    1.0, 0.0
377     };
378     Drawing::ColorMatrix colorMatrix;
379     colorMatrix.SetArray(colorMatrixArray);
380     static auto invertDeuteranomalyMat = Drawing::ColorFilter::CreateMatrixColorFilter(colorMatrix);
381     return invertDeuteranomalyMat;
382 }
383 #endif
384 
385 #ifndef USE_ROSEN_DRAWING
InvertTritanomalyMat()386 static const sk_sp<SkColorFilter>& InvertTritanomalyMat()
387 {
388     static const SkScalar colorMatrix[MATRIX_SIZE] = {
389         0.402,  -0.792, -0.609, 1.0, 0.0,
390         -0.598, 0.392,  -0.794, 1.0, 0.0,
391         -0.598, 0.118,  -0.521, 1.0, 0.0,
392         0.0,    0.0,    0.0,    1.0, 0.0
393     };
394     static auto invertTritanomalyMat = SkColorFilters::Matrix(colorMatrix);
395     return invertTritanomalyMat;
396 }
397 #else
InvertTritanomalyMat()398 static const std::shared_ptr<Drawing::ColorFilter>& InvertTritanomalyMat()
399 {
400     static const Drawing::scalar colorMatrixArray[MATRIX_SIZE] = {
401         0.401,  -1.98,  0.578, 1.0, 0.0,
402         -0.599, -0.796, 0.393, 1.0, 0.0,
403         -0.599, -1.07,  0.667, 1.0, 0.0,
404         0.0,    0.0,    0.0,   1.0, 0.0
405     };
406     Drawing::ColorMatrix colorMatrix;
407     colorMatrix.SetArray(colorMatrixArray);
408     static auto invertTritanomalyMat = Drawing::ColorFilter::CreateMatrixColorFilter(colorMatrix);
409     return invertTritanomalyMat;
410 }
411 #endif
412 
413 class SimpleColorSpace {
414 public:
415     // 3 RGB basePoints and 1 whitePoint.
SimpleColorSpace(const std::array<Vector2f,3> & basePoints,const Vector2f & whitePoint,float gamma,PixelTransformFunc clamper=Saturate<float>)416     SimpleColorSpace(
417         const std::array<Vector2f, 3>& basePoints,
418         const Vector2f& whitePoint,
419         float gamma,
420         PixelTransformFunc clamper = Saturate<float>
421     ) noexcept
422         : rgbToXyz_(GenRGBToXYZMatrix(basePoints, whitePoint)),
423           xyzToRgb_(rgbToXyz_.Inverse()),
424           transEOTF_(GenEOTF(gamma)),
425           transOETF_(GenOETF(gamma)),
426           clamper_(std::move(clamper)),
427           transferParams_({ gamma, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f })
428     {
429     }
430 
SimpleColorSpace(const std::array<Vector2f,3> & basePoints,const Vector2f & whitePoint,const TransferParameters & parameters,PixelTransformFunc clamper=Saturate<float>)431     SimpleColorSpace(
432         const std::array<Vector2f, 3>& basePoints,
433         const Vector2f& whitePoint,
434         const TransferParameters& parameters,
435         PixelTransformFunc clamper = Saturate<float>
436     ) noexcept
437         : rgbToXyz_(GenRGBToXYZMatrix(basePoints, whitePoint)),
438           xyzToRgb_(rgbToXyz_.Inverse()),
439           transEOTF_(GenEOTF(parameters)),
440           transOETF_(GenOETF(parameters)),
441           clamper_(std::move(clamper)),
442           transferParams_(parameters)
443     {
444     }
445 
446     ~SimpleColorSpace() noexcept = default;
447 
ToneMapping(const Vector3f & color,float targetLum=0) const448     Vector3f ToneMapping(const Vector3f& color, float targetLum = 0) const
449     {
450         PixelTransformFunc toneMappingFunc = GenACESToneMapping(targetLum);
451         return ApplyTransForm(color, toneMappingFunc);
452     }
453 
ToLinear(const Vector3f & val) const454     Vector3f ToLinear(const Vector3f& val) const
455     {
456         return ApplyTransForm(val, transEOTF_);
457     }
458 
FromLinear(const Vector3f & val) const459     Vector3f FromLinear(const Vector3f& val) const
460     {
461         return ApplyTransForm(val, transOETF_);
462     }
463 
RGBToXYZ(const Vector3f & rgb) const464     Vector3f RGBToXYZ(const Vector3f& rgb) const
465     {
466         return rgbToXyz_ * ToLinear(rgb);
467     }
468 
XYZToRGB(const Vector3f & xyz) const469     Vector3f XYZToRGB(const Vector3f& xyz) const
470     {
471         return ApplyTransForm(FromLinear(xyzToRgb_ * xyz), clamper_);
472     }
473 
474 private:
475     Matrix3f rgbToXyz_;
476     Matrix3f xyzToRgb_;
477     PixelTransformFunc transEOTF_;
478     PixelTransformFunc transOETF_;
479     PixelTransformFunc clamper_;
480     TransferParameters transferParams_;
481 };
482 
GetSRGBColorSpace()483 SimpleColorSpace &GetSRGBColorSpace()
484 {
485     static SimpleColorSpace sRGB {
486         {{Vector2f{0.640f, 0.330f}, {0.300f, 0.600f}, {0.150f, 0.060f}}}, // rgb base points.
487         {0.3127f, 0.3290f}, // white points.
488         {2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.04045f, 0.0f, 0.0f}}; // TransferParameters
489     return sRGB;
490 }
491 
GetAdobeRGBColorSpace()492 SimpleColorSpace &GetAdobeRGBColorSpace()
493 {
494     static SimpleColorSpace adobeRGB {
495         {{Vector2f{0.64f, 0.33f}, {0.21f, 0.71f}, {0.15f, 0.06f}}}, // rgb base points.
496         {0.3127f, 0.3290f}, // white points.
497         2.2f}; // gamma 2.2
498     return adobeRGB;
499 }
500 
GetDisplayP3ColorSpace()501 SimpleColorSpace &GetDisplayP3ColorSpace()
502 {
503     static SimpleColorSpace displayP3 {
504         {{Vector2f{0.680f, 0.320f}, {0.265f, 0.690f}, {0.150f, 0.060f}}}, // rgb base points.
505         {0.3127f, 0.3290f}, // white points.
506         {2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.039f, 0.0f, 0.0f}}; // TransferParameters
507     return displayP3;
508 }
509 
GetDCIP3ColorSpace()510 SimpleColorSpace &GetDCIP3ColorSpace()
511 {
512     static SimpleColorSpace dciP3 {
513         {{Vector2f{0.680f, 0.320f}, {0.265f, 0.690f}, {0.150f, 0.060f}}}, // rgb base points.
514         {0.314f, 0.351f}, // white points.
515         2.6f}; // gamma 2.6
516     return dciP3;
517 }
518 
GetBT2020ColorSpace()519 SimpleColorSpace &GetBT2020ColorSpace()
520 {
521     static SimpleColorSpace bt2020 {
522         {{Vector2f{0.708f, 0.292f}, {0.17f, 0.797f}, {0.131f, 0.046f}}}, // BT.2020 rgb base points.
523         {0.3127f, 0.3290f}, // BT.2020 white points.
524         {-2.0f, 0.1593017578125, 78.84375, 0.8359375, 18.8515625, 18.6875, 0.f}}; // PQ TransferParameters
525     return bt2020;
526 }
527 
IsValidMetaData(const std::vector<GraphicHDRMetaData> & metaDatas)528 bool IsValidMetaData(const std::vector<GraphicHDRMetaData> &metaDatas)
529 {
530     uint16_t validFlag = 0;
531     for (auto metaData : metaDatas) {
532         validFlag ^= 1 << metaData.key;
533     }
534 
535     uint16_t bitsToCheck = 0xFF;
536     // has complete and unique primaries;
537     return (validFlag & bitsToCheck) == bitsToCheck;
538 }
539 
GetColorSpaceFromMetaData(const std::vector<GraphicHDRMetaData> & metaDatas,float targetLum=0)540 SimpleColorSpace &GetColorSpaceFromMetaData(const std::vector<GraphicHDRMetaData> &metaDatas, float targetLum = 0)
541 {
542     std::vector<GraphicHDRMetaData> metaDataSorted = metaDatas;
543     std::sort(metaDataSorted.begin(), metaDataSorted.end(),
544               [&](const GraphicHDRMetaData &a, const GraphicHDRMetaData &b)->bool {
545             return a.key < b.key;
546     });
547     static SimpleColorSpace hdrPq {
548          // rgb base points.
549         {{Vector2f{metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_RED_PRIMARY_X].value,
550                    metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_RED_PRIMARY_Y].value},
551                   {metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_GREEN_PRIMARY_X].value,
552                    metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_GREEN_PRIMARY_Y].value},
553                   {metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_BLUE_PRIMARY_X].value,
554                    metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_BLUE_PRIMARY_Y].value}}},
555         {metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_WHITE_PRIMARY_X].value,
556          metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_WHITE_PRIMARY_Y].value}, // white points.
557         {-2.0f, 0.1593017578125, 78.84375, 0.8359375, 18.8515625, 18.6875, 0.f}}; // PQ TransferParameters
558     return hdrPq;
559 }
560 
GetHdrPqColorSpace(const std::vector<GraphicHDRMetaData> & metaData,float targetLum=0.f)561 SimpleColorSpace &GetHdrPqColorSpace(const std::vector<GraphicHDRMetaData> &metaData, float targetLum = 0.f)
562 {
563     if (metaData.size() > 0 && IsValidMetaData(metaData)) {
564         return GetColorSpaceFromMetaData(metaData, targetLum);
565     }
566 
567     return GetBT2020ColorSpace();
568 }
569 
IsSupportedFormatForGamutConversion(int32_t pixelFormat)570 bool IsSupportedFormatForGamutConversion(int32_t pixelFormat)
571 {
572     static std::unordered_set<GraphicPixelFormat> supportedFormats = {
573         GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBX_8888,
574         GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBA_8888,
575         GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGB_888,
576         GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BGRX_8888,
577         GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BGRA_8888
578     };
579 
580     // Because GraphicPixelFormat has no enumeration for RBG_16,
581     // we use a temporary stub here for testing
582     // The final version should use a GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBA_XXXX
583     return pixelFormat == STUB_PIXEL_FMT_RGBA_16161616 ||
584         supportedFormats.count(static_cast<GraphicPixelFormat>(pixelFormat)) > 0;
585 }
586 
IsSupportedColorGamut(GraphicColorGamut colorGamut)587 bool IsSupportedColorGamut(GraphicColorGamut colorGamut)
588 {
589     static std::unordered_set<GraphicColorGamut> supportedColorGamuts = {
590         GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
591         GraphicColorGamut::GRAPHIC_COLOR_GAMUT_ADOBE_RGB,
592         GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_P3,
593         GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DCI_P3,
594         GraphicColorGamut::GRAPHIC_COLOR_GAMUT_BT2020,
595         GraphicColorGamut::GRAPHIC_COLOR_GAMUT_BT2100_PQ
596     };
597     return supportedColorGamuts.count(colorGamut) > 0;
598 }
599 
GetColorSpaceOfCertainGamut(GraphicColorGamut colorGamut,const std::vector<GraphicHDRMetaData> & metaData={})600 SimpleColorSpace& GetColorSpaceOfCertainGamut(GraphicColorGamut colorGamut,
601                                               const std::vector<GraphicHDRMetaData> &metaData = {})
602 {
603     switch (colorGamut) {
604         case GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB: {
605             return GetSRGBColorSpace();
606         }
607         case GraphicColorGamut::GRAPHIC_COLOR_GAMUT_ADOBE_RGB: {
608             return GetAdobeRGBColorSpace();
609         }
610         case GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_P3:
611         case GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DCI_P3: {
612             return GetDisplayP3ColorSpace(); // Currently p3 colorspace is displayP3
613         }
614         case GraphicColorGamut::GRAPHIC_COLOR_GAMUT_BT2020:
615         case GraphicColorGamut::GRAPHIC_COLOR_GAMUT_BT2100_PQ: {
616             return GetHdrPqColorSpace(metaData);
617         }
618         default: {
619             return GetSRGBColorSpace();
620         }
621     }
622 }
623 
624 const uint16_t maxUint10 = 1023;
RGBUint8ToFloat(uint8_t val)625 float RGBUint8ToFloat(uint8_t val)
626 {
627     return val * 1.0f / 255.0f; // 255.0f is the max value.
628 }
629 
630 // Used to transfer integers of pictures with color depth of 10 bits to float
RGBUint10ToFloat(uint16_t val)631 float RGBUint10ToFloat(uint16_t val)
632 {
633     return val * 1.0f / maxUint10; // 1023.0f is the max value
634 }
635 
RGBFloatToUint8(float val)636 uint8_t RGBFloatToUint8(float val)
637 {
638     return static_cast<uint8_t>(Saturate(val) * 255 + 0.5f); // 255.0 is the max value, + 0.5f to avoid negative.
639 }
640 
641 // Used to transfer float values to integers for pictures with color depth of 10 bits
RGBFloatToUint10(float val)642 uint16_t RGBFloatToUint10(float val)
643 {
644     // 1023.0 is the max value, + 0.5f to avoid negative.
645     return static_cast<uint16_t>(Saturate(val) * maxUint10 + 0.5f);
646 }
647 
RGBUintToFloat(uint8_t * dst,uint8_t * src,int32_t pixelFormat,Vector3f & srcColor,Array3ptr & colorDst)648 Offset RGBUintToFloat(uint8_t* dst, uint8_t* src, int32_t pixelFormat, Vector3f &srcColor,
649     Array3ptr &colorDst)
650 {
651     // Because PixelFormat does not have enumeration for RGBA_16 or RGBA_1010102,
652     // we use two special IF statements here to realize the transfer process.
653     // They should to be adjusted to the SWITCH process after the enumerations are added.
654     if (pixelFormat == STUB_PIXEL_FMT_RGBA_16161616) {
655         auto src16 = reinterpret_cast<const uint16_t*>(src);
656         // R: src[0], G: src[1], B: src[2]
657         srcColor = {RGBUint10ToFloat(src16[0]), RGBUint10ToFloat(src16[1]), RGBUint10ToFloat(src16[2])};
658         // R: dst + 0, G: dst + 1, B: dst + 2
659         colorDst = {dst + 0, dst + 1, dst + 2};
660         // Alpha: linear transfer src[3] to dst[3]
661         dst[3] = RGBFloatToUint8(RGBUint10ToFloat(src16[3]));
662         const uint8_t outPixelBits = 4;
663         const uint8_t inPixelBits = 8;
664         // 8 bytes per pixel and HDR pictures are always redrawn as sRGB
665         return std::make_pair(inPixelBits, outPixelBits);
666     }
667     if (pixelFormat == STUB_PIXEL_FMT_RGBA_1010102) {
668         auto src32 = reinterpret_cast<const uint32_t*>(src);
669         // R: 0-9 bits, G: 10-19 ts, B: 20-29bits
670         srcColor = {RGBUint10ToFloat((*src32) & 0x3FF), RGBUint10ToFloat(((*src32) >> 10) & 0x3FF),
671              RGBUint10ToFloat(((*src32) >> 20) & 0x3FF)};
672         // R: dst + 0, G: dst + 1, B: dst + 2
673         colorDst = {dst + 0, dst + 1, dst + 2};
674         // Alpha: copy src[3] to dst[3]
675         const uint8_t rbgBitsNum = 30;
676         const uint8_t alphaBitMask = 0x3;
677         const uint8_t alphaPos = 3;
678         dst[alphaPos] = static_cast<uint8_t>(((*src32) >> rbgBitsNum) & alphaBitMask);
679         return std::make_pair(4, 4); // 4 bytes per pixel and HDR pictures are always redrawn as sRGB
680     }
681     switch (static_cast<GraphicPixelFormat>(pixelFormat)) {
682         case GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBX_8888:
683         case GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBA_8888: {
684             // R: src[0], G: src[1], B: src[2]
685             srcColor = {RGBUint8ToFloat(src[0]), RGBUint8ToFloat(src[1]), RGBUint8ToFloat(src[2])};
686             // R: dst + 0, G: dst + 1, B: dst + 2
687             colorDst = {dst + 0, dst + 1, dst + 2};
688             // Alpha: copy src[3] to dst[3]
689             dst[3] = src[3];
690             return std::make_pair(4, 4); // 4 bytes per pixel.
691         }
692         case GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGB_888: {
693             // R: src[0], G: src[1], B: src[2]
694             srcColor = {RGBUint8ToFloat(src[0]), RGBUint8ToFloat(src[1]), RGBUint8ToFloat(src[2])};
695             // R: dst + 0, G: dst + 1, B: dst + 2
696             colorDst = {dst + 0, dst + 1, dst + 2};
697             return std::make_pair(3, 3); // 3 bytes per pixel.
698         }
699         case GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BGRX_8888:
700         case GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BGRA_8888: {
701             // R: src[2], G: src[1], B: src[0]
702             srcColor = {RGBUint8ToFloat(src[2]), RGBUint8ToFloat(src[1]), RGBUint8ToFloat(src[0])};
703             // R: dst + 2, G: dst + 1, B: dst + 0
704             colorDst = {dst + 2, dst + 1, dst + 0};
705             // Alpha: copy src[3] to dst[3]
706             dst[3] = src[3];
707             return std::make_pair(4, 4); // 4 bytes per pixel.
708         }
709         default: {
710             RS_LOGE("RGBUintToFloat: unexpected pixelFormat(%d).", pixelFormat);
711             return std::make_pair(0, 0);
712         }
713     }
714 }
715 
ConvertColorGamut(uint8_t * dst,uint8_t * src,int32_t pixelFormat,SimpleColorSpace & srcColorSpace,SimpleColorSpace & dstColorSpace)716 Offset ConvertColorGamut(uint8_t* dst, uint8_t* src, int32_t pixelFormat, SimpleColorSpace& srcColorSpace,
717     SimpleColorSpace& dstColorSpace)
718 {
719     Vector3f srcColor;
720     Array3ptr colorDst; // color dst, 3 bytes (R G B).
721 
722     Offset len = RGBUintToFloat(dst, src, pixelFormat, srcColor, colorDst);
723     Vector3f outColor = dstColorSpace.XYZToRGB(srcColorSpace.RGBToXYZ(srcColor));
724     *(colorDst[0]) = RGBFloatToUint8(outColor[0]); // outColor 0 to colorDst[0]
725     *(colorDst[1]) = RGBFloatToUint8(outColor[1]); // outColor 1 to colorDst[1]
726     *(colorDst[2]) = RGBFloatToUint8(outColor[2]); // outColor 2 to colorDst[2]
727 
728     return len;
729 }
730 
ConvertBufferColorGamut(std::vector<uint8_t> & dstBuf,const sptr<OHOS::SurfaceBuffer> & srcBuf,GraphicColorGamut srcGamut,GraphicColorGamut dstGamut,const std::vector<GraphicHDRMetaData> & metaDatas)731 bool ConvertBufferColorGamut(std::vector<uint8_t>& dstBuf, const sptr<OHOS::SurfaceBuffer>& srcBuf,
732     GraphicColorGamut srcGamut, GraphicColorGamut dstGamut, const std::vector<GraphicHDRMetaData>& metaDatas)
733 {
734     RS_TRACE_NAME("ConvertBufferColorGamut");
735 
736     int32_t pixelFormat = srcBuf->GetFormat();
737     if (!IsSupportedFormatForGamutConversion(pixelFormat)) {
738         RS_LOGE("ConvertBufferColorGamut: the buffer's format is not supported.");
739         return false;
740     }
741     if (!IsSupportedColorGamut(srcGamut) || !IsSupportedColorGamut(dstGamut)) {
742         return false;
743     }
744 
745     uint32_t bufferSize = srcBuf->GetSize();
746     dstBuf.resize(bufferSize);
747 
748     auto bufferAddr = srcBuf->GetVirAddr();
749     uint8_t* srcStart = static_cast<uint8_t*>(bufferAddr);
750 
751     uint32_t offsetDst = 0, offsetSrc = 0;
752     auto& srcColorSpace = GetColorSpaceOfCertainGamut(srcGamut, metaDatas);
753     auto& dstColorSpace = GetColorSpaceOfCertainGamut(dstGamut, metaDatas);
754     while (offsetSrc < bufferSize) {
755         uint8_t* dst = &dstBuf[offsetDst];
756         uint8_t* src = srcStart + offsetSrc;
757         Offset len = ConvertColorGamut(dst, src, pixelFormat, srcColorSpace, dstColorSpace);
758         if (len.first == 0 || len.second == 0) {
759             return false;
760         }
761         offsetSrc += len.first;
762         offsetDst += len.second;
763     }
764     dstBuf.resize(offsetDst); // dstBuf size might not be as large ad srcBuf in HDR
765 
766     return true;
767 }
768 
769 #ifndef USE_ROSEN_DRAWING
GenerateSkImageInfo(const sptr<OHOS::SurfaceBuffer> & buffer)770 SkImageInfo GenerateSkImageInfo(const sptr<OHOS::SurfaceBuffer>& buffer)
771 {
772     SkColorType colorType = (buffer->GetFormat() == GRAPHIC_PIXEL_FMT_BGRA_8888) ?
773         kBGRA_8888_SkColorType : kRGBA_8888_SkColorType;
774     return SkImageInfo::Make(buffer->GetWidth(), buffer->GetHeight(),
775         colorType, kPremul_SkAlphaType);
776 }
777 #else
GenerateDrawingBitmapFormat(const sptr<OHOS::SurfaceBuffer> & buffer)778 Drawing::BitmapFormat GenerateDrawingBitmapFormat(const sptr<OHOS::SurfaceBuffer>& buffer)
779 {
780     Drawing::ColorType colorType = (buffer->GetFormat() == GRAPHIC_PIXEL_FMT_BGRA_8888) ?
781         Drawing::ColorType::COLORTYPE_BGRA_8888 : Drawing::ColorType::COLORTYPE_RGBA_8888;
782     Drawing::AlphaType alphaType = Drawing::AlphaType::ALPHATYPE_PREMUL;
783     Drawing::BitmapFormat format { colorType, alphaType };
784     return format;
785 }
786 #endif
787 
788 // YUV to RGBA: Pixel value conversion table
789 static int Table_fv1[256] = { -180, -179, -177, -176, -174, -173, -172, -170, -169, -167, -166, -165, -163, -162,
790     -160, -159, -158, -156, -155, -153, -152, -151, -149, -148, -146, -145, -144, -142, -141, -139,
791     -138, -137,  -135, -134, -132, -131, -130, -128, -127, -125, -124, -123, -121, -120, -118,
792     -117, -115, -114, -113, -111, -110, -108, -107, -106, -104, -103, -101, -100, -99, -97, -96,
793     -94, -93, -92, -90,  -89, -87, -86, -85, -83, -82, -80, -79, -78, -76, -75, -73, -72, -71,
794     -69, -68, -66, -65, -64, -62, -61, -59, -58, -57, -55, -54, -52, -51, -50, -48, -47, -45,
795     -44, -43, -41, -40, -38, -37,  -36, -34, -33, -31, -30, -29, -27, -26, -24, -23, -22, -20,
796     -19, -17, -16, -15, -13, -12, -10, -9, -8, -6, -5, -3, -2, 0, 1, 2, 4, 5, 7, 8, 9, 11, 12,
797     14, 15, 16, 18, 19, 21, 22, 23, 25, 26, 28, 29, 30, 32, 33, 35, 36, 37, 39, 40, 42, 43, 44,
798     46, 47, 49, 50, 51, 53, 54, 56, 57, 58, 60, 61, 63, 64, 65, 67, 68, 70, 71, 72, 74, 75, 77,
799     78, 79, 81, 82, 84, 85, 86, 88, 89, 91, 92, 93, 95, 96, 98, 99, 100, 102, 103, 105, 106, 107,
800     109, 110, 112, 113, 114, 116, 117, 119, 120, 122, 123, 124, 126, 127, 129, 130, 131, 133, 134,
801     136, 137, 138, 140, 141, 143, 144, 145, 147, 148,  150, 151, 152, 154, 155, 157, 158, 159, 161,
802     162, 164, 165, 166, 168, 169, 171, 172, 173, 175, 176, 178 };
803 static int Table_fv2[256] = { -92, -91, -91, -90, -89, -88, -88, -87, -86, -86, -85, -84, -83, -83, -82, -81,
804     -81, -80, -79, -78, -78, -77, -76, -76, -75, -74, -73, -73, -72, -71, -71, -70, -69, -68, -68, -67, -66,
805     -66, -65, -64, -63, -63, -62, -61, -61, -60, -59, -58, -58, -57, -56, -56, -55, -54, -53, -53, -52, -51,
806     -51, -50, -49, -48, -48, -47, -46, -46, -45, -44, -43, -43, -42, -41, -41, -40, -39, -38, -38, -37, -36,
807     -36, -35, -34, -33, -33, -32, -31, -31, -30, -29, -28, -28, -27, -26, -26, -25, -24, -23, -23, -22, -21,
808     -21, -20, -19, -18, -18, -17, -16, -16, -15, -14, -13, -13, -12, -11, -11, -10, -9, -8, -8, -7, -6, -6,
809     -5, -4, -3, -3, -2, -1, 0, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 11, 12, 12, 13, 14, 15, 15, 16,
810     17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24, 25, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 35,
811     36, 37, 37, 38, 39, 40, 40, 41, 42, 42, 43, 44, 45, 45, 46, 47, 47, 48, 49, 50, 50, 51, 52, 52, 53, 54, 55,
812     55, 56, 57, 57, 58, 59, 60, 60, 61, 62, 62, 63, 64, 65, 65, 66, 67, 67, 68, 69, 70, 70, 71, 72, 72, 73, 74,
813     75, 75, 76, 77, 77, 78, 79, 80, 80, 81, 82, 82, 83, 84, 85, 85, 86, 87, 87, 88, 89, 90, 90 };
814 static int Table_fu1[256] = { -44, -44, -44, -43, -43, -43, -42, -42, -42, -41, -41, -41, -40, -40, -40, -39, -39,
815     -39, -38, -38, -38, -37, -37, -37, -36, -36, -36, -35, -35, -35, -34, -34, -33, -33, -33, -32, -32, -32, -31,
816     -31, -31, -30, -30, -30, -29, -29, -29, -28, -28, -28, -27, -27, -27, -26, -26, -26, -25, -25, -25, -24, -24,
817     -24, -23, -23, -22, -22, -22, -21, -21, -21, -20, -20, -20, -19, -19, -19, -18, -18, -18, -17, -17, -17, -16,
818     -16, -16, -15, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -11, -11, -11, -10, -10, -10, -9, -9, -9, -8,
819     -8, -8, -7, -7, -7, -6, -6, -6, -5, -5, -5, -4, -4, -4, -3, -3, -3, -2, -2, -2, -1, -1, 0, 0, 0, 1, 1, 1, 2, 2,
820     2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13,
821     14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, 22, 23,
822     23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32,
823     32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41,
824     41, 42, 42, 42, 43, 43 };
825 static int Table_fu2[256] = { -227, -226, -224, -222, -220, -219, -217, -215, -213, -212, -210, -208, -206, -204,
826     -203, -201, -199, -197, -196, -194, -192, -190, -188, -187, -185, -183, -181, -180, -178, -176, -174, -173,
827     -171, -169, -167, -165, -164, -162, -160, -158, -157, -155, -153, -151, -149, -148, -146, -144, -142, -141,
828     -139, -137, -135, -134, -132, -130, -128, -126, -125, -123, -121, -119, -118, -116, -114, -112, -110, -109,
829     -107, -105, -103, -102, -100, -98, -96, -94, -93, -91, -89, -87, -86, -84, -82, -80, -79, -77, -75, -73,
830     -71, -70, -68, -66, -64, -63, -61, -59, -57, -55, -54, -52, -50, -48, -47, -45, -43, -41, -40, -38, -36,
831     -34, -32, -31, -29, -27, -25, -24, -22, -20, -18, -16, -15, -13, -11, -9, -8, -6, -4, -2, 0, 1, 3, 5, 7, 8,
832     10, 12, 14, 15, 17, 19, 21, 23, 24, 26, 28, 30, 31, 33, 35, 37, 39, 40, 42, 44, 46, 47, 49, 51, 53, 54, 56,
833     58, 60, 62, 63, 65, 67, 69, 70, 72, 74, 76, 78, 79, 81, 83, 85, 86, 88, 90, 92, 93, 95, 97, 99, 101, 102,
834     104, 106, 108, 109, 111, 113, 115, 117, 118, 120, 122, 124, 125, 127, 129, 131, 133, 134, 136, 138, 140, 141,
835     143, 145, 147, 148, 150, 152, 154, 156, 157, 159, 161, 163, 164, 166, 168, 170, 172, 173, 175, 177, 179, 180,
836     182, 184, 186, 187, 189, 191, 193, 195, 196, 198, 200, 202, 203, 205, 207, 209, 211, 212, 214, 216, 218,
837     219, 221, 223, 225 };
838 
ConvertYUV420SPToRGBA(std::vector<uint8_t> & rgbaBuf,const sptr<OHOS::SurfaceBuffer> & srcBuf)839 bool ConvertYUV420SPToRGBA(std::vector<uint8_t>& rgbaBuf, const sptr<OHOS::SurfaceBuffer>& srcBuf)
840 {
841     if (srcBuf == nullptr || rgbaBuf.empty()) {
842         RS_LOGE("RSBaseRenderUtil::ConvertYUV420SPToRGBA invalid params");
843         return false;
844     }
845     uint8_t* rgbaDst = &rgbaBuf[0];
846     uint8_t* src = static_cast<uint8_t*>(srcBuf->GetVirAddr());
847     if (src == nullptr || rgbaDst == nullptr) {
848         RS_LOGE("RSBaseRenderUtil::ConvertYUV420SPToRGBA null buffer ptr");
849         return false;
850     }
851     int32_t bufferWidth = srcBuf->GetWidth();
852     int32_t bufferHeight = srcBuf->GetHeight();
853     int32_t bufferStride = srcBuf->GetStride();
854     int32_t bufferSize = static_cast<int32_t>(srcBuf->GetSize());
855     if (bufferWidth < 1 || bufferHeight < 1 || bufferStride < 1 || bufferSize < 1) {
856         RS_LOGE("RSBaseRenderUtil::ConvertYUV420SPToRGBA invalid buffer size, w/h/stride/size = [%d, %d, %d, %d]",
857             bufferWidth, bufferHeight, bufferStride, bufferSize);
858         return false;
859     }
860 #ifdef PADDING_HEIGHT_32
861     // temporally only update buffer len for video stream
862     if (srcBuf->GetFormat() == GRAPHIC_PIXEL_FMT_YCBCR_420_SP) {
863         int32_t paddingBase = 32;
864         bufferHeight = ((bufferHeight - 1) / paddingBase + 1) * paddingBase;
865     }
866 #endif
867     float yuvSizeFactor = 1.5f; // y:uv = 2:1
868     int32_t len = bufferStride * bufferHeight;
869     int32_t totalLen = static_cast<int32_t>(len * yuvSizeFactor);
870     if (bufferSize < totalLen) {
871         RS_LOGE("RSBaseRenderUtil::ConvertYUV420SPToRGBA invalid buffer size, "
872             "w/h/stride/size/totalLen = [%d, %d, %d, %d, %d]",
873             bufferWidth, srcBuf->GetHeight(), bufferStride, bufferSize, totalLen);
874         return false;
875     }
876     uint8_t* ybase = src;
877     uint8_t* ubase = &src[len];
878 
879     int rgb[3] = {0, 0, 0};
880     int idx = 0;
881     int rdif = 0;
882     int invgdif = 0;
883     int bdif = 0;
884     for (int i = 0; i < bufferHeight; i++) {
885         for (int j = 0; j < bufferWidth; j++) {
886             int Y = static_cast<int>(ybase[i * bufferStride + j]);
887             int U = static_cast<int>(ubase[i / 2 * bufferStride + (j / 2) * 2 + 1]);
888             int V = static_cast<int>(ubase[i / 2 * bufferStride + (j / 2) * 2]);
889             if (srcBuf->GetFormat() == GRAPHIC_PIXEL_FMT_YCBCR_420_SP) {
890                 std::swap(U, V);
891             }
892             rdif = Table_fv1[V];
893             invgdif = Table_fu1[U] + Table_fv2[V];
894             bdif = Table_fu2[U];
895 
896             rgb[0] = Y + rdif;
897             rgb[1] = Y - invgdif;
898             rgb[2] = Y + bdif; // 2 is index
899 
900             for (int k = 0; k < 3; k++) { // 3 is index
901                 idx = (i * bufferWidth + j) * 4 + k; // 4 is color channel
902                 if (rgb[k] >= 0 && rgb[k] <= 255) { // 255 is upper threshold
903                     rgbaDst[idx] = static_cast<uint8_t>(rgb[k]);
904                 } else {
905                     rgbaDst[idx] = (rgb[k] < 0) ? 0 : 255; // 255 is upper threshold
906                 }
907             }
908             ++idx;
909             rgbaDst[idx] = 255; // 255 is upper threshold
910         }
911     }
912     return true;
913 }
914 } // namespace Detail
915 
916 bool RSBaseRenderUtil::enableClient = false;
917 
SetNeedClient(bool flag)918 void RSBaseRenderUtil::SetNeedClient(bool flag)
919 {
920     enableClient = flag;
921 }
922 
IsNeedClient(RSRenderNode & node,const ComposeInfo & info)923 bool RSBaseRenderUtil::IsNeedClient(RSRenderNode& node, const ComposeInfo& info)
924 {
925     if (IsForceClient()) {
926         RS_LOGD("RsDebug RSBaseRenderUtil::IsNeedClient: client composition is force enabled.");
927         return true;
928     }
929 
930     if (enableClient) {
931         RS_LOGD("RsDebug RSBaseRenderUtil::IsNeedClient enable composition client");
932         return true;
933     }
934 
935     const auto& property = node.GetRenderProperties();
936 #ifndef USE_ROSEN_DRAWING
937     auto backgroundColor = static_cast<SkColor>(property.GetBackgroundColor().AsArgbInt());
938     // If node's gravity is not RESIZE and backgroundColor is not transparent,
939     // we check the src and dst size to decide whether to use client composition or not.
940     if (property.GetFrameGravity() != Gravity::RESIZE && SkColorGetA(backgroundColor) != SK_AlphaTRANSPARENT &&
941         (info.srcRect.w != info.dstRect.w || info.srcRect.h != info.dstRect.h)) {
942         return true;
943     }
944 #else
945     auto backgroundColor = static_cast<Drawing::ColorQuad>(property.GetBackgroundColor().AsArgbInt());
946     // If node's gravity is not RESIZE and backgroundColor is not transparent,
947     // we check the src and dst size to decide whether to use client composition or not.
948     if (property.GetFrameGravity() != Gravity::RESIZE &&
949             Drawing::Color::ColorQuadGetA(backgroundColor) != Drawing::Color::COLOR_TRANSPARENT &&
950         (info.srcRect.w != info.dstRect.w || info.srcRect.h != info.dstRect.h)) {
951         return true;
952     }
953 #endif
954 
955     if (property.GetBackgroundFilter() || property.GetFilter()) {
956         RS_LOGD("RsDebug RSBaseRenderUtil::IsNeedClient enable composition client need filter");
957         return true;
958     }
959 
960     if (!property.GetCornerRadius().IsZero()) {
961         RS_LOGD("RsDebug RSBaseRenderUtil::IsNeedClient enable composition client need round corner");
962         return true;
963     }
964     if (property.IsShadowValid()) {
965         RS_LOGD("RsDebug RSBaseRenderUtil::IsNeedClient enable composition client need shadow");
966         return true;
967     }
968     if (node.IsInstanceOf<RSSurfaceRenderNode>() &&
969         (property.GetRotation() != 0 || property.GetRotationX() != 0 || property.GetRotationY() != 0 ||
970         property.GetQuaternion() != Quaternion())) {
971         RS_LOGD("RsDebug RSBaseRenderUtil::IsNeedClient enable composition client need RSSurfaceRenderNode rotation");
972         return true;
973     }
974     return false;
975 }
976 
IsForceClient()977 bool RSBaseRenderUtil::IsForceClient()
978 {
979     return (std::atoi((system::GetParameter("rosen.client_composition.enabled", "0")).c_str()) != 0);
980 }
981 
GetFrameBufferRequestConfig(const ScreenInfo & screenInfo,bool isPhysical)982 BufferRequestConfig RSBaseRenderUtil::GetFrameBufferRequestConfig(
983     const ScreenInfo& screenInfo, bool isPhysical)
984 {
985     BufferRequestConfig config {};
986     const auto width = isPhysical ? screenInfo.width : screenInfo.GetRotatedWidth();
987     const auto height = isPhysical ? screenInfo.height : screenInfo.GetRotatedHeight();
988     config.width = static_cast<int32_t>(width);
989     config.height = static_cast<int32_t>(height);
990     config.strideAlignment = 0x8; // default stride is 8 Bytes.
991     config.format = GRAPHIC_PIXEL_FMT_RGBA_8888;
992     config.usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_FB;
993     config.timeout = 0;
994     return config;
995 }
996 
DropFrameProcess(RSSurfaceHandler & node)997 GSError RSBaseRenderUtil::DropFrameProcess(RSSurfaceHandler& node)
998 {
999     auto availableBufferCnt = node.GetAvailableBufferCount();
1000     const auto& surfaceConsumer = node.GetConsumer();
1001     if (surfaceConsumer == nullptr) {
1002         RS_LOGE("RsDebug RSBaseRenderUtil::DropFrameProcess (node: %" PRIu64 "): surfaceConsumer is null!",
1003             node.GetNodeId());
1004         return OHOS::GSERROR_NO_CONSUMER;
1005     }
1006 
1007     int32_t maxDirtyListSize = static_cast<int32_t>(surfaceConsumer->GetQueueSize()) - 1;
1008     // maxDirtyListSize > 2 means QueueSize >3 too
1009     if (maxDirtyListSize > 2 && availableBufferCnt >= maxDirtyListSize) {
1010         RS_TRACE_NAME("DropFrame");
1011         OHOS::sptr<SurfaceBuffer> cbuffer;
1012         Rect damage;
1013         sptr<SyncFence> acquireFence = SyncFence::INVALID_FENCE;
1014         int64_t timestamp = 0;
1015         auto ret = surfaceConsumer->AcquireBuffer(cbuffer, acquireFence, timestamp, damage);
1016         if (ret != OHOS::SURFACE_ERROR_OK) {
1017             RS_LOGW("RSBaseRenderUtil::DropFrameProcess(node: %" PRIu64 "): AcquireBuffer failed(ret: %d), do nothing ",
1018                 node.GetNodeId(), ret);
1019             return OHOS::GSERROR_NO_BUFFER;
1020         }
1021 
1022         ret = surfaceConsumer->ReleaseBuffer(cbuffer, SyncFence::INVALID_FENCE);
1023         if (ret != OHOS::SURFACE_ERROR_OK) {
1024             RS_LOGW("RSBaseRenderUtil::DropFrameProcess(node: %" PRIu64
1025                     "): ReleaseBuffer failed(ret: %d), Acquire done ",
1026                 node.GetNodeId(), ret);
1027         }
1028         node.ReduceAvailableBuffer();
1029         RS_LOGD("RsDebug RSBaseRenderUtil::DropFrameProcess (node: %" PRIu64 "), drop one frame", node.GetNodeId());
1030     }
1031 
1032     return OHOS::GSERROR_OK;
1033 }
1034 
ConsumeAndUpdateBuffer(RSSurfaceHandler & surfaceHandler)1035 bool RSBaseRenderUtil::ConsumeAndUpdateBuffer(RSSurfaceHandler& surfaceHandler)
1036 {
1037     auto availableBufferCnt = surfaceHandler.GetAvailableBufferCount();
1038     if (availableBufferCnt <= 0) {
1039         // this node has no new buffer, try use old buffer.
1040         return true;
1041     }
1042     auto& consumer = surfaceHandler.GetConsumer();
1043     if (consumer == nullptr) {
1044         return false;
1045     }
1046 
1047     DropFrameProcess(surfaceHandler);
1048     sptr<SurfaceBuffer> buffer;
1049     sptr<SyncFence> acquireFence = SyncFence::INVALID_FENCE;
1050     int64_t timestamp = 0;
1051     Rect damage;
1052     auto ret = consumer->AcquireBuffer(buffer, acquireFence, timestamp, damage);
1053     if (buffer == nullptr || ret != SURFACE_ERROR_OK) {
1054         RS_LOGE("RsDebug surfaceHandler(id: %" PRIu64 ") AcquireBuffer failed(ret: %d)!",
1055             surfaceHandler.GetNodeId(), ret);
1056         return false;
1057     }
1058 
1059     surfaceHandler.SetBuffer(buffer, acquireFence, damage, timestamp);
1060     surfaceHandler.SetCurrentFrameBufferConsumed();
1061     RS_LOGD("RsDebug surfaceHandler(id: %" PRIu64 ") AcquireBuffer success, timestamp = %" PRId64 ".",
1062         surfaceHandler.GetNodeId(), timestamp);
1063     surfaceHandler.ReduceAvailableBuffer();
1064     return true;
1065 }
1066 
ReleaseBuffer(RSSurfaceHandler & surfaceHandler)1067 bool RSBaseRenderUtil::ReleaseBuffer(RSSurfaceHandler& surfaceHandler)
1068 {
1069     auto& consumer = surfaceHandler.GetConsumer();
1070     if (consumer == nullptr) {
1071         return false;
1072     }
1073 
1074     auto& preBuffer = surfaceHandler.GetPreBuffer();
1075     if (preBuffer.buffer != nullptr) {
1076         auto ret = consumer->ReleaseBuffer(preBuffer.buffer, preBuffer.releaseFence);
1077         if (ret != OHOS::SURFACE_ERROR_OK) {
1078             RS_LOGE("RsDebug surfaceHandler(id: %" PRIu64 ") ReleaseBuffer failed(ret: %d)!",
1079                 surfaceHandler.GetNodeId(), ret);
1080             return false;
1081         }
1082         // reset prevBuffer if we release it successfully,
1083         // to avoid releasing the same buffer next frame in some situations.
1084         preBuffer.Reset();
1085     }
1086 
1087     return true;
1088 }
1089 
IsColorFilterModeValid(ColorFilterMode mode)1090 bool RSBaseRenderUtil::IsColorFilterModeValid(ColorFilterMode mode)
1091 {
1092     bool valid = false;
1093     switch (mode) {
1094         case ColorFilterMode::INVERT_COLOR_DISABLE_MODE:
1095         case ColorFilterMode::INVERT_COLOR_ENABLE_MODE:
1096         case ColorFilterMode::DALTONIZATION_PROTANOMALY_MODE:
1097         case ColorFilterMode::DALTONIZATION_DEUTERANOMALY_MODE:
1098         case ColorFilterMode::DALTONIZATION_TRITANOMALY_MODE:
1099         case ColorFilterMode::INVERT_DALTONIZATION_PROTANOMALY_MODE:
1100         case ColorFilterMode::INVERT_DALTONIZATION_DEUTERANOMALY_MODE:
1101         case ColorFilterMode::INVERT_DALTONIZATION_TRITANOMALY_MODE:
1102         case ColorFilterMode::DALTONIZATION_NORMAL_MODE:
1103         case ColorFilterMode::COLOR_FILTER_END:
1104             valid = true;
1105             break;
1106         default:
1107             valid = false;
1108     }
1109     return valid;
1110 }
1111 
1112 #ifndef USE_ROSEN_DRAWING
SetColorFilterModeToPaint(ColorFilterMode colorFilterMode,SkPaint & paint)1113 void RSBaseRenderUtil::SetColorFilterModeToPaint(ColorFilterMode colorFilterMode, SkPaint& paint)
1114 {
1115     switch (colorFilterMode) {
1116         case ColorFilterMode::INVERT_COLOR_ENABLE_MODE:
1117             paint.setColorFilter(Detail::InvertColorMat());
1118             break;
1119         case ColorFilterMode::DALTONIZATION_PROTANOMALY_MODE:
1120             paint.setColorFilter(Detail::ProtanomalyMat());
1121             break;
1122         case ColorFilterMode::DALTONIZATION_DEUTERANOMALY_MODE:
1123             paint.setColorFilter(Detail::DeuteranomalyMat());
1124             break;
1125         case ColorFilterMode::DALTONIZATION_TRITANOMALY_MODE:
1126             paint.setColorFilter(Detail::TritanomalyMat());
1127             break;
1128         case ColorFilterMode::INVERT_DALTONIZATION_PROTANOMALY_MODE:
1129             paint.setColorFilter(Detail::InvertProtanomalyMat());
1130             break;
1131         case ColorFilterMode::INVERT_DALTONIZATION_DEUTERANOMALY_MODE:
1132             paint.setColorFilter(Detail::InvertDeuteranomalyMat());
1133             break;
1134         case ColorFilterMode::INVERT_DALTONIZATION_TRITANOMALY_MODE:
1135             paint.setColorFilter(Detail::InvertTritanomalyMat());
1136             break;
1137         // INVERT_COLOR_DISABLE_MODE and DALTONIZATION_NORMAL_MODE couldn't be in this process
1138         case ColorFilterMode::INVERT_COLOR_DISABLE_MODE:
1139         case ColorFilterMode::DALTONIZATION_NORMAL_MODE:
1140         case ColorFilterMode::COLOR_FILTER_END:
1141         default:
1142             paint.setColorFilter(nullptr);
1143     }
1144 }
1145 #else
SetColorFilterModeToPaint(ColorFilterMode colorFilterMode,Drawing::Brush & paint)1146 void RSBaseRenderUtil::SetColorFilterModeToPaint(ColorFilterMode colorFilterMode, Drawing::Brush& paint)
1147 {
1148     Drawing::Filter filter;
1149     switch (colorFilterMode) {
1150         case ColorFilterMode::INVERT_COLOR_ENABLE_MODE:
1151             filter.SetColorFilter(Detail::InvertColorMat());
1152             break;
1153         case ColorFilterMode::DALTONIZATION_PROTANOMALY_MODE:
1154             filter.SetColorFilter(Detail::ProtanomalyMat());
1155             break;
1156         case ColorFilterMode::DALTONIZATION_DEUTERANOMALY_MODE:
1157             filter.SetColorFilter(Detail::DeuteranomalyMat());
1158             break;
1159         case ColorFilterMode::DALTONIZATION_TRITANOMALY_MODE:
1160             filter.SetColorFilter(Detail::TritanomalyMat());
1161             break;
1162         case ColorFilterMode::INVERT_DALTONIZATION_PROTANOMALY_MODE:
1163             filter.SetColorFilter(Detail::InvertProtanomalyMat());
1164             break;
1165         case ColorFilterMode::INVERT_DALTONIZATION_DEUTERANOMALY_MODE:
1166             filter.SetColorFilter(Detail::InvertDeuteranomalyMat());
1167             break;
1168         case ColorFilterMode::INVERT_DALTONIZATION_TRITANOMALY_MODE:
1169             filter.SetColorFilter(Detail::InvertTritanomalyMat());
1170             break;
1171         // INVERT_COLOR_DISABLE_MODE and DALTONIZATION_NORMAL_MODE couldn't be in this process
1172         case ColorFilterMode::INVERT_COLOR_DISABLE_MODE:
1173         case ColorFilterMode::DALTONIZATION_NORMAL_MODE:
1174         case ColorFilterMode::COLOR_FILTER_END:
1175         default:
1176             filter.SetColorFilter(nullptr);
1177             break;
1178     }
1179     paint.SetFilter(filter);
1180 }
1181 #endif
1182 
IsBufferValid(const sptr<SurfaceBuffer> & buffer)1183 bool RSBaseRenderUtil::IsBufferValid(const sptr<SurfaceBuffer>& buffer)
1184 {
1185     if (!buffer) {
1186         RS_LOGE("RSBaseRenderUtil: buffer is nullptr");
1187         return false;
1188     }
1189     auto addr = buffer->GetVirAddr();
1190     if (addr == nullptr) {
1191         RS_LOGE("RSBaseRenderUtil: buffer has no vir addr");
1192         return false;
1193     }
1194     if (buffer->GetWidth() <= 0 || buffer->GetHeight() <= 0) {
1195         RS_LOGE("RSBaseRenderUtil: this buffer has negative width or height [%d %d]",
1196             buffer->GetWidth(), buffer->GetHeight());
1197         return false;
1198     }
1199     return true;
1200 }
1201 
1202 #ifndef USE_ROSEN_DRAWING
GetSurfaceTransformMatrix(GraphicTransformType rotationTransform,const RectF & bounds)1203 SkMatrix RSBaseRenderUtil::GetSurfaceTransformMatrix(GraphicTransformType rotationTransform, const RectF& bounds)
1204 {
1205     SkMatrix matrix;
1206     const float boundsWidth = bounds.GetWidth();
1207     const float boundsHeight = bounds.GetHeight();
1208     switch (rotationTransform) {
1209         case GraphicTransformType::GRAPHIC_ROTATE_90: {
1210             matrix.preTranslate(0, boundsHeight);
1211             matrix.preRotate(-90); // rotate 90 degrees anti-clockwise at last.
1212             break;
1213         }
1214         case GraphicTransformType::GRAPHIC_ROTATE_180: {
1215             matrix.preTranslate(boundsWidth, boundsHeight);
1216             matrix.preRotate(-180); // rotate 180 degrees anti-clockwise at last.
1217             break;
1218         }
1219         case GraphicTransformType::GRAPHIC_ROTATE_270: {
1220             matrix.preTranslate(boundsWidth, 0);
1221             matrix.preRotate(-270); // rotate 270 degrees anti-clockwise at last.
1222             break;
1223         }
1224         default:
1225             break;
1226     }
1227 
1228     return matrix;
1229 }
1230 #else
GetSurfaceTransformMatrix(GraphicTransformType rotationTransform,const RectF & bounds)1231 Drawing::Matrix RSBaseRenderUtil::GetSurfaceTransformMatrix(GraphicTransformType rotationTransform, const RectF& bounds)
1232 {
1233     Drawing::Matrix matrix;
1234     const float boundsWidth = bounds.GetWidth();
1235     const float boundsHeight = bounds.GetHeight();
1236     switch (rotationTransform) {
1237         case GraphicTransformType::GRAPHIC_ROTATE_90: {
1238             matrix.PreTranslate(0, boundsHeight);
1239             matrix.PreRotate(-90); // rotate 90 degrees anti-clockwise at last.
1240             break;
1241         }
1242         case GraphicTransformType::GRAPHIC_ROTATE_180: {
1243             matrix.PreTranslate(boundsWidth, boundsHeight);
1244             matrix.PreRotate(-180); // rotate 180 degrees anti-clockwise at last.
1245             break;
1246         }
1247         case GraphicTransformType::GRAPHIC_ROTATE_270: {
1248             matrix.PreTranslate(boundsWidth, 0);
1249             matrix.PreRotate(-270); // rotate 270 degrees anti-clockwise at last.
1250             break;
1251         }
1252         default:
1253             break;
1254     }
1255 
1256     return matrix;
1257 }
1258 #endif
1259 
1260 #ifndef USE_ROSEN_DRAWING
GetGravityMatrix(Gravity gravity,const sptr<SurfaceBuffer> & buffer,const RectF & bounds)1261 SkMatrix RSBaseRenderUtil::GetGravityMatrix(Gravity gravity, const sptr<SurfaceBuffer>& buffer, const RectF& bounds)
1262 {
1263     SkMatrix gravityMatrix;
1264 #else
1265 Drawing::Matrix RSBaseRenderUtil::GetGravityMatrix(
1266     Gravity gravity, const sptr<SurfaceBuffer>& buffer, const RectF& bounds)
1267 {
1268     Drawing::Matrix gravityMatrix;
1269 #endif
1270     if (buffer == nullptr) {
1271         return gravityMatrix;
1272     }
1273 
1274     auto frameWidth = static_cast<float>(buffer->GetSurfaceBufferWidth());
1275     auto frameHeight = static_cast<float>(buffer->GetSurfaceBufferHeight());
1276     const float boundsWidth = bounds.GetWidth();
1277     const float boundsHeight = bounds.GetHeight();
1278     if (frameWidth == boundsWidth && frameHeight == boundsHeight) {
1279         return gravityMatrix;
1280     }
1281 
1282     if (!RSPropertiesPainter::GetGravityMatrix(gravity,
1283         RectF {0.0f, 0.0f, boundsWidth, boundsHeight}, frameWidth, frameHeight, gravityMatrix)) {
1284         RS_LOGD("RSBaseRenderUtil::DealWithNodeGravity did not obtain gravity matrix.");
1285     }
1286 
1287     return gravityMatrix;
1288 }
1289 
1290 void RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(GraphicTransformType transform, Gravity gravity,
1291     RectF& localBounds, BufferDrawParam& params)
1292 {
1293     // the surface can rotate itself.
1294     auto rotationTransform = GetRotateTransform(transform);
1295 #ifndef USE_ROSEN_DRAWING
1296     params.matrix.preConcat(RSBaseRenderUtil::GetSurfaceTransformMatrix(rotationTransform, localBounds));
1297 #else
1298     params.matrix.PreConcat(RSBaseRenderUtil::GetSurfaceTransformMatrix(rotationTransform, localBounds));
1299 #endif
1300     if (rotationTransform == GraphicTransformType::GRAPHIC_ROTATE_90 ||
1301         rotationTransform == GraphicTransformType::GRAPHIC_ROTATE_270) {
1302         // after rotate, we should swap dstRect and bound's width and height.
1303         std::swap(localBounds.width_, localBounds.height_);
1304 #ifndef USE_ROSEN_DRAWING
1305         params.dstRect = SkRect::MakeWH(localBounds.GetWidth(), localBounds.GetHeight());
1306 #else
1307         params.dstRect = Drawing::Rect(0, 0, localBounds.GetWidth(), localBounds.GetHeight());
1308 #endif
1309     }
1310 
1311     // deal with buffer's gravity effect in node's inner space.
1312 #ifndef USE_ROSEN_DRAWING
1313     params.matrix.preConcat(RSBaseRenderUtil::GetGravityMatrix(gravity, params.buffer, localBounds));
1314 #else
1315     params.matrix.PreConcat(RSBaseRenderUtil::GetGravityMatrix(gravity, params.buffer, localBounds));
1316 #endif
1317     // because we use the gravity matrix above(which will implicitly includes scale effect),
1318     // we must disable the scale effect that from srcRect to dstRect.
1319     params.dstRect = params.srcRect;
1320 }
1321 
1322 void RSBaseRenderUtil::FlipMatrix(GraphicTransformType transform, BufferDrawParam& params)
1323 {
1324 #ifndef USE_ROSEN_DRAWING
1325     const int angle = 180;
1326     Sk3DView sk3DView;
1327     switch (GetFlipTransform(transform)) {
1328         case GraphicTransformType::GRAPHIC_FLIP_H: {
1329             sk3DView.rotateY(angle);
1330             break;
1331         }
1332         case GraphicTransformType::GRAPHIC_FLIP_V: {
1333             sk3DView.rotateX(angle);
1334             break;
1335         }
1336         default: {
1337             return;
1338         }
1339     }
1340     RS_LOGD("RSBaseRenderUtil::FlipMatrix %d", transform);
1341     SkMatrix flip;
1342     sk3DView.getMatrix(&flip);
1343     const float half = 0.5f;
1344     flip.preTranslate(-half * params.dstRect.width(), -half * params.dstRect.height());
1345     flip.postTranslate(half * params.dstRect.width(), half * params.dstRect.height());
1346     params.matrix.preConcat(flip);
1347 #else
1348     const int angle = 180;
1349     Drawing::Camera3D camera3D;
1350     switch (GetFlipTransform(transform)) {
1351         case GraphicTransformType::GRAPHIC_FLIP_H: {
1352             camera3D.RotateYDegrees(angle);
1353             break;
1354         }
1355         case GraphicTransformType::GRAPHIC_FLIP_V: {
1356             camera3D.RotateXDegrees(angle);
1357             break;
1358         }
1359         default: {
1360             return;
1361         }
1362     }
1363     RS_LOGD("RSBaseRenderUtil::FlipMatrix %d", transform);
1364     Drawing::Matrix flip;
1365     camera3D.ApplyToMatrix(flip);
1366     const float half = 0.5f;
1367     flip.PreTranslate(-half * params.dstRect.GetWidth(), -half * params.dstRect.GetHeight());
1368     Drawing::Matrix tmpMatrix;
1369     tmpMatrix.Translate(half * params.dstRect.GetWidth(), half * params.dstRect.GetHeight());
1370     flip = tmpMatrix * flip;
1371     params.matrix = params.matrix * flip;
1372 #endif
1373 }
1374 
1375 void RSBaseRenderUtil::SetPropertiesForCanvas(RSPaintFilterCanvas& canvas, const BufferDrawParam& params)
1376 {
1377 #ifndef USE_ROSEN_DRAWING
1378     if (params.isNeedClip) {
1379         if (!params.cornerRadius.IsZero()) {
1380             canvas.clipRRect(RSPropertiesPainter::RRect2SkRRect(params.clipRRect), true);
1381         } else {
1382             canvas.clipRect(params.clipRect);
1383         }
1384     }
1385     if (SkColorGetA(params.backgroundColor) != SK_AlphaTRANSPARENT) {
1386         canvas.drawColor(params.backgroundColor);
1387     }
1388     canvas.concat(params.matrix);
1389 #else
1390     if (params.isNeedClip) {
1391         if (!params.cornerRadius.IsZero()) {
1392             canvas.ClipRoundRect(
1393                 RSPropertiesPainter::RRect2DrawingRRect(params.clipRRect), Drawing::ClipOp::INTERSECT, true);
1394         } else {
1395             canvas.ClipRect(params.clipRect, Drawing::ClipOp::INTERSECT, false);
1396         }
1397     }
1398     if (Drawing::Color::ColorQuadGetA(params.backgroundColor) != Drawing::Color::COLOR_TRANSPARENT) {
1399         canvas.Clear(params.backgroundColor);
1400     }
1401     canvas.ConcatMatrix(params.matrix);
1402 #endif
1403 }
1404 
1405 #ifndef USE_ROSEN_DRAWING
1406 bool RSBaseRenderUtil::ConvertBufferToBitmap(sptr<SurfaceBuffer> buffer, std::vector<uint8_t>& newBuffer,
1407     GraphicColorGamut dstGamut, SkBitmap& bitmap, const std::vector<GraphicHDRMetaData>& metaDatas)
1408 #else
1409 bool RSBaseRenderUtil::ConvertBufferToBitmap(sptr<SurfaceBuffer> buffer, std::vector<uint8_t>& newBuffer,
1410     GraphicColorGamut dstGamut, Drawing::Bitmap& bitmap, const std::vector<GraphicHDRMetaData>& metaDatas)
1411 #endif
1412 {
1413     if (!IsBufferValid(buffer)) {
1414         return false;
1415     }
1416     bool bitmapCreated = false;
1417     GraphicColorGamut srcGamut = static_cast<GraphicColorGamut>(buffer->GetSurfaceBufferColorGamut());
1418     // [PLANNING]: We will not use this tmp newBuffer if we use GPU to do the color conversions.
1419     // Attention: make sure newBuffer's lifecycle is longer than the moment call drawBitmap
1420     if (buffer->GetFormat() == GRAPHIC_PIXEL_FMT_YCRCB_420_SP ||
1421         buffer->GetFormat() == GRAPHIC_PIXEL_FMT_YCBCR_420_SP) {
1422         bitmapCreated = CreateYuvToRGBABitMap(buffer, newBuffer, bitmap);
1423     } else if (buffer->GetFormat() == Detail::STUB_PIXEL_FMT_RGBA_16161616) {
1424         bitmapCreated = CreateNewColorGamutBitmap(buffer, newBuffer, bitmap, srcGamut, dstGamut, metaDatas);
1425     } else if (srcGamut != dstGamut) {
1426         RS_LOGD("RSBaseRenderUtil::ConvertBufferToBitmap: need to convert color gamut.");
1427         bitmapCreated = CreateNewColorGamutBitmap(buffer, newBuffer, bitmap, srcGamut, dstGamut);
1428     } else {
1429         bitmapCreated = CreateBitmap(buffer, bitmap);
1430     }
1431     return bitmapCreated;
1432 }
1433 
1434 #ifndef USE_ROSEN_DRAWING
1435 bool RSBaseRenderUtil::CreateYuvToRGBABitMap(sptr<OHOS::SurfaceBuffer> buffer, std::vector<uint8_t>& newBuffer,
1436     SkBitmap& bitmap)
1437 {
1438     newBuffer.resize(buffer->GetWidth() * buffer->GetHeight() * 4, 0); // 4 is color channel
1439     if (!Detail::ConvertYUV420SPToRGBA(newBuffer, buffer)) {
1440         return false;
1441     }
1442 
1443     SkColorType colorType = kRGBA_8888_SkColorType;
1444     SkImageInfo imageInfo = SkImageInfo::Make(buffer->GetWidth(), buffer->GetHeight(),
1445         colorType, kPremul_SkAlphaType);
1446     SkPixmap pixmap(imageInfo, newBuffer.data(), buffer->GetWidth() * 4); // 4 is color channel
1447     return bitmap.installPixels(pixmap);
1448 }
1449 #else
1450 bool RSBaseRenderUtil::CreateYuvToRGBABitMap(sptr<OHOS::SurfaceBuffer> buffer, std::vector<uint8_t>& newBuffer,
1451     Drawing::Bitmap& bitmap)
1452 {
1453     newBuffer.resize(buffer->GetWidth() * buffer->GetHeight() * 4, 0); // 4 is color channel
1454     if (!Detail::ConvertYUV420SPToRGBA(newBuffer, buffer)) {
1455         return false;
1456     }
1457 
1458     Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL };
1459     bitmap.Build(buffer->GetWidth(), buffer->GetHeight(), format);
1460     bitmap.SetPixels(newBuffer.data());
1461     return true;
1462 }
1463 #endif
1464 
1465 #ifndef USE_ROSEN_DRAWING
1466 bool RSBaseRenderUtil::CreateBitmap(sptr<OHOS::SurfaceBuffer> buffer, SkBitmap& bitmap)
1467 {
1468     SkImageInfo imageInfo = Detail::GenerateSkImageInfo(buffer);
1469     SkPixmap pixmap(imageInfo, buffer->GetVirAddr(), buffer->GetStride());
1470     return bitmap.installPixels(pixmap);
1471 }
1472 
1473 bool RSBaseRenderUtil::CreateNewColorGamutBitmap(sptr<OHOS::SurfaceBuffer> buffer, std::vector<uint8_t>& newBuffer,
1474     SkBitmap& bitmap, GraphicColorGamut srcGamut, GraphicColorGamut dstGamut,
1475     const std::vector<GraphicHDRMetaData>& metaDatas)
1476 {
1477     bool convertRes = Detail::ConvertBufferColorGamut(newBuffer, buffer, srcGamut, dstGamut, metaDatas);
1478     if (convertRes) {
1479         RS_LOGW("CreateNewColorGamutBitmap: convert color gamut succeed, use new buffer to create bitmap.");
1480         SkImageInfo imageInfo = Detail::GenerateSkImageInfo(buffer);
1481         SkPixmap pixmap(imageInfo, newBuffer.data(), buffer->GetStride());
1482         return bitmap.installPixels(pixmap);
1483     } else {
1484         RS_LOGW("CreateNewColorGamutBitmap: convert color gamut failed, use old buffer to create bitmap.");
1485         return CreateBitmap(buffer, bitmap);
1486     }
1487 }
1488 #else
1489 bool RSBaseRenderUtil::CreateBitmap(sptr<OHOS::SurfaceBuffer> buffer, Drawing::Bitmap& bitmap)
1490 {
1491     Drawing::BitmapFormat format = Detail::GenerateDrawingBitmapFormat(buffer);
1492     bitmap.Build(buffer->GetWidth(), buffer->GetHeight(), format, buffer->GetStride());
1493     bitmap.SetPixels(buffer->GetVirAddr());
1494     return true;
1495 }
1496 
1497 bool RSBaseRenderUtil::CreateNewColorGamutBitmap(sptr<OHOS::SurfaceBuffer> buffer, std::vector<uint8_t>& newBuffer,
1498     Drawing::Bitmap& bitmap, GraphicColorGamut srcGamut, GraphicColorGamut dstGamut,
1499     const std::vector<GraphicHDRMetaData>& metaDatas)
1500 {
1501     bool convertRes = Detail::ConvertBufferColorGamut(newBuffer, buffer, srcGamut, dstGamut, metaDatas);
1502     if (convertRes) {
1503         RS_LOGW("CreateNewColorGamutBitmap: convert color gamut succeed, use new buffer to create bitmap.");
1504         Drawing::BitmapFormat format = Detail::GenerateDrawingBitmapFormat(buffer);
1505         bitmap.Build(buffer->GetWidth(), buffer->GetHeight(), format, buffer->GetStride());
1506         bitmap.SetPixels(newBuffer.data());
1507         return true;
1508     } else {
1509         RS_LOGW("CreateNewColorGamutBitmap: convert color gamut failed, use old buffer to create bitmap.");
1510         return CreateBitmap(buffer, bitmap);
1511     }
1512 }
1513 #endif
1514 
1515 std::unique_ptr<RSTransactionData> RSBaseRenderUtil::ParseTransactionData(MessageParcel& parcel)
1516 {
1517     RS_TRACE_NAME("UnMarsh RSTransactionData: data size:" + std::to_string(parcel.GetDataSize()));
1518     auto transactionData = parcel.ReadParcelable<RSTransactionData>();
1519     if (!transactionData) {
1520         RS_TRACE_NAME("UnMarsh RSTransactionData fail!");
1521         RS_LOGE("UnMarsh RSTransactionData fail!");
1522         return nullptr;
1523     }
1524     RS_TRACE_NAME("UnMarsh RSTransactionData: recv data from " + std::to_string(transactionData->GetSendingPid()));
1525     std::unique_ptr<RSTransactionData> transData(transactionData);
1526     return transData;
1527 }
1528 
1529 bool RSBaseRenderUtil::WriteSurfaceRenderNodeToPng(const RSSurfaceRenderNode& node)
1530 {
1531     auto type = RSSystemProperties::GetDumpSurfaceType();
1532     if (type == DumpSurfaceType::DISABLED || type == DumpSurfaceType::PIXELMAP) {
1533         return false;
1534     }
1535     uint64_t id = static_cast<uint64_t>(RSSystemProperties::GetDumpSurfaceId());
1536     if (type == DumpSurfaceType::SINGLESURFACE && !ROSEN_EQ(node.GetId(), id)) {
1537         return false;
1538     }
1539     sptr<SurfaceBuffer> buffer = node.GetBuffer();
1540     if (!buffer) {
1541         return false;
1542     }
1543     BufferHandle *bufferHandle =  buffer->GetBufferHandle();
1544     if (bufferHandle == nullptr) {
1545         return false;
1546     }
1547 
1548     struct timeval now;
1549     gettimeofday(&now, nullptr);
1550     constexpr int secToUsec = 1000 * 1000;
1551     int64_t nowVal =  static_cast<int64_t>(now.tv_sec) * secToUsec + static_cast<int64_t>(now.tv_usec);
1552     std::string filename = "/data/SurfaceRenderNode_" +
1553         node.GetName() + "_"  +
1554         std::to_string(node.GetId()) + "_" +
1555         std::to_string(nowVal) + ".png";
1556     WriteToPngParam param;
1557     param.width = static_cast<uint32_t>(bufferHandle->width);
1558     param.height = static_cast<uint32_t>(bufferHandle->height);
1559     param.data = static_cast<uint8_t *>(buffer->GetVirAddr());
1560     param.stride = static_cast<uint32_t>(bufferHandle->stride);
1561     param.bitDepth = Detail::BITMAP_DEPTH;
1562 
1563     return WriteToPng(filename, param);
1564 }
1565 
1566 bool RSBaseRenderUtil::WriteCacheRenderNodeToPng(const RSRenderNode& node)
1567 {
1568     auto type = RSSystemProperties::GetDumpSurfaceType();
1569     if (type == DumpSurfaceType::DISABLED || type == DumpSurfaceType::PIXELMAP) {
1570         return false;
1571     }
1572     uint64_t id = static_cast<uint64_t>(RSSystemProperties::GetDumpSurfaceId());
1573     if (type == DumpSurfaceType::SINGLESURFACE && !ROSEN_EQ(node.GetId(), id)) {
1574         return false;
1575     }
1576 #ifndef USE_ROSEN_DRAWING
1577     sk_sp<SkSurface> surface = node.GetCacheSurface();
1578 #else
1579     std::shared_ptr<Drawing::Surface> surface = node.GetCacheSurface();
1580 #endif
1581     if (!surface) {
1582         return false;
1583     }
1584 
1585     struct timeval now;
1586     gettimeofday(&now, nullptr);
1587     constexpr int secToUsec = 1000 * 1000;
1588     int64_t nowVal =  static_cast<int64_t>(now.tv_sec) * secToUsec + static_cast<int64_t>(now.tv_usec);
1589     std::string filename = "/data/CacheRenderNode_" +
1590         std::to_string(node.GetId()) + "_" +
1591         std::to_string(nowVal) + ".png";
1592     WriteToPngParam param;
1593 
1594 #ifndef USE_ROSEN_DRAWING
1595     SkImageInfo info = SkImageInfo::Make(surface->width(), surface->height(),
1596         kRGBA_8888_SkColorType, kPremul_SkAlphaType);
1597     SkBitmap bitmap;
1598     bitmap.setInfo(info);
1599     bitmap.allocPixels();
1600     surface->readPixels(bitmap, 0, 0);
1601     param.width = static_cast<uint32_t>(surface->width());
1602     param.height = static_cast<uint32_t>(surface->height());
1603     param.data = static_cast<uint8_t *>(bitmap.getPixels());
1604     param.stride = static_cast<uint32_t>(bitmap.rowBytes());
1605     param.bitDepth = Detail::BITMAP_DEPTH;
1606 #else
1607     auto image = surface->GetImageSnapshot();
1608     if (!image) {
1609         return false;
1610     }
1611     Drawing::BitmapFormat format = { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL };
1612     Drawing::Bitmap bitmap;
1613     bitmap.Build(image->GetWidth(), image->GetHeight(), format);
1614     image->ReadPixels(bitmap, 0, 0);
1615     param.width = static_cast<uint32_t>(image->GetWidth());
1616     param.height = static_cast<uint32_t>(image->GetHeight());
1617     param.data = static_cast<uint8_t *>(bitmap.GetPixels());
1618     param.stride = static_cast<uint32_t>(image->GetWidth() * Detail::BYTES_PER_PIXEL);
1619     param.bitDepth = Detail::BITMAP_DEPTH;
1620 #endif
1621 
1622     return WriteToPng(filename, param);
1623 }
1624 
1625 bool RSBaseRenderUtil::WritePixelMapToPng(Media::PixelMap& pixelMap)
1626 {
1627     auto type = RSSystemProperties::GetDumpSurfaceType();
1628     if (type != DumpSurfaceType::PIXELMAP) {
1629         return false;
1630     }
1631     struct timeval now;
1632     gettimeofday(&now, nullptr);
1633     constexpr int secToUsec = 1000 * 1000;
1634     int64_t nowVal =  static_cast<int64_t>(now.tv_sec) * secToUsec + static_cast<int64_t>(now.tv_usec);
1635     std::string filename = "/data/PixelMap_" + std::to_string(nowVal) + ".png";
1636 
1637     WriteToPngParam param;
1638     param.width = static_cast<uint32_t>(pixelMap.GetWidth());
1639     param.height = static_cast<uint32_t>(pixelMap.GetHeight());
1640     param.data = pixelMap.GetPixels();
1641     param.stride = static_cast<uint32_t>(pixelMap.GetRowBytes());
1642     param.bitDepth = Detail::BITMAP_DEPTH;
1643 
1644     return WriteToPng(filename, param);
1645 }
1646 
1647 bool RSBaseRenderUtil::WriteToPng(const std::string &filename, const WriteToPngParam &param)
1648 {
1649     if (filename.empty()) {
1650         RS_LOGI("RSBaseRenderUtil::WriteToPng filename is empty");
1651         return false;
1652     }
1653     RS_LOGI("RSBaseRenderUtil::WriteToPng filename = %s", filename.c_str());
1654     png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
1655     if (pngStruct == nullptr) {
1656         return false;
1657     }
1658     png_infop pngInfo = png_create_info_struct(pngStruct);
1659     if (pngInfo == nullptr) {
1660         png_destroy_write_struct(&pngStruct, nullptr);
1661         return false;
1662     }
1663 
1664     FILE *fp = fopen(filename.c_str(), "wb");
1665     if (fp == nullptr) {
1666         png_destroy_write_struct(&pngStruct, &pngInfo);
1667         return false;
1668     }
1669     png_init_io(pngStruct, fp);
1670 
1671     // set png header
1672     png_set_IHDR(pngStruct, pngInfo,
1673         param.width, param.height,
1674         param.bitDepth,
1675         PNG_COLOR_TYPE_RGBA,
1676         PNG_INTERLACE_NONE,
1677         PNG_COMPRESSION_TYPE_BASE,
1678         PNG_FILTER_TYPE_BASE);
1679     png_set_packing(pngStruct); // set packing info
1680     png_write_info(pngStruct, pngInfo); // write to header
1681 
1682     for (uint32_t i = 0; i < param.height; i++) {
1683         png_write_row(pngStruct, param.data + (i * param.stride));
1684     }
1685     png_write_end(pngStruct, pngInfo);
1686 
1687     // free
1688     png_destroy_write_struct(&pngStruct, &pngInfo);
1689     int ret = fclose(fp);
1690     return ret == 0;
1691 }
1692 
1693 GraphicTransformType RSBaseRenderUtil::GetRotateTransform(GraphicTransformType transform)
1694 {
1695     switch (transform) {
1696         case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
1697         case GraphicTransformType::GRAPHIC_FLIP_V_ROT90: {
1698             return GraphicTransformType::GRAPHIC_ROTATE_90;
1699         }
1700         case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
1701         case GraphicTransformType::GRAPHIC_FLIP_V_ROT180: {
1702             return GraphicTransformType::GRAPHIC_ROTATE_180;
1703         }
1704         case GraphicTransformType::GRAPHIC_FLIP_H_ROT270:
1705         case GraphicTransformType::GRAPHIC_FLIP_V_ROT270: {
1706             return GraphicTransformType::GRAPHIC_ROTATE_270;
1707         }
1708         default: {
1709             return transform;
1710         }
1711     }
1712 }
1713 
1714 GraphicTransformType RSBaseRenderUtil::GetFlipTransform(GraphicTransformType transform)
1715 {
1716     switch (transform) {
1717         case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
1718         case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
1719         case GraphicTransformType::GRAPHIC_FLIP_H_ROT270: {
1720             return GraphicTransformType::GRAPHIC_FLIP_H;
1721         }
1722         case GraphicTransformType::GRAPHIC_FLIP_V_ROT90:
1723         case GraphicTransformType::GRAPHIC_FLIP_V_ROT180:
1724         case GraphicTransformType::GRAPHIC_FLIP_V_ROT270: {
1725             return GraphicTransformType::GRAPHIC_FLIP_V;
1726         }
1727         default: {
1728             return transform;
1729         }
1730     }
1731 }
1732 
1733 GraphicTransformType RSBaseRenderUtil::ClockwiseToAntiClockwiseTransform(GraphicTransformType transform)
1734 {
1735     switch (transform) {
1736         case GraphicTransformType::GRAPHIC_ROTATE_90: {
1737             return GraphicTransformType::GRAPHIC_ROTATE_270;
1738         }
1739         case GraphicTransformType::GRAPHIC_ROTATE_270: {
1740             return GraphicTransformType::GRAPHIC_ROTATE_90;
1741         }
1742         case GraphicTransformType::GRAPHIC_FLIP_H_ROT90: {
1743             return GraphicTransformType::GRAPHIC_FLIP_V_ROT90;
1744         }
1745         case GraphicTransformType::GRAPHIC_FLIP_H_ROT270: {
1746             return GraphicTransformType::GRAPHIC_FLIP_V_ROT270;
1747         }
1748         case GraphicTransformType::GRAPHIC_FLIP_V_ROT90: {
1749             return GraphicTransformType::GRAPHIC_FLIP_H_ROT90;
1750         }
1751         case GraphicTransformType::GRAPHIC_FLIP_V_ROT270: {
1752             return GraphicTransformType::GRAPHIC_FLIP_H_ROT270;
1753         }
1754         default: {
1755             return transform;
1756         }
1757     }
1758 }
1759 
1760 int RSBaseRenderUtil::RotateEnumToInt(GraphicTransformType rotation)
1761 {
1762     static const std::map<GraphicTransformType, int> transformTypeEnumToIntMap = {
1763         {GraphicTransformType::GRAPHIC_ROTATE_NONE, 0}, {GraphicTransformType::GRAPHIC_ROTATE_90, 90},
1764         {GraphicTransformType::GRAPHIC_ROTATE_180, 180}, {GraphicTransformType::GRAPHIC_ROTATE_270, 270}};
1765     auto iter = transformTypeEnumToIntMap.find(rotation);
1766     return iter != transformTypeEnumToIntMap.end() ? iter->second : 0;
1767 }
1768 
1769 GraphicTransformType RSBaseRenderUtil::RotateEnumToInt(int angle, GraphicTransformType flip)
1770 {
1771     static const std::map<int, GraphicTransformType> intToEnumMap = {
1772         {0, GraphicTransformType::GRAPHIC_ROTATE_NONE}, {90, GraphicTransformType::GRAPHIC_ROTATE_270},
1773         {180, GraphicTransformType::GRAPHIC_ROTATE_180}, {270, GraphicTransformType::GRAPHIC_ROTATE_90}};
1774     static const std::map<std::pair<int, GraphicTransformType>, GraphicTransformType> pairToEnumMap = {
1775         {{0, GraphicTransformType::GRAPHIC_FLIP_H}, GraphicTransformType::GRAPHIC_FLIP_H},
1776         {{0, GraphicTransformType::GRAPHIC_FLIP_V}, GraphicTransformType::GRAPHIC_FLIP_V},
1777         {{90, GraphicTransformType::GRAPHIC_FLIP_H}, GraphicTransformType::GRAPHIC_FLIP_V_ROT90},
1778         {{90, GraphicTransformType::GRAPHIC_FLIP_V}, GraphicTransformType::GRAPHIC_FLIP_H_ROT90},
1779         {{180, GraphicTransformType::GRAPHIC_FLIP_H}, GraphicTransformType::GRAPHIC_FLIP_V},
1780         {{180, GraphicTransformType::GRAPHIC_FLIP_V}, GraphicTransformType::GRAPHIC_FLIP_H},
1781         {{270, GraphicTransformType::GRAPHIC_FLIP_H}, GraphicTransformType::GRAPHIC_FLIP_H_ROT90},
1782         {{270, GraphicTransformType::GRAPHIC_FLIP_V}, GraphicTransformType::GRAPHIC_FLIP_V_ROT90},
1783     };
1784 
1785     if (flip != GraphicTransformType::GRAPHIC_FLIP_H && flip != GraphicTransformType::GRAPHIC_FLIP_V) {
1786         auto iter = intToEnumMap.find(angle);
1787         return iter != intToEnumMap.end() ? iter->second : GraphicTransformType::GRAPHIC_ROTATE_NONE;
1788     } else {
1789         auto iter = pairToEnumMap.find({angle, flip});
1790         return iter != pairToEnumMap.end() ? iter->second : GraphicTransformType::GRAPHIC_ROTATE_NONE;
1791     }
1792 }
1793 } // namespace Rosen
1794 } // namespace OHOS
1795