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