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