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