• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "rs_base_render_util.h"
17 
18 #include <sys/time.h>
19 #include <unordered_set>
20 
21 #include "common/rs_matrix3.h"
22 #include "common/rs_obj_abs_geometry.h"
23 #include "common/rs_vector2.h"
24 #include "common/rs_vector3.h"
25 #include "include/utils/SkCamera.h"
26 #include "platform/common/rs_log.h"
27 #include "png.h"
28 #include "rs_trace.h"
29 #include "transaction/rs_transaction_data.h"
30 
31 namespace OHOS {
32 namespace Rosen {
33 namespace Detail {
34 // [PLANNING]: Use GPU to do the gamut conversion instead of these following works.
35 using PixelTransformFunc = std::function<float(float)>;
36 
37 using Offset = std::pair<uint8_t, uint8_t>; // first: offsetSrc; second: offsetDst
38 const int dstLength = 3;
39 using Array3ptr = std::array<uint8_t*, dstLength>;
40 const uint32_t STUB_PIXEL_FMT_RGBA_16161616 = 0X7fff0001;
41 const uint32_t STUB_PIXEL_FMT_RGBA_1010102 = 0X7fff0002;
42 constexpr uint32_t MATRIX_SIZE = 20; // colorMatrix size
43 constexpr int BITMAP_DEPTH = 8;
44 
PassThrough(float v)45 inline constexpr float PassThrough(float v)
46 {
47     return v;
48 }
49 
50 template<typename T>
Saturate(T v)51 static constexpr T Saturate(T v) noexcept
52 {
53     return T(std::min(static_cast<T>(1), std::max(static_cast<T>(0), v)));
54 }
55 
ApplyTransForm(const Vector3f & val,const PixelTransformFunc & func)56 inline Vector3f ApplyTransForm(const Vector3f& val, const PixelTransformFunc& func)
57 {
58     return Vector3f {func(val.x_), func(val.y_), func(val.z_)};
59 }
60 
SafePow(float x,float e)61 inline float SafePow(float x, float e)
62 {
63     return powf(x < 0.0f ? 0.0f : x, e);
64 }
65 
GenOETF(float gamma)66 inline PixelTransformFunc GenOETF(float gamma)
67 {
68     if (gamma == 1.0f || gamma == 0.0f) {
69         return PassThrough;
70     }
71 
72     return std::bind(SafePow, std::placeholders::_1, 1.0f / gamma);
73 }
74 
GenEOTF(float gamma)75 inline PixelTransformFunc GenEOTF(float gamma)
76 {
77     if (gamma == 1.0f) {
78         return PassThrough;
79     }
80 
81     return std::bind(SafePow, std::placeholders::_1, gamma);
82 }
83 
84 struct TransferParameters {
85     float g = 0.0f;
86     float a = 0.0f;
87     float b = 0.0f;
88     float c = 0.0f;
89     float d = 0.0f;
90     float e = 0.0f;
91     float f = 0.0f;
92 };
93 
RcpResponsePq(float x,const TransferParameters & p)94 inline float RcpResponsePq(float x, const TransferParameters& p)
95 {
96     float tmp = powf(x, p.a);
97     return std::powf((p.c + p.d * tmp) / (1 + p.e * tmp), p.b);
98 }
99 
ResponsePq(float x,const TransferParameters & p)100 inline float ResponsePq(float x, const TransferParameters& p)
101 {
102     float tmp = powf(x, 1.f / p.b);
103     return std::powf(std::max((tmp - p.c), p.f) / (p.d - p.e * tmp), 1.f / p.a);
104 }
105 
106 
RcpResponse(float x,const TransferParameters & p)107 static constexpr float RcpResponse(float x, const TransferParameters& p)
108 {
109     return x >= p.d * p.c ? (std::pow(x, 1.0f / p.g) - p.b) / p.a : x / p.c;
110 }
111 
Response(float x,const TransferParameters & p)112 inline constexpr float Response(float x, const TransferParameters& p)
113 {
114     return x >= p.d ? std::pow(p.a * x + p.b, p.g) : p.c * x;
115 }
116 
RcpFullResponse(float x,const TransferParameters & p)117 inline constexpr float RcpFullResponse(float x, const TransferParameters& p)
118 {
119     return x >= p.d * p.c ? (std::pow(x - p.e, 1.0f / p.g) - p.b) / p.a : (x - p.f) / p.c;
120 }
121 
FullResponse(float x,const TransferParameters & p)122 inline constexpr float FullResponse(float x, const TransferParameters& p)
123 {
124     return x >= p.d ? std::pow(p.a * x + p.b, p.g) + p.e : p.c * x + p.f;
125 }
126 
GenOETF(const TransferParameters & params)127 inline PixelTransformFunc GenOETF(const TransferParameters& params)
128 {
129     if (params.g < 0) { // HDR
130         return std::bind(RcpResponsePq, std::placeholders::_1, params);
131     }
132 
133     if (params.e == 0.0f && params.f == 0.0f) {
134         return std::bind(RcpResponse, std::placeholders::_1, params);
135     }
136 
137     return std::bind(RcpFullResponse, std::placeholders::_1, params);
138 }
139 
GenEOTF(const TransferParameters & params)140 inline PixelTransformFunc GenEOTF(const TransferParameters& params)
141 {
142     if (params.g < 0) {
143         return std::bind(ResponsePq, std::placeholders::_1, params);
144     }
145 
146     if (params.e == 0.0f && params.f == 0.0f) {
147         return std::bind(Response, std::placeholders::_1, params);
148     }
149 
150     return std::bind(FullResponse, std::placeholders::_1, params);
151 }
152 
ACESToneMapping(float color,float targetLum)153 float ACESToneMapping(float color, float targetLum)
154 {
155     const float a = 2.51f;
156     const float b = 0.03f;
157     const float c = 2.43f;
158     const float d = 0.59f;
159     const float e = 0.14f;
160 
161     color *= targetLum;
162     return (color * (a * color + b)) / (color * (c * color + d) + e);
163 }
164 
GenACESToneMapping(float targetLum)165 inline PixelTransformFunc GenACESToneMapping(float targetLum)
166 {
167     if (targetLum <= 0) {
168         const float defaultLum = 200.f;
169         targetLum = defaultLum;
170     }
171     return std::bind(ACESToneMapping, std::placeholders::_1, targetLum);
172 }
173 
GenRGBToXYZMatrix(const std::array<Vector2f,3> & basePoints,const Vector2f & whitePoint)174 Matrix3f GenRGBToXYZMatrix(const std::array<Vector2f, 3>& basePoints, const Vector2f& whitePoint)
175 {
176     const Vector2f& R = basePoints[0];
177     const Vector2f& G = basePoints[1];
178     const Vector2f& B = basePoints[2];
179 
180     float RxRy = R.x_ / R.y_;
181     float GxGy = G.x_ / G.y_;
182     float BxBy = B.x_ / B.y_;
183     float WxWy = whitePoint.x_ / whitePoint.y_;
184 
185     float oneRxRy = (1 - R.x_) / R.y_;
186     float oneGxGy = (1 - G.x_) / G.y_;
187     float oneBxBy = (1 - B.x_) / B.y_;
188     float oneWxWy = (1 - whitePoint.x_) / whitePoint.y_;
189 
190     float BY =
191         ((oneWxWy - oneRxRy) * (GxGy - RxRy) - (WxWy - RxRy) * (oneGxGy - oneRxRy)) /
192         ((oneBxBy - oneRxRy) * (GxGy - RxRy) - (BxBy - RxRy) * (oneGxGy - oneRxRy));
193     float GY = (WxWy - RxRy - BY * (BxBy - RxRy)) / (GxGy - RxRy);
194     float RY = 1 - GY - BY;
195 
196     float RYRy = RY / R.y_;
197     float GYGy = GY / G.y_;
198     float BYBy = BY / B.y_;
199 
200     return Matrix3f {
201         RYRy * R.x_, RY, RYRy * (1 - R.x_ - R.y_),
202         GYGy * G.x_, GY, GYGy * (1 - G.x_ - G.y_),
203         BYBy * B.x_, BY, BYBy * (1 - B.x_ - B.y_)
204     };
205 }
InvertColorMat()206 static const sk_sp<SkColorFilter>& InvertColorMat()
207 {
208     static const SkScalar colorMatrix[MATRIX_SIZE] = {
209         0.402,  -1.174, -0.228, 1.0, 0.0,
210         -0.598, -0.174, -0.228, 1.0, 0.0,
211         -0.599, -1.175, 0.772,  1.0, 0.0,
212         0.0,    0.0,    0.0,    1.0, 0.0
213     };
214     static auto invertColorMat = SkColorFilters::Matrix(colorMatrix);
215     return invertColorMat;
216 }
217 
ProtanomalyMat()218 static const sk_sp<SkColorFilter>& ProtanomalyMat()
219 {
220     static const SkScalar colorMatrix[MATRIX_SIZE] = {
221         0.622,  0.377,  0.0, 0.0, 0.0,
222         0.264,  0.736,  0.0, 0.0, 0.0,
223         0.217,  -0.217, 1.0, 0.0, 0.0,
224         0.0,    0.0,    0.0, 1.0, 0.0
225     };
226     static auto protanomalyMat = SkColorFilters::Matrix(colorMatrix);
227     return protanomalyMat;
228 }
229 
DeuteranomalyMat()230 static const sk_sp<SkColorFilter>& DeuteranomalyMat()
231 {
232     static const SkScalar colorMatrix[MATRIX_SIZE] = {
233         0.288,  0.712, 0.0, 0.0, 0.0,
234         0.053,  0.947, 0.0, 0.0, 0.0,
235         -0.258, 0.258, 1.0, 0.0, 0.0,
236         0.0,    0.0,   0.0, 1.0, 0.0
237     };
238     static auto deuteranomalyMat = SkColorFilters::Matrix(colorMatrix);
239     return deuteranomalyMat;
240 }
241 
TritanomalyMat()242 static const sk_sp<SkColorFilter>& TritanomalyMat()
243 {
244     static const SkScalar colorMatrix[MATRIX_SIZE] = {
245         1.0, -0.806, 0.806, 0.0, 0.0,
246         0.0, 0.379,  0.621, 0.0, 0.0,
247         0.0, 0.105,  0.895, 0.0, 0.0,
248         0.0, 0.0,    0.0,   1.0, 0.0
249     };
250     static auto tritanomalyMat = SkColorFilters::Matrix(colorMatrix);
251     return tritanomalyMat;
252 }
253 
InvertProtanomalyMat()254 static const sk_sp<SkColorFilter>& InvertProtanomalyMat()
255 {
256     static const SkScalar colorMatrix[MATRIX_SIZE] = {
257         -0.109, -0.663, -0.228, 1.0, 0.0,
258         -0.468, -0.304, -0.228, 1.0, 0.0,
259         -0.516, -1.258, 0.772,  1.0, 0.0,
260         0.0,    0.0,    0.0,    1.0, 0.0
261     };
262     static auto invertProtanomalyMat = SkColorFilters::Matrix(colorMatrix);
263     return invertProtanomalyMat;
264 }
265 
InvertDeuteranomalyMat()266 static const sk_sp<SkColorFilter>& InvertDeuteranomalyMat()
267 {
268     static const SkScalar colorMatrix[MATRIX_SIZE] = {
269         0.113,  -0.885, -0.228, 1.0, 0.0,
270         -0.123, -0.649, -0.228, 1.0, 0.0,
271         -0.434, -1.341, 0.772,  1.0, 0.0,
272         0.0,    0.0,    0.0,    1.0, 0.0
273     };
274     static auto invertDeuteranomalyMat = SkColorFilters::Matrix(colorMatrix);
275     return invertDeuteranomalyMat;
276 }
277 
InvertTritanomalyMat()278 static const sk_sp<SkColorFilter>& InvertTritanomalyMat()
279 {
280     static const SkScalar colorMatrix[MATRIX_SIZE] = {
281         0.402,  -0.792, -0.609, 1.0, 0.0,
282         -0.598, 0.392,  -0.794, 1.0, 0.0,
283         -0.598, 0.118,  -0.521, 1.0, 0.0,
284         0.0,    0.0,    0.0,    1.0, 0.0
285     };
286     static auto invertTritanomalyMat = SkColorFilters::Matrix(colorMatrix);
287     return invertTritanomalyMat;
288 }
289 
290 class SimpleColorSpace {
291 public:
292     // 3 RGB basePoints and 1 whitePoint.
SimpleColorSpace(const std::array<Vector2f,3> & basePoints,const Vector2f & whitePoint,float gamma,PixelTransformFunc clamper=Saturate<float>)293     SimpleColorSpace(
294         const std::array<Vector2f, 3>& basePoints,
295         const Vector2f& whitePoint,
296         float gamma,
297         PixelTransformFunc clamper = Saturate<float>
298     ) noexcept
299         : rgbToXyz_(GenRGBToXYZMatrix(basePoints, whitePoint)),
300           xyzToRgb_(rgbToXyz_.Inverse()),
301           transEOTF_(GenEOTF(gamma)),
302           transOETF_(GenOETF(gamma)),
303           clamper_(std::move(clamper)),
304           transferParams_({ gamma, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f })
305     {
306     }
307 
SimpleColorSpace(const std::array<Vector2f,3> & basePoints,const Vector2f & whitePoint,const TransferParameters & parameters,PixelTransformFunc clamper=Saturate<float>)308     SimpleColorSpace(
309         const std::array<Vector2f, 3>& basePoints,
310         const Vector2f& whitePoint,
311         const TransferParameters& parameters,
312         PixelTransformFunc clamper = Saturate<float>
313     ) noexcept
314         : rgbToXyz_(GenRGBToXYZMatrix(basePoints, whitePoint)),
315           xyzToRgb_(rgbToXyz_.Inverse()),
316           transEOTF_(GenEOTF(parameters)),
317           transOETF_(GenOETF(parameters)),
318           clamper_(std::move(clamper)),
319           transferParams_(parameters)
320     {
321     }
322 
323     ~SimpleColorSpace() noexcept = default;
324 
ToneMapping(const Vector3f & color,float targetLum=0) const325     Vector3f ToneMapping(const Vector3f& color, float targetLum = 0) const
326     {
327         PixelTransformFunc toneMappingFunc = GenACESToneMapping(targetLum);
328         return ApplyTransForm(color, toneMappingFunc);
329     }
330 
ToLinear(const Vector3f & val) const331     Vector3f ToLinear(const Vector3f& val) const
332     {
333         return ApplyTransForm(val, transEOTF_);
334     }
335 
FromLinear(const Vector3f & val) const336     Vector3f FromLinear(const Vector3f& val) const
337     {
338         return ApplyTransForm(val, transOETF_);
339     }
340 
RGBToXYZ(const Vector3f & rgb) const341     Vector3f RGBToXYZ(const Vector3f& rgb) const
342     {
343         return rgbToXyz_ * ToLinear(rgb);
344     }
345 
XYZToRGB(const Vector3f & xyz) const346     Vector3f XYZToRGB(const Vector3f& xyz) const
347     {
348         return ApplyTransForm(FromLinear(xyzToRgb_ * xyz), clamper_);
349     }
350 
351 private:
352     Matrix3f rgbToXyz_;
353     Matrix3f xyzToRgb_;
354     PixelTransformFunc transEOTF_;
355     PixelTransformFunc transOETF_;
356     PixelTransformFunc clamper_;
357     TransferParameters transferParams_;
358 };
359 
GetSRGBColorSpace()360 SimpleColorSpace &GetSRGBColorSpace()
361 {
362     static SimpleColorSpace sRGB {
363         {{Vector2f{0.640f, 0.330f}, {0.300f, 0.600f}, {0.150f, 0.060f}}}, // rgb base points.
364         {0.3127f, 0.3290f}, // white points.
365         {2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.04045f, 0.0f, 0.0f}}; // TransferParameters
366     return sRGB;
367 }
368 
GetAdobeRGBColorSpace()369 SimpleColorSpace &GetAdobeRGBColorSpace()
370 {
371     static SimpleColorSpace adobeRGB {
372         {{Vector2f{0.64f, 0.33f}, {0.21f, 0.71f}, {0.15f, 0.06f}}}, // rgb base points.
373         {0.3127f, 0.3290f}, // white points.
374         2.2f}; // gamma 2.2
375     return adobeRGB;
376 }
377 
GetDisplayP3ColorSpace()378 SimpleColorSpace &GetDisplayP3ColorSpace()
379 {
380     static SimpleColorSpace displayP3 {
381         {{Vector2f{0.680f, 0.320f}, {0.265f, 0.690f}, {0.150f, 0.060f}}}, // rgb base points.
382         {0.3127f, 0.3290f}, // white points.
383         {2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.039f, 0.0f, 0.0f}}; // TransferParameters
384     return displayP3;
385 }
386 
GetDCIP3ColorSpace()387 SimpleColorSpace &GetDCIP3ColorSpace()
388 {
389     static SimpleColorSpace dciP3 {
390         {{Vector2f{0.680f, 0.320f}, {0.265f, 0.690f}, {0.150f, 0.060f}}}, // rgb base points.
391         {0.314f, 0.351f}, // white points.
392         2.6f}; // gamma 2.6
393     return dciP3;
394 }
395 
GetBT2020ColorSpace()396 SimpleColorSpace &GetBT2020ColorSpace()
397 {
398     static SimpleColorSpace bt2020 {
399         {{Vector2f{0.708f, 0.292f}, {0.17f, 0.797f}, {0.131f, 0.046f}}}, // BT.2020 rgb base points.
400         {0.3127f, 0.3290f}, // BT.2020 white points.
401         {-2.0f, 0.1593017578125, 78.84375, 0.8359375, 18.8515625, 18.6875, 0.f}}; // PQ TransferParameters
402     return bt2020;
403 }
404 
IsValidMetaData(const std::vector<GraphicHDRMetaData> & metaDatas)405 bool IsValidMetaData(const std::vector<GraphicHDRMetaData> &metaDatas)
406 {
407     uint16_t validFlag = 0;
408     for (auto metaData : metaDatas) {
409         validFlag ^= 1 << metaData.key;
410     }
411 
412     uint16_t bitsToCheck = 0xFF;
413     // has complete and unique primaries;
414     return (validFlag & bitsToCheck) == bitsToCheck;
415 }
416 
GetColorSpaceFromMetaData(const std::vector<GraphicHDRMetaData> & metaDatas,float targetLum=0)417 SimpleColorSpace &GetColorSpaceFromMetaData(const std::vector<GraphicHDRMetaData> &metaDatas, float targetLum = 0)
418 {
419     std::vector<GraphicHDRMetaData> metaDataSorted = metaDatas;
420     std::sort(metaDataSorted.begin(), metaDataSorted.end(), [&](const GraphicHDRMetaData &a, const GraphicHDRMetaData &b)->bool {
421             return a.key < b.key;
422     });
423     static SimpleColorSpace hdrPq {
424          // rgb base points.
425         {{Vector2f{metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_RED_PRIMARY_X].value,
426                    metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_RED_PRIMARY_Y].value},
427                   {metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_GREEN_PRIMARY_X].value,
428                    metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_GREEN_PRIMARY_Y].value},
429                   {metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_BLUE_PRIMARY_X].value,
430                    metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_BLUE_PRIMARY_Y].value}}},
431         {metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_WHITE_PRIMARY_X].value,
432          metaDataSorted[GraphicHDRMetadataKey::GRAPHIC_MATAKEY_WHITE_PRIMARY_Y].value}, // white points.
433         {-2.0f, 0.1593017578125, 78.84375, 0.8359375, 18.8515625, 18.6875, 0.f}}; // PQ TransferParameters
434     return hdrPq;
435 }
436 
GetHdrPqColorSpace(const std::vector<GraphicHDRMetaData> & metaData,float targetLum=0.f)437 SimpleColorSpace &GetHdrPqColorSpace(const std::vector<GraphicHDRMetaData> &metaData, float targetLum = 0.f)
438 {
439     if (metaData.size() > 0 && IsValidMetaData(metaData)) {
440         return GetColorSpaceFromMetaData(metaData, targetLum);
441     }
442 
443     return GetBT2020ColorSpace();
444 }
445 
IsSupportedFormatForGamutConversion(int32_t pixelFormat)446 bool IsSupportedFormatForGamutConversion(int32_t pixelFormat)
447 {
448     static std::unordered_set<PixelFormat> supportedFormats = {
449         PixelFormat::PIXEL_FMT_RGBX_8888,
450         PixelFormat::PIXEL_FMT_RGBA_8888,
451         PixelFormat::PIXEL_FMT_RGB_888,
452         PixelFormat::PIXEL_FMT_BGRX_8888,
453         PixelFormat::PIXEL_FMT_BGRA_8888
454     };
455 
456     // Because PixelFormat has no enumeration for RBG_16,
457     // we use a temporary stub here for testing
458     // The final version should use a PixelFormat::PIXEL_FMT_RGBA_XXXX
459     return pixelFormat == STUB_PIXEL_FMT_RGBA_16161616 ||
460         supportedFormats.count(static_cast<PixelFormat>(pixelFormat)) > 0;
461 }
462 
IsSupportedColorGamut(ColorGamut colorGamut)463 bool IsSupportedColorGamut(ColorGamut colorGamut)
464 {
465     static std::unordered_set<ColorGamut> supportedColorGamuts = {
466         ColorGamut::COLOR_GAMUT_SRGB,
467         ColorGamut::COLOR_GAMUT_ADOBE_RGB,
468         ColorGamut::COLOR_GAMUT_DISPLAY_P3,
469         ColorGamut::COLOR_GAMUT_DCI_P3,
470         ColorGamut::COLOR_GAMUT_BT2020,
471         ColorGamut::COLOR_GAMUT_BT2100_PQ
472     };
473     return supportedColorGamuts.count(colorGamut) > 0;
474 }
475 
GetColorSpaceOfCertainGamut(ColorGamut colorGamut,const std::vector<GraphicHDRMetaData> & metaData={})476 SimpleColorSpace& GetColorSpaceOfCertainGamut(ColorGamut colorGamut, const std::vector<GraphicHDRMetaData> &metaData = {})
477 {
478     switch (colorGamut) {
479         case ColorGamut::COLOR_GAMUT_SRGB: {
480             return GetSRGBColorSpace();
481         }
482         case ColorGamut::COLOR_GAMUT_ADOBE_RGB: {
483             return GetAdobeRGBColorSpace();
484         }
485         case ColorGamut::COLOR_GAMUT_DISPLAY_P3:
486         case ColorGamut::COLOR_GAMUT_DCI_P3: {
487             return GetDisplayP3ColorSpace(); // Currently p3 colorspace is displayP3
488         }
489         case ColorGamut::COLOR_GAMUT_BT2020:
490         case ColorGamut::COLOR_GAMUT_BT2100_PQ: {
491             return GetHdrPqColorSpace(metaData);
492         }
493         default: {
494             return GetSRGBColorSpace();
495         }
496     }
497 }
498 
499 const uint16_t maxUint10 = 1023;
RGBUint8ToFloat(uint8_t val)500 float RGBUint8ToFloat(uint8_t val)
501 {
502     return val * 1.0f / 255.0f; // 255.0f is the max value.
503 }
504 
505 // Used to transfer integers of pictures with color depth of 10 bits to float
RGBUint10ToFloat(uint16_t val)506 float RGBUint10ToFloat(uint16_t val)
507 {
508     return val * 1.0f / maxUint10; // 1023.0f is the max value
509 }
510 
RGBFloatToUint8(float val)511 uint8_t RGBFloatToUint8(float val)
512 {
513     return static_cast<uint8_t>(Saturate(val) * 255 + 0.5f); // 255.0 is the max value, + 0.5f to avoid negative.
514 }
515 
516 // Used to transfer float values to integers for pictures with color depth of 10 bits
RGBFloatToUint10(float val)517 uint16_t RGBFloatToUint10(float val)
518 {
519     // 1023.0 is the max value, + 0.5f to avoid negative.
520     return static_cast<uint16_t>(Saturate(val) * maxUint10 + 0.5f);
521 }
522 
RGBUintToFloat(uint8_t * dst,uint8_t * src,int32_t pixelFormat,Vector3f & srcColor,Array3ptr & colorDst)523 Offset RGBUintToFloat(uint8_t* dst, uint8_t* src, int32_t pixelFormat, Vector3f &srcColor,
524     Array3ptr &colorDst)
525 {
526     // Because PixelFormat does not have enumeration for RGBA_16 or RGBA_1010102,
527     // we use two special IF statements here to realize the transfer process.
528     // They should to be adjusted to the SWITCH process after the enumerations are added.
529     if (pixelFormat == STUB_PIXEL_FMT_RGBA_16161616) {
530         auto src16 = reinterpret_cast<const uint16_t*>(src);
531         // R: src[0], G: src[1], B: src[2]
532         srcColor = {RGBUint10ToFloat(src16[0]), RGBUint10ToFloat(src16[1]), RGBUint10ToFloat(src16[2])};
533         // R: dst + 0, G: dst + 1, B: dst + 2
534         colorDst = {dst + 0, dst + 1, dst + 2};
535         // Alpha: linear transfer src[3] to dst[3]
536         dst[3] = RGBFloatToUint8(RGBUint10ToFloat(src16[3]));
537         const uint8_t outPixelBits = 4;
538         const uint8_t inPixelBits = 8;
539         // 8 bytes per pixel and HDR pictures are always redrawn as sRGB
540         return std::make_pair(inPixelBits, outPixelBits);
541     }
542     if (pixelFormat == STUB_PIXEL_FMT_RGBA_1010102) {
543         auto src32 = reinterpret_cast<const uint32_t*>(src);
544         // R: 0-9 bits, G: 10-19 ts, B: 20-29bits
545         srcColor = {RGBUint10ToFloat((*src32) & 0x3FF), RGBUint10ToFloat(((*src32) >> 10) & 0x3FF),
546              RGBUint10ToFloat(((*src32) >> 20) & 0x3FF)};
547         // R: dst + 0, G: dst + 1, B: dst + 2
548         colorDst = {dst + 0, dst + 1, dst + 2};
549         // Alpha: copy src[3] to dst[3]
550         const uint8_t rbgBitsNum = 30;
551         const uint8_t alphaBitMask = 0x3;
552         const uint8_t alphaPos = 3;
553         dst[alphaPos] = static_cast<uint8_t>(((*src32) >> rbgBitsNum) & alphaBitMask);
554         return std::make_pair(4, 4); // 4 bytes per pixel and HDR pictures are always redrawn as sRGB
555     }
556     switch (static_cast<PixelFormat>(pixelFormat)) {
557         case PixelFormat::PIXEL_FMT_RGBX_8888:
558         case PixelFormat::PIXEL_FMT_RGBA_8888: {
559             // R: src[0], G: src[1], B: src[2]
560             srcColor = {RGBUint8ToFloat(src[0]), RGBUint8ToFloat(src[1]), RGBUint8ToFloat(src[2])};
561             // R: dst + 0, G: dst + 1, B: dst + 2
562             colorDst = {dst + 0, dst + 1, dst + 2};
563             // Alpha: copy src[3] to dst[3]
564             dst[3] = src[3];
565             return std::make_pair(4, 4); // 4 bytes per pixel.
566         }
567         case PixelFormat::PIXEL_FMT_RGB_888: {
568             // R: src[0], G: src[1], B: src[2]
569             srcColor = {RGBUint8ToFloat(src[0]), RGBUint8ToFloat(src[1]), RGBUint8ToFloat(src[2])};
570             // R: dst + 0, G: dst + 1, B: dst + 2
571             colorDst = {dst + 0, dst + 1, dst + 2};
572             return std::make_pair(3, 3); // 3 bytes per pixel.
573         }
574         case PixelFormat::PIXEL_FMT_BGRX_8888:
575         case PixelFormat::PIXEL_FMT_BGRA_8888: {
576             // R: src[2], G: src[1], B: src[0]
577             srcColor = {RGBUint8ToFloat(src[2]), RGBUint8ToFloat(src[1]), RGBUint8ToFloat(src[0])};
578             // R: dst + 2, G: dst + 1, B: dst + 0
579             colorDst = {dst + 2, dst + 1, dst + 0};
580             // Alpha: copy src[3] to dst[3]
581             dst[3] = src[3];
582             return std::make_pair(4, 4); // 4 bytes per pixel.
583         }
584         default: {
585             RS_LOGE("RGBUintToFloat: unexpected pixelFormat(%d).", pixelFormat);
586             return std::make_pair(0, 0);
587         }
588     }
589 }
590 
ConvertColorGamut(uint8_t * dst,uint8_t * src,int32_t pixelFormat,SimpleColorSpace & srcColorSpace,SimpleColorSpace & dstColorSpace)591 Offset ConvertColorGamut(uint8_t* dst, uint8_t* src, int32_t pixelFormat, SimpleColorSpace& srcColorSpace,
592     SimpleColorSpace& dstColorSpace)
593 {
594     Vector3f srcColor;
595     Array3ptr colorDst; // color dst, 3 bytes (R G B).
596 
597     Offset len = RGBUintToFloat(dst, src, pixelFormat, srcColor, colorDst);
598     Vector3f outColor = dstColorSpace.XYZToRGB(srcColorSpace.RGBToXYZ(srcColor));
599     *(colorDst[0]) = RGBFloatToUint8(outColor[0]); // outColor 0 to colorDst[0]
600     *(colorDst[1]) = RGBFloatToUint8(outColor[1]); // outColor 1 to colorDst[1]
601     *(colorDst[2]) = RGBFloatToUint8(outColor[2]); // outColor 2 to colorDst[2]
602 
603     return len;
604 }
605 
ConvertBufferColorGamut(std::vector<uint8_t> & dstBuf,const sptr<OHOS::SurfaceBuffer> & srcBuf,ColorGamut srcGamut,ColorGamut dstGamut,const std::vector<GraphicHDRMetaData> & metaDatas)606 bool ConvertBufferColorGamut(std::vector<uint8_t>& dstBuf, const sptr<OHOS::SurfaceBuffer>& srcBuf,
607     ColorGamut srcGamut, ColorGamut dstGamut, const std::vector<GraphicHDRMetaData>& metaDatas)
608 {
609     RS_TRACE_NAME("ConvertBufferColorGamut");
610 
611     int32_t pixelFormat = srcBuf->GetFormat();
612     if (!IsSupportedFormatForGamutConversion(pixelFormat)) {
613         RS_LOGE("ConvertBufferColorGamut: the buffer's format is not supported.");
614         return false;
615     }
616     if (!IsSupportedColorGamut(srcGamut) || !IsSupportedColorGamut(dstGamut)) {
617         return false;
618     }
619 
620     uint32_t bufferSize = srcBuf->GetSize();
621     dstBuf.resize(bufferSize);
622 
623     auto bufferAddr = srcBuf->GetVirAddr();
624     uint8_t* srcStart = static_cast<uint8_t*>(bufferAddr);
625 
626     uint32_t offsetDst = 0, offsetSrc = 0;
627     auto& srcColorSpace = GetColorSpaceOfCertainGamut(srcGamut, metaDatas);
628     auto& dstColorSpace = GetColorSpaceOfCertainGamut(dstGamut, metaDatas);
629     while (offsetSrc < bufferSize) {
630         uint8_t* dst = &dstBuf[offsetDst];
631         uint8_t* src = srcStart + offsetSrc;
632         Offset len = ConvertColorGamut(dst, src, pixelFormat, srcColorSpace, dstColorSpace);
633         if (len.first == 0 || len.second == 0) {
634             return false;
635         }
636         offsetSrc += len.first;
637         offsetDst += len.second;
638     }
639     dstBuf.resize(offsetDst); // dstBuf size might not be as large ad srcBuf in HDR
640 
641     return true;
642 }
643 
GenerateSkImageInfo(const sptr<OHOS::SurfaceBuffer> & buffer)644 SkImageInfo GenerateSkImageInfo(const sptr<OHOS::SurfaceBuffer>& buffer)
645 {
646     SkColorType colorType = (buffer->GetFormat() == PIXEL_FMT_BGRA_8888) ?
647         kBGRA_8888_SkColorType : kRGBA_8888_SkColorType;
648     return SkImageInfo::Make(buffer->GetWidth(), buffer->GetHeight(),
649         colorType, kPremul_SkAlphaType);
650 }
651 
652 // YUV to RGBA: Pixel value conversion table
653 static int Table_fv1[256] = { -180, -179, -177, -176, -174, -173, -172, -170, -169, -167, -166, -165, -163, -162,
654     -160, -159, -158, -156, -155, -153, -152, -151, -149, -148, -146, -145, -144, -142, -141, -139,
655     -138, -137,  -135, -134, -132, -131, -130, -128, -127, -125, -124, -123, -121, -120, -118,
656     -117, -115, -114, -113, -111, -110, -108, -107, -106, -104, -103, -101, -100, -99, -97, -96,
657     -94, -93, -92, -90,  -89, -87, -86, -85, -83, -82, -80, -79, -78, -76, -75, -73, -72, -71,
658     -69, -68, -66, -65, -64, -62, -61, -59, -58, -57, -55, -54, -52, -51, -50, -48, -47, -45,
659     -44, -43, -41, -40, -38, -37,  -36, -34, -33, -31, -30, -29, -27, -26, -24, -23, -22, -20,
660     -19, -17, -16, -15, -13, -12, -10, -9, -8, -6, -5, -3, -2, 0, 1, 2, 4, 5, 7, 8, 9, 11, 12,
661     14, 15, 16, 18, 19, 21, 22, 23, 25, 26, 28, 29, 30, 32, 33, 35, 36, 37, 39, 40, 42, 43, 44,
662     46, 47, 49, 50, 51, 53, 54, 56, 57, 58, 60, 61, 63, 64, 65, 67, 68, 70, 71, 72, 74, 75, 77,
663     78, 79, 81, 82, 84, 85, 86, 88, 89, 91, 92, 93, 95, 96, 98, 99, 100, 102, 103, 105, 106, 107,
664     109, 110, 112, 113, 114, 116, 117, 119, 120, 122, 123, 124, 126, 127, 129, 130, 131, 133, 134,
665     136, 137, 138, 140, 141, 143, 144, 145, 147, 148,  150, 151, 152, 154, 155, 157, 158, 159, 161,
666     162, 164, 165, 166, 168, 169, 171, 172, 173, 175, 176, 178 };
667 static int Table_fv2[256] = { -92, -91, -91, -90, -89, -88, -88, -87, -86, -86, -85, -84, -83, -83, -82, -81,
668     -81, -80, -79, -78, -78, -77, -76, -76, -75, -74, -73, -73, -72, -71, -71, -70, -69, -68, -68, -67, -66,
669     -66, -65, -64, -63, -63, -62, -61, -61, -60, -59, -58, -58, -57, -56, -56, -55, -54, -53, -53, -52, -51,
670     -51, -50, -49, -48, -48, -47, -46, -46, -45, -44, -43, -43, -42, -41, -41, -40, -39, -38, -38, -37, -36,
671     -36, -35, -34, -33, -33, -32, -31, -31, -30, -29, -28, -28, -27, -26, -26, -25, -24, -23, -23, -22, -21,
672     -21, -20, -19, -18, -18, -17, -16, -16, -15, -14, -13, -13, -12, -11, -11, -10, -9, -8, -8, -7, -6, -6,
673     -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,
674     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,
675     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,
676     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,
677     75, 75, 76, 77, 77, 78, 79, 80, 80, 81, 82, 82, 83, 84, 85, 85, 86, 87, 87, 88, 89, 90, 90 };
678 static int Table_fu1[256] = { -44, -44, -44, -43, -43, -43, -42, -42, -42, -41, -41, -41, -40, -40, -40, -39, -39,
679     -39, -38, -38, -38, -37, -37, -37, -36, -36, -36, -35, -35, -35, -34, -34, -33, -33, -33, -32, -32, -32, -31,
680     -31, -31, -30, -30, -30, -29, -29, -29, -28, -28, -28, -27, -27, -27, -26, -26, -26, -25, -25, -25, -24, -24,
681     -24, -23, -23, -22, -22, -22, -21, -21, -21, -20, -20, -20, -19, -19, -19, -18, -18, -18, -17, -17, -17, -16,
682     -16, -16, -15, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -11, -11, -11, -10, -10, -10, -9, -9, -9, -8,
683     -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,
684     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,
685     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,
686     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,
687     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,
688     41, 42, 42, 42, 43, 43 };
689 static int Table_fu2[256] = { -227, -226, -224, -222, -220, -219, -217, -215, -213, -212, -210, -208, -206, -204,
690     -203, -201, -199, -197, -196, -194, -192, -190, -188, -187, -185, -183, -181, -180, -178, -176, -174, -173,
691     -171, -169, -167, -165, -164, -162, -160, -158, -157, -155, -153, -151, -149, -148, -146, -144, -142, -141,
692     -139, -137, -135, -134, -132, -130, -128, -126, -125, -123, -121, -119, -118, -116, -114, -112, -110, -109,
693     -107, -105, -103, -102, -100, -98, -96, -94, -93, -91, -89, -87, -86, -84, -82, -80, -79, -77, -75, -73,
694     -71, -70, -68, -66, -64, -63, -61, -59, -57, -55, -54, -52, -50, -48, -47, -45, -43, -41, -40, -38, -36,
695     -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,
696     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,
697     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,
698     104, 106, 108, 109, 111, 113, 115, 117, 118, 120, 122, 124, 125, 127, 129, 131, 133, 134, 136, 138, 140, 141,
699     143, 145, 147, 148, 150, 152, 154, 156, 157, 159, 161, 163, 164, 166, 168, 170, 172, 173, 175, 177, 179, 180,
700     182, 184, 186, 187, 189, 191, 193, 195, 196, 198, 200, 202, 203, 205, 207, 209, 211, 212, 214, 216, 218,
701     219, 221, 223, 225 };
702 
ConvertYUV420SPToRGBA(std::vector<uint8_t> & rgbaBuf,const sptr<OHOS::SurfaceBuffer> & srcBuf)703 bool ConvertYUV420SPToRGBA(std::vector<uint8_t>& rgbaBuf, const sptr<OHOS::SurfaceBuffer>& srcBuf)
704 {
705     if (srcBuf == nullptr || rgbaBuf.empty()) {
706         RS_LOGE("RSBaseRenderUtil::ConvertYUV420SPToRGBA invalid params");
707         return false;
708     }
709     uint8_t* rgbaDst = &rgbaBuf[0];
710     uint8_t* src = static_cast<uint8_t*>(srcBuf->GetVirAddr());
711     if (src == nullptr || rgbaDst == nullptr) {
712         RS_LOGE("RSBaseRenderUtil::ConvertYUV420SPToRGBA null buffer ptr");
713         return false;
714     }
715     int32_t bufferWidth = srcBuf->GetWidth();
716     int32_t bufferHeight = srcBuf->GetHeight();
717     int32_t bufferStride = srcBuf->GetStride();
718     int32_t bufferSize = static_cast<int32_t>(srcBuf->GetSize());
719     if (bufferWidth < 1 || bufferHeight < 1 || bufferStride < 1 || bufferSize < 1) {
720         RS_LOGE("RSBaseRenderUtil::ConvertYUV420SPToRGBA invalid buffer size, w/h/stride/size = [%d, %d, %d, %d]",
721             bufferWidth, bufferHeight, bufferStride, bufferSize);
722         return false;
723     }
724 #ifdef PADDING_HEIGHT_32
725     // temporally only update buffer len for video stream
726     if (srcBuf->GetFormat() == PIXEL_FMT_YCBCR_420_SP) {
727         int32_t paddingBase = 32;
728         bufferHeight = ((bufferHeight - 1) / paddingBase + 1) * paddingBase;
729     }
730 #endif
731     float yuvSizeFactor = 1.5f; // y:uv = 2:1
732     int32_t len = bufferStride * bufferHeight;
733     int32_t totalLen = static_cast<int32_t>(len * yuvSizeFactor);
734     if (bufferSize < totalLen) {
735         RS_LOGE("RSBaseRenderUtil::ConvertYUV420SPToRGBA invalid buffer size, "
736             "w/h/stride/size/totalLen = [%d, %d, %d, %d, %d]",
737             bufferWidth, srcBuf->GetHeight(), bufferStride, bufferSize, totalLen);
738         return false;
739     }
740     uint8_t* ybase = src;
741     uint8_t* ubase = &src[len];
742 
743     int rgb[3] = {0, 0, 0};
744     int idx = 0;
745     int rdif = 0;
746     int invgdif = 0;
747     int bdif = 0;
748     for (int i = 0; i < bufferHeight; i++) {
749         for (int j = 0; j < bufferWidth; j++) {
750             int Y = static_cast<int>(ybase[i * bufferStride + j]);
751             int U = static_cast<int>(ubase[i / 2 * bufferStride + (j / 2) * 2 + 1]);
752             int V = static_cast<int>(ubase[i / 2 * bufferStride + (j / 2) * 2]);
753             if (srcBuf->GetFormat() == PIXEL_FMT_YCBCR_420_SP) {
754                 std::swap(U, V);
755             }
756             rdif = Table_fv1[V];
757             invgdif = Table_fu1[U] + Table_fv2[V];
758             bdif = Table_fu2[U];
759 
760             rgb[0] = Y + rdif;
761             rgb[1] = Y - invgdif;
762             rgb[2] = Y + bdif; // 2 is index
763 
764             for (int k = 0; k < 3; k++) { // 3 is index
765                 idx = (i * bufferWidth + j) * 4 + k; // 4 is color channel
766                 if (rgb[k] >= 0 && rgb[k] <= 255) { // 255 is upper threshold
767                     rgbaDst[idx] = static_cast<uint8_t>(rgb[k]);
768                 } else {
769                     rgbaDst[idx] = (rgb[k] < 0) ? 0 : 255; // 255 is upper threshold
770                 }
771             }
772             ++idx;
773             rgbaDst[idx] = 255; // 255 is upper threshold
774         }
775     }
776     return true;
777 }
778 } // namespace Detail
779 
GetFrameBufferRequestConfig(const ScreenInfo & screenInfo,bool isPhysical)780 BufferRequestConfig RSBaseRenderUtil::GetFrameBufferRequestConfig(
781     const ScreenInfo& screenInfo, bool isPhysical)
782 {
783     BufferRequestConfig config {};
784     const auto width = isPhysical ? screenInfo.width : screenInfo.GetRotatedWidth();
785     const auto height = isPhysical ? screenInfo.height : screenInfo.GetRotatedHeight();
786     config.width = static_cast<int32_t>(width);
787     config.height = static_cast<int32_t>(height);
788     config.strideAlignment = 0x8; // default stride is 8 Bytes.
789     config.format = PIXEL_FMT_RGBA_8888;
790     config.usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_FB;
791     config.timeout = 0;
792     return config;
793 }
794 
DropFrameProcess(RSSurfaceHandler & node)795 GSError RSBaseRenderUtil::DropFrameProcess(RSSurfaceHandler& node)
796 {
797     auto availableBufferCnt = node.GetAvailableBufferCount();
798     const auto& surfaceConsumer = node.GetConsumer();
799     if (surfaceConsumer == nullptr) {
800         RS_LOGE("RsDebug RSBaseRenderUtil::DropFrameProcess (node: %" PRIu64 "): surfaceConsumer is null!",
801             node.GetNodeId());
802         return OHOS::GSERROR_NO_CONSUMER;
803     }
804 
805     int32_t maxDirtyListSize = static_cast<int32_t>(surfaceConsumer->GetQueueSize()) - 1;
806     // maxDirtyListSize > 2 means QueueSize >3 too
807     if (maxDirtyListSize > 2 && availableBufferCnt >= maxDirtyListSize) {
808         RS_TRACE_NAME("DropFrame");
809         OHOS::sptr<SurfaceBuffer> cbuffer;
810         Rect damage;
811         sptr<SyncFence> acquireFence = SyncFence::INVALID_FENCE;
812         int64_t timestamp = 0;
813         auto ret = surfaceConsumer->AcquireBuffer(cbuffer, acquireFence, timestamp, damage);
814         if (ret != OHOS::SURFACE_ERROR_OK) {
815             RS_LOGW("RSBaseRenderUtil::DropFrameProcess(node: %" PRIu64 "): AcquireBuffer failed(ret: %d), do nothing ",
816                 node.GetNodeId(), ret);
817             return OHOS::GSERROR_NO_BUFFER;
818         }
819 
820         ret = surfaceConsumer->ReleaseBuffer(cbuffer, SyncFence::INVALID_FENCE);
821         if (ret != OHOS::SURFACE_ERROR_OK) {
822             RS_LOGW("RSBaseRenderUtil::DropFrameProcess(node: %" PRIu64
823                     "): ReleaseBuffer failed(ret: %d), Acquire done ",
824                 node.GetNodeId(), ret);
825         }
826         availableBufferCnt = node.ReduceAvailableBuffer();
827         RS_LOGD("RsDebug RSBaseRenderUtil::DropFrameProcess (node: %" PRIu64 "), drop one frame", node.GetNodeId());
828     }
829 
830     return OHOS::GSERROR_OK;
831 }
832 
ConsumeAndUpdateBuffer(RSSurfaceHandler & surfaceHandler)833 bool RSBaseRenderUtil::ConsumeAndUpdateBuffer(RSSurfaceHandler& surfaceHandler)
834 {
835     auto availableBufferCnt = surfaceHandler.GetAvailableBufferCount();
836     if (availableBufferCnt <= 0) {
837         // this node has no new buffer, try use old buffer.
838         return true;
839     }
840     auto& consumer = surfaceHandler.GetConsumer();
841     if (consumer == nullptr) {
842         return false;
843     }
844 
845     DropFrameProcess(surfaceHandler);
846     sptr<SurfaceBuffer> buffer;
847     sptr<SyncFence> acquireFence = SyncFence::INVALID_FENCE;
848     int64_t timestamp = 0;
849     Rect damage;
850     auto ret = consumer->AcquireBuffer(buffer, acquireFence, timestamp, damage);
851     if (buffer == nullptr || ret != SURFACE_ERROR_OK) {
852         RS_LOGE("RsDebug surfaceHandler(id: %" PRIu64 ") AcquireBuffer failed(ret: %d)!",
853             surfaceHandler.GetNodeId(), ret);
854         return false;
855     }
856 
857     surfaceHandler.SetBuffer(buffer, acquireFence, damage, timestamp);
858     surfaceHandler.SetCurrentFrameBufferConsumed();
859     RS_LOGD("RsDebug surfaceHandler(id: %" PRIu64 ") AcquireBuffer success, timestamp = %" PRId64 ".",
860         surfaceHandler.GetNodeId(), timestamp);
861     availableBufferCnt = surfaceHandler.ReduceAvailableBuffer();
862     return true;
863 }
864 
ReleaseBuffer(RSSurfaceHandler & surfaceHandler)865 bool RSBaseRenderUtil::ReleaseBuffer(RSSurfaceHandler& surfaceHandler)
866 {
867     auto& consumer = surfaceHandler.GetConsumer();
868     if (consumer == nullptr) {
869         return false;
870     }
871 
872     auto& preBuffer = surfaceHandler.GetPreBuffer();
873     if (preBuffer.buffer != nullptr) {
874         auto ret = consumer->ReleaseBuffer(preBuffer.buffer, preBuffer.releaseFence);
875         if (ret != OHOS::SURFACE_ERROR_OK) {
876             RS_LOGE("RsDebug surfaceHandler(id: %" PRIu64 ") ReleaseBuffer failed(ret: %d)!",
877                 surfaceHandler.GetNodeId(), ret);
878             return false;
879         }
880         // reset prevBuffer if we release it successfully,
881         // to avoid releasing the same buffer next frame in some situations.
882         preBuffer.Reset();
883     }
884 
885     return true;
886 }
887 
IsColorFilterModeValid(ColorFilterMode mode)888 bool RSBaseRenderUtil::IsColorFilterModeValid(ColorFilterMode mode)
889 {
890     bool valid = false;
891     switch (mode) {
892         case ColorFilterMode::INVERT_COLOR_DISABLE_MODE:
893         case ColorFilterMode::INVERT_COLOR_ENABLE_MODE:
894         case ColorFilterMode::DALTONIZATION_PROTANOMALY_MODE:
895         case ColorFilterMode::DALTONIZATION_DEUTERANOMALY_MODE:
896         case ColorFilterMode::DALTONIZATION_TRITANOMALY_MODE:
897         case ColorFilterMode::INVERT_DALTONIZATION_PROTANOMALY_MODE:
898         case ColorFilterMode::INVERT_DALTONIZATION_DEUTERANOMALY_MODE:
899         case ColorFilterMode::INVERT_DALTONIZATION_TRITANOMALY_MODE:
900         case ColorFilterMode::DALTONIZATION_NORMAL_MODE:
901         case ColorFilterMode::COLOR_FILTER_END:
902             valid = true;
903             break;
904         default:
905             valid = false;
906     }
907     return valid;
908 }
909 
SetColorFilterModeToPaint(ColorFilterMode colorFilterMode,SkPaint & paint)910 void RSBaseRenderUtil::SetColorFilterModeToPaint(ColorFilterMode colorFilterMode, SkPaint& paint)
911 {
912     switch (colorFilterMode) {
913         case ColorFilterMode::INVERT_COLOR_ENABLE_MODE:
914             paint.setColorFilter(Detail::InvertColorMat());
915             break;
916         case ColorFilterMode::DALTONIZATION_PROTANOMALY_MODE:
917             paint.setColorFilter(Detail::ProtanomalyMat());
918             break;
919         case ColorFilterMode::DALTONIZATION_DEUTERANOMALY_MODE:
920             paint.setColorFilter(Detail::DeuteranomalyMat());
921             break;
922         case ColorFilterMode::DALTONIZATION_TRITANOMALY_MODE:
923             paint.setColorFilter(Detail::TritanomalyMat());
924             break;
925         case ColorFilterMode::INVERT_DALTONIZATION_PROTANOMALY_MODE:
926             paint.setColorFilter(Detail::InvertProtanomalyMat());
927             break;
928         case ColorFilterMode::INVERT_DALTONIZATION_DEUTERANOMALY_MODE:
929             paint.setColorFilter(Detail::InvertDeuteranomalyMat());
930             break;
931         case ColorFilterMode::INVERT_DALTONIZATION_TRITANOMALY_MODE:
932             paint.setColorFilter(Detail::InvertTritanomalyMat());
933             break;
934         // INVERT_COLOR_DISABLE_MODE and DALTONIZATION_NORMAL_MODE couldn't be in this process
935         case ColorFilterMode::INVERT_COLOR_DISABLE_MODE:
936         case ColorFilterMode::DALTONIZATION_NORMAL_MODE:
937         case ColorFilterMode::COLOR_FILTER_END:
938         default:
939             paint.setColorFilter(nullptr);
940     }
941 }
942 
IsBufferValid(const sptr<SurfaceBuffer> & buffer)943 bool RSBaseRenderUtil::IsBufferValid(const sptr<SurfaceBuffer>& buffer)
944 {
945     if (!buffer) {
946         RS_LOGE("RSBaseRenderUtil: buffer is nullptr");
947         return false;
948     }
949     auto addr = buffer->GetVirAddr();
950     if (addr == nullptr) {
951         RS_LOGE("RSBaseRenderUtil: buffer has no vir addr");
952         return false;
953     }
954     if (buffer->GetWidth() <= 0 || buffer->GetHeight() <= 0) {
955         RS_LOGE("RSBaseRenderUtil: this buffer has negative width or height [%d %d]",
956             buffer->GetWidth(), buffer->GetHeight());
957         return false;
958     }
959     return true;
960 }
961 
GetSurfaceTransformMatrix(const RSSurfaceRenderNode & node,const RectF & bounds)962 SkMatrix RSBaseRenderUtil::GetSurfaceTransformMatrix(const RSSurfaceRenderNode& node, const RectF& bounds)
963 {
964     SkMatrix matrix;
965     const float boundsWidth = bounds.GetWidth();
966     const float boundsHeight = bounds.GetHeight();
967     const sptr<Surface>& surface = node.GetConsumer();
968     if (surface == nullptr) {
969         return matrix;
970     }
971 
972     auto transform = GetRotateTransform(surface->GetTransform());
973     switch (transform) {
974         case GraphicTransformType::GRAPHIC_ROTATE_90: {
975             matrix.preTranslate(0, boundsHeight);
976             matrix.preRotate(-90); // rotate 90 degrees anti-clockwise at last.
977             break;
978         }
979         case GraphicTransformType::GRAPHIC_ROTATE_180: {
980             matrix.preTranslate(boundsWidth, boundsHeight);
981             matrix.preRotate(-180); // rotate 180 degrees anti-clockwise at last.
982             break;
983         }
984         case GraphicTransformType::GRAPHIC_ROTATE_270: {
985             matrix.preTranslate(boundsWidth, 0);
986             matrix.preRotate(-270); // rotate 270 degrees anti-clockwise at last.
987             break;
988         }
989         default:
990             break;
991     }
992 
993     return matrix;
994 }
995 
GetNodeGravityMatrix(const RSSurfaceRenderNode & node,const sptr<SurfaceBuffer> & buffer,const RectF & bounds)996 SkMatrix RSBaseRenderUtil::GetNodeGravityMatrix(
997     const RSSurfaceRenderNode& node, const sptr<SurfaceBuffer>& buffer, const RectF& bounds)
998 {
999     SkMatrix gravityMatrix;
1000     if (buffer == nullptr) {
1001         return gravityMatrix;
1002     }
1003 
1004     const RSProperties& property = node.GetRenderProperties();
1005     const Gravity gravity = property.GetFrameGravity();
1006     const float frameWidth = buffer->GetSurfaceBufferWidth();
1007     const float frameHeight = buffer->GetSurfaceBufferHeight();
1008     const float boundsWidth = bounds.GetWidth();
1009     const float boundsHeight = bounds.GetHeight();
1010     if (frameWidth == boundsWidth && frameHeight == boundsHeight) {
1011         return gravityMatrix;
1012     }
1013 
1014     if (!RSPropertiesPainter::GetGravityMatrix(gravity,
1015         RectF {0.0f, 0.0f, boundsWidth, boundsHeight}, frameWidth, frameHeight, gravityMatrix)) {
1016         RS_LOGD("RSDividedRenderUtil::DealWithNodeGravity did not obtain gravity matrix.");
1017     }
1018 
1019     return gravityMatrix;
1020 }
1021 
DealWithSurfaceRotationAndGravity(const RSSurfaceRenderNode & node,RectF & localBounds,BufferDrawParam & params)1022 void RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(
1023     const RSSurfaceRenderNode& node, RectF& localBounds, BufferDrawParam& params)
1024 {
1025     // the surface can rotate itself.
1026     params.matrix.preConcat(RSBaseRenderUtil::GetSurfaceTransformMatrix(node, localBounds));
1027     const sptr<Surface>& surface = node.GetConsumer(); // private func, guarantee surface is not nullptr.
1028     auto transform = GetRotateTransform(surface->GetTransform());
1029     if (transform == GraphicTransformType::GRAPHIC_ROTATE_90 ||
1030         transform == GraphicTransformType::GRAPHIC_ROTATE_270) {
1031         // after rotate, we should swap dstRect and bound's width and height.
1032         std::swap(localBounds.width_, localBounds.height_);
1033         params.dstRect = SkRect::MakeWH(localBounds.GetWidth(), localBounds.GetHeight());
1034     }
1035 
1036     // deal with buffer's gravity effect in node's inner space.
1037     params.matrix.preConcat(RSBaseRenderUtil::GetNodeGravityMatrix(node, params.buffer, localBounds));
1038     // because we use the gravity matrix above(which will implicitly includes scale effect),
1039     // we must disable the scale effect that from srcRect to dstRect.
1040     params.dstRect = params.srcRect;
1041 }
1042 
FlipMatrix(const RSSurfaceRenderNode & node,BufferDrawParam & params)1043 void RSBaseRenderUtil::FlipMatrix(const RSSurfaceRenderNode& node, BufferDrawParam& params)
1044 {
1045     auto& consumer = node.GetConsumer();
1046     if (consumer == nullptr) {
1047         RS_LOGW("RSBaseRenderUtil::FlipMatrix consumer is null");
1048         return;
1049     }
1050     const int angle = 180;
1051     Sk3DView sk3DView;
1052     switch (GetFlipTransform(consumer->GetTransform())) {
1053         case GraphicTransformType::GRAPHIC_FLIP_H: {
1054             sk3DView.rotateX(angle);
1055             break;
1056         }
1057         case GraphicTransformType::GRAPHIC_FLIP_V: {
1058             sk3DView.rotateY(angle);
1059             break;
1060         }
1061         default: {
1062             return;
1063         }
1064     }
1065     RS_LOGD("RSBaseRenderUtil::FlipMatrix %d", consumer->GetTransform());
1066     SkMatrix flip;
1067     sk3DView.getMatrix(&flip);
1068     const float half = 0.5f;
1069     flip.preTranslate(-half * params.dstRect.width(), -half * params.dstRect.height());
1070     flip.postTranslate(half * params.dstRect.width(), half * params.dstRect.height());
1071     params.matrix.preConcat(flip);
1072 }
1073 
SetPropertiesForCanvas(RSPaintFilterCanvas & canvas,const BufferDrawParam & params)1074 void RSBaseRenderUtil::SetPropertiesForCanvas(RSPaintFilterCanvas& canvas, const BufferDrawParam& params)
1075 {
1076     if (params.isNeedClip) {
1077         if (!params.cornerRadius.IsZero()) {
1078             canvas.clipRRect(RSPropertiesPainter::RRect2SkRRect(params.clipRRect), true);
1079         } else {
1080             canvas.clipRect(params.clipRect);
1081         }
1082     }
1083     if (SkColorGetA(params.backgroundColor) != SK_AlphaTRANSPARENT) {
1084         canvas.drawColor(params.backgroundColor);
1085     }
1086     canvas.concat(params.matrix);
1087 }
1088 
ConvertBufferToBitmap(sptr<SurfaceBuffer> buffer,std::vector<uint8_t> & newBuffer,ColorGamut dstGamut,SkBitmap & bitmap,const std::vector<GraphicHDRMetaData> & metaDatas)1089 bool RSBaseRenderUtil::ConvertBufferToBitmap(sptr<SurfaceBuffer> buffer, std::vector<uint8_t>& newBuffer,
1090     ColorGamut dstGamut, SkBitmap& bitmap, const std::vector<GraphicHDRMetaData>& metaDatas)
1091 {
1092     if (!IsBufferValid(buffer)) {
1093         return false;
1094     }
1095     bool bitmapCreated = false;
1096     ColorGamut srcGamut = static_cast<ColorGamut>(buffer->GetSurfaceBufferColorGamut());
1097     // [PLANNING]: We will not use this tmp newBuffer if we use GPU to do the color conversions.
1098     // Attention: make sure newBuffer's lifecycle is longer than the moment call drawBitmap
1099     if (buffer->GetFormat() == PIXEL_FMT_YCRCB_420_SP || buffer->GetFormat() == PIXEL_FMT_YCBCR_420_SP) {
1100         bitmapCreated = CreateYuvToRGBABitMap(buffer, newBuffer, bitmap);
1101     } else if (buffer->GetFormat() == Detail::STUB_PIXEL_FMT_RGBA_16161616) {
1102         bitmapCreated = CreateNewColorGamutBitmap(buffer, newBuffer, bitmap, srcGamut, dstGamut, metaDatas);
1103     } else if (srcGamut != dstGamut) {
1104         RS_LOGD("RSBaseRenderUtil::ConvertBufferToBitmap: need to convert color gamut.");
1105         bitmapCreated = CreateNewColorGamutBitmap(buffer, newBuffer, bitmap, srcGamut, dstGamut);
1106     } else {
1107         bitmapCreated = CreateBitmap(buffer, bitmap);
1108     }
1109     return bitmapCreated;
1110 }
1111 
CreateYuvToRGBABitMap(sptr<OHOS::SurfaceBuffer> buffer,std::vector<uint8_t> & newBuffer,SkBitmap & bitmap)1112 bool RSBaseRenderUtil::CreateYuvToRGBABitMap(sptr<OHOS::SurfaceBuffer> buffer, std::vector<uint8_t>& newBuffer,
1113     SkBitmap& bitmap)
1114 {
1115     newBuffer.resize(buffer->GetWidth() * buffer->GetHeight() * 4, 0); // 4 is color channel
1116     if (!Detail::ConvertYUV420SPToRGBA(newBuffer, buffer)) {
1117         return false;
1118     }
1119 
1120     SkColorType colorType = kRGBA_8888_SkColorType;
1121     SkImageInfo imageInfo = SkImageInfo::Make(buffer->GetWidth(), buffer->GetHeight(),
1122         colorType, kPremul_SkAlphaType);
1123     SkPixmap pixmap(imageInfo, newBuffer.data(), buffer->GetWidth() * 4); // 4 is color channel
1124     return bitmap.installPixels(pixmap);
1125 }
1126 
CreateBitmap(sptr<OHOS::SurfaceBuffer> buffer,SkBitmap & bitmap)1127 bool RSBaseRenderUtil::CreateBitmap(sptr<OHOS::SurfaceBuffer> buffer, SkBitmap& bitmap)
1128 {
1129     SkImageInfo imageInfo = Detail::GenerateSkImageInfo(buffer);
1130     SkPixmap pixmap(imageInfo, buffer->GetVirAddr(), buffer->GetStride());
1131     return bitmap.installPixels(pixmap);
1132 }
1133 
CreateNewColorGamutBitmap(sptr<OHOS::SurfaceBuffer> buffer,std::vector<uint8_t> & newBuffer,SkBitmap & bitmap,ColorGamut srcGamut,ColorGamut dstGamut,const std::vector<GraphicHDRMetaData> & metaDatas)1134 bool RSBaseRenderUtil::CreateNewColorGamutBitmap(sptr<OHOS::SurfaceBuffer> buffer, std::vector<uint8_t>& newBuffer,
1135     SkBitmap& bitmap, ColorGamut srcGamut, ColorGamut dstGamut, const std::vector<GraphicHDRMetaData>& metaDatas)
1136 {
1137     bool convertRes = Detail::ConvertBufferColorGamut(newBuffer, buffer, srcGamut, dstGamut, metaDatas);
1138     if (convertRes) {
1139         RS_LOGW("CreateNewColorGamutBitmap: convert color gamut succeed, use new buffer to create bitmap.");
1140         SkImageInfo imageInfo = Detail::GenerateSkImageInfo(buffer);
1141         SkPixmap pixmap(imageInfo, newBuffer.data(), buffer->GetStride());
1142         return bitmap.installPixels(pixmap);
1143     } else {
1144         RS_LOGW("CreateNewColorGamutBitmap: convert color gamut failed, use old buffer to create bitmap.");
1145         return CreateBitmap(buffer, bitmap);
1146     }
1147 }
1148 
ParseTransactionData(MessageParcel & parcel)1149 std::unique_ptr<RSTransactionData> RSBaseRenderUtil::ParseTransactionData(MessageParcel& parcel)
1150 {
1151     RS_TRACE_NAME("UnMarsh RSTransactionData: data size:" + std::to_string(parcel.GetDataSize()));
1152     auto transactionData = parcel.ReadParcelable<RSTransactionData>();
1153     if (!transactionData) {
1154         RS_TRACE_NAME("UnMarsh RSTransactionData fail!");
1155         RS_LOGE("UnMarsh RSTransactionData fail!");
1156         return nullptr;
1157     }
1158     RS_TRACE_NAME("UnMarsh RSTransactionData: recv data from " + std::to_string(transactionData->GetSendingPid()));
1159     std::unique_ptr<RSTransactionData> transData(transactionData);
1160     return transData;
1161 }
1162 
WriteSurfaceRenderNodeToPng(const RSSurfaceRenderNode & node)1163 bool RSBaseRenderUtil::WriteSurfaceRenderNodeToPng(const RSSurfaceRenderNode& node)
1164 {
1165     auto type = RSSystemProperties::GetDumpSurfaceType();
1166     if (type == DumpSurfaceType::DISABLED || type == DumpSurfaceType::PIXELMAP) {
1167         return false;
1168     }
1169     uint64_t id = RSSystemProperties::GetDumpSurfaceId();
1170     if (type == DumpSurfaceType::SINGLESURFACE && !ROSEN_EQ(node.GetId(), id)) {
1171         return false;
1172     }
1173     sptr<SurfaceBuffer> buffer = node.GetBuffer();
1174     if (buffer == nullptr) {
1175         return false;
1176     }
1177     BufferHandle *bufferHandle =  buffer->GetBufferHandle();
1178     if (bufferHandle == nullptr) {
1179         return false;
1180     }
1181 
1182     struct timeval now;
1183     gettimeofday(&now, nullptr);
1184     constexpr int secToUsec = 1000 * 1000;
1185     int64_t nowVal =  static_cast<int64_t>(now.tv_sec) * secToUsec + static_cast<int64_t>(now.tv_usec);
1186     std::string filename = "/data/SurfaceRenderNode_" +
1187         node.GetName() + "_"  +
1188         std::to_string(node.GetId()) + "_" +
1189         std::to_string(nowVal) + ".png";
1190 
1191     WriteToPngParam param;
1192     param.width = static_cast<uint32_t>(bufferHandle->width);
1193     param.height = static_cast<uint32_t>(bufferHandle->height);
1194     param.data = (uint8_t*)(buffer->GetVirAddr());
1195     param.stride = static_cast<uint32_t>(bufferHandle->stride);
1196     param.bitDepth = Detail::BITMAP_DEPTH;
1197 
1198     return WriteToPng(filename, param);
1199 }
1200 
WritePixelMapToPng(Media::PixelMap & pixelMap)1201 bool RSBaseRenderUtil::WritePixelMapToPng(Media::PixelMap& pixelMap)
1202 {
1203     auto type = RSSystemProperties::GetDumpSurfaceType();
1204     if (type != DumpSurfaceType::PIXELMAP) {
1205         return false;
1206     }
1207     struct timeval now;
1208     gettimeofday(&now, nullptr);
1209     constexpr int secToUsec = 1000 * 1000;
1210     int64_t nowVal =  static_cast<int64_t>(now.tv_sec) * secToUsec + static_cast<int64_t>(now.tv_usec);
1211     std::string filename = "/data/PixelMap_" + std::to_string(nowVal) + ".png";
1212 
1213     WriteToPngParam param;
1214     param.width = static_cast<uint32_t>(pixelMap.GetWidth());
1215     param.height = static_cast<uint32_t>(pixelMap.GetHeight());
1216     param.data = pixelMap.GetPixels();
1217     param.stride = static_cast<uint32_t>(pixelMap.GetRowBytes());
1218     param.bitDepth = Detail::BITMAP_DEPTH;
1219 
1220     return WriteToPng(filename, param);
1221 }
1222 
WriteToPng(const std::string & filename,const WriteToPngParam & param)1223 bool RSBaseRenderUtil::WriteToPng(const std::string &filename, const WriteToPngParam &param)
1224 {
1225     RS_LOGI("RSBaseRenderUtil::WriteToPng filename = %s", filename.c_str());
1226     png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
1227     if (pngStruct == nullptr) {
1228         return false;
1229     }
1230     png_infop pngInfo = png_create_info_struct(pngStruct);
1231     if (pngInfo == nullptr) {
1232         png_destroy_write_struct(&pngStruct, nullptr);
1233         return false;
1234     }
1235 
1236     FILE *fp = fopen(filename.c_str(), "wb");
1237     if (fp == nullptr) {
1238         png_destroy_write_struct(&pngStruct, &pngInfo);
1239         return false;
1240     }
1241     png_init_io(pngStruct, fp);
1242 
1243     // set png header
1244     png_set_IHDR(pngStruct, pngInfo,
1245         param.width, param.height,
1246         param.bitDepth,
1247         PNG_COLOR_TYPE_RGBA,
1248         PNG_INTERLACE_NONE,
1249         PNG_COMPRESSION_TYPE_BASE,
1250         PNG_FILTER_TYPE_BASE);
1251     png_set_packing(pngStruct); // set packing info
1252     png_write_info(pngStruct, pngInfo); // write to header
1253 
1254     for (uint32_t i = 0; i < param.height; i++) {
1255         png_write_row(pngStruct, param.data + (i * param.stride));
1256     }
1257     png_write_end(pngStruct, pngInfo);
1258 
1259     // free
1260     png_destroy_write_struct(&pngStruct, &pngInfo);
1261     int ret = fclose(fp);
1262     return ret == 0;
1263 }
1264 
GetRotateTransform(GraphicTransformType transform)1265 GraphicTransformType RSBaseRenderUtil::GetRotateTransform(GraphicTransformType transform)
1266 {
1267     switch (transform) {
1268         case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
1269         case GraphicTransformType::GRAPHIC_FLIP_V_ROT90: {
1270             return GraphicTransformType::GRAPHIC_ROTATE_90;
1271         }
1272         case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
1273         case GraphicTransformType::GRAPHIC_FLIP_V_ROT180: {
1274             return GraphicTransformType::GRAPHIC_ROTATE_180;
1275         }
1276         case GraphicTransformType::GRAPHIC_FLIP_H_ROT270:
1277         case GraphicTransformType::GRAPHIC_FLIP_V_ROT270: {
1278             return GraphicTransformType::GRAPHIC_ROTATE_270;
1279         }
1280         default: {
1281             return transform;
1282         }
1283     }
1284 }
1285 
GetFlipTransform(GraphicTransformType transform)1286 GraphicTransformType RSBaseRenderUtil::GetFlipTransform(GraphicTransformType transform)
1287 {
1288     switch (transform) {
1289         case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
1290         case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
1291         case GraphicTransformType::GRAPHIC_FLIP_H_ROT270: {
1292             return GraphicTransformType::GRAPHIC_FLIP_H;
1293         }
1294         case GraphicTransformType::GRAPHIC_FLIP_V_ROT90:
1295         case GraphicTransformType::GRAPHIC_FLIP_V_ROT180:
1296         case GraphicTransformType::GRAPHIC_FLIP_V_ROT270: {
1297             return GraphicTransformType::GRAPHIC_FLIP_V;
1298         }
1299         default: {
1300             return transform;
1301         }
1302     }
1303 }
1304 } // namespace Rosen
1305 } // namespace OHOS
1306