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