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 ¶m)
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