1 /*
2 * Copyright (c) 2021-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 "render/rs_image.h"
17
18 #include "common/rs_common_tools.h"
19 #include "pipeline/rs_recording_canvas.h"
20 #include "pipeline/sk_resource_manager.h"
21 #include "platform/common/rs_log.h"
22 #include "platform/common/rs_system_properties.h"
23 #include "property/rs_properties_painter.h"
24 #include "render/rs_image_cache.h"
25 #include "render/rs_pixel_map_util.h"
26 #include "rs_trace.h"
27 #include "sandbox_utils.h"
28 #include "rs_profiler.h"
29
30 #ifdef USE_VIDEO_PROCESSING_ENGINE
31 #include "render/rs_colorspace_convert.h"
32 #endif
33
34 namespace OHOS {
35 namespace Rosen {
36 namespace {
37 constexpr int32_t CORNER_SIZE = 4;
38 constexpr float CENTER_ALIGNED_FACTOR = 2.f;
39 }
40
~RSImage()41 RSImage::~RSImage()
42 {}
43
ReMapPixelMap(std::shared_ptr<Media::PixelMap> & pixelMap)44 inline void ReMapPixelMap(std::shared_ptr<Media::PixelMap>& pixelMap)
45 {
46 #ifdef ROSEN_OHOS
47 if (pixelMap && pixelMap->IsUnMap()) {
48 pixelMap->ReMap();
49 }
50 #endif
51 }
52
IsEqual(const RSImage & other) const53 bool RSImage::IsEqual(const RSImage& other) const
54 {
55 bool radiusEq = true;
56 for (auto i = 0; i < CORNER_SIZE; i++) {
57 radiusEq &= (radius_[i] == other.radius_[i]);
58 }
59 return (image_ == other.image_) && (pixelMap_ == other.pixelMap_) &&
60 (imageFit_ == other.imageFit_) && (imageRepeat_ == other.imageRepeat_) &&
61 (scale_ == other.scale_) && radiusEq && (compressData_ == other.compressData_);
62 }
63
HDRConvert(const Drawing::SamplingOptions & sampling,Drawing::Canvas & canvas)64 bool RSImage::HDRConvert(const Drawing::SamplingOptions& sampling, Drawing::Canvas& canvas)
65 {
66 #ifdef USE_VIDEO_PROCESSING_ENGINE
67 // HDR disable
68 if (!RSSystemProperties::GetHDRImageEnable()) {
69 return false;
70 }
71
72 if (pixelMap_ == nullptr || image_ == nullptr) {
73 RS_LOGE("bhdr pixelMap_ || image_ is nullptr");
74 return false;
75 }
76 if (!pixelMap_->IsHdr()) {
77 return false;
78 }
79
80 if (canvas.GetDrawingType() != Drawing::DrawingType::PAINT_FILTER) {
81 RS_LOGE("bhdr GetDrawingType() != Drawing::DrawingType::PAINT_FILTER");
82 return false;
83 }
84
85 SurfaceBuffer* surfaceBuffer = reinterpret_cast<SurfaceBuffer*>(pixelMap_->GetFd());
86
87 if (surfaceBuffer == nullptr) {
88 RS_LOGE("bhdr ColorSpaceConvertor surfaceBuffer is nullptr");
89 return false;
90 }
91
92 Drawing::Matrix matrix; //Identity Matrix
93 auto sx = dstRect_.GetWidth() / srcRect_.GetWidth();
94 auto sy = dstRect_.GetHeight() / srcRect_.GetHeight();
95 auto tx = dstRect_.GetLeft() - srcRect_.GetLeft() * sx;
96 auto ty = dstRect_.GetTop() - srcRect_.GetTop() * sy;
97 matrix.SetScaleTranslate(sx, sy, tx, ty);
98
99 auto imageShader = Drawing::ShaderEffect::CreateImageShader(
100 *image_, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, sampling, matrix);
101
102 sptr<SurfaceBuffer> sfBuffer(surfaceBuffer);
103 RSPaintFilterCanvas& rscanvas = static_cast<RSPaintFilterCanvas&>(canvas);
104 auto targetColorSpace = GRAPHIC_COLOR_GAMUT_SRGB;
105 if (LIKELY(!rscanvas.IsCapture())) {
106 RSColorSpaceConvert::Instance().ColorSpaceConvertor(imageShader, sfBuffer, paint_,
107 targetColorSpace, rscanvas.GetScreenId(), dynamicRangeMode_);
108 } else {
109 RSColorSpaceConvert::Instance().ColorSpaceConvertor(imageShader, sfBuffer, paint_,
110 targetColorSpace, rscanvas.GetScreenId(), DynamicRangeMode::STANDARD);
111 }
112 canvas.AttachPaint(paint_);
113 return true;
114 #else
115 return false;
116 #endif
117 }
118
CanvasDrawImage(Drawing::Canvas & canvas,const Drawing::Rect & rect,const Drawing::SamplingOptions & samplingOptions,bool isBackground)119 void RSImage::CanvasDrawImage(Drawing::Canvas& canvas, const Drawing::Rect& rect,
120 const Drawing::SamplingOptions& samplingOptions, bool isBackground)
121 {
122 if (canvas.GetRecordingState() && RSSystemProperties::GetDumpUICaptureEnabled() && pixelMap_) {
123 CommonTools::SavePixelmapToFile(pixelMap_, "/data/rsImage_");
124 }
125 if (!isDrawn_ || rect != lastRect_) {
126 UpdateNodeIdToPicture(nodeId_);
127 Drawing::AutoCanvasRestore acr(canvas, HasRadius());
128 if (!canvas.GetOffscreen()) {
129 frameRect_.SetAll(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
130 }
131 if (!isBackground) {
132 ApplyImageFit();
133 ApplyCanvasClip(canvas);
134 }
135 DrawImageRepeatRect(samplingOptions, canvas);
136 } else {
137 Drawing::AutoCanvasRestore acr(canvas, HasRadius());
138 if (pixelMap_ != nullptr && pixelMap_->IsAstc()) {
139 canvas.Save();
140 RSPixelMapUtil::TransformDataSetForAstc(pixelMap_, src_, dst_, canvas);
141 }
142 ReMapPixelMap(pixelMap_);
143 if (image_) {
144 if (!isBackground) {
145 ApplyCanvasClip(canvas);
146 }
147 if (innerRect_.has_value()) {
148 canvas.DrawImageNine(image_.get(), innerRect_.value(), dst_, Drawing::FilterMode::LINEAR);
149 } else if (HDRConvert(samplingOptions, canvas)) {
150 canvas.DrawRect(dst_);
151 } else {
152 canvas.DrawImageRect(*image_, src_, dst_, samplingOptions,
153 Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
154 }
155 }
156 if (pixelMap_ != nullptr && pixelMap_->IsAstc()) {
157 canvas.Restore();
158 }
159 }
160 lastRect_ = rect;
161 }
162
163 struct ImageParameter {
164 float ratio;
165 float srcW;
166 float srcH;
167 float frameW;
168 float frameH;
169 float dstW;
170 float dstH;
171 };
172
ApplyImageFitSwitch(ImageParameter & imageParameter,ImageFit imageFit_,RectF tempRectF)173 RectF ApplyImageFitSwitch(ImageParameter &imageParameter, ImageFit imageFit_, RectF tempRectF)
174 {
175 switch (imageFit_) {
176 case ImageFit::TOP_LEFT:
177 tempRectF.SetAll(0.f, 0.f, imageParameter.srcW, imageParameter.srcH);
178 return tempRectF;
179 case ImageFit::TOP:
180 tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR, 0.f,
181 imageParameter.srcW, imageParameter.srcH);
182 return tempRectF;
183 case ImageFit::TOP_RIGHT:
184 tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW, 0.f, imageParameter.srcW, imageParameter.srcH);
185 return tempRectF;
186 case ImageFit::LEFT:
187 tempRectF.SetAll(0.f, (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
188 imageParameter.srcW, imageParameter.srcH);
189 return tempRectF;
190 case ImageFit::CENTER:
191 tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR,
192 (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
193 imageParameter.srcW, imageParameter.srcH);
194 return tempRectF;
195 case ImageFit::RIGHT:
196 tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW,
197 (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
198 imageParameter.srcW, imageParameter.srcH);
199 return tempRectF;
200 case ImageFit::BOTTOM_LEFT:
201 tempRectF.SetAll(0.f, imageParameter.dstH - imageParameter.srcH, imageParameter.srcW, imageParameter.srcH);
202 return tempRectF;
203 case ImageFit::BOTTOM:
204 tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR,
205 imageParameter.dstH - imageParameter.srcH, imageParameter.srcW, imageParameter.srcH);
206 return tempRectF;
207 case ImageFit::BOTTOM_RIGHT:
208 tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW, imageParameter.dstH - imageParameter.srcH,
209 imageParameter.srcW, imageParameter.srcH);
210 return tempRectF;
211 case ImageFit::FILL:
212 break;
213 case ImageFit::NONE:
214 imageParameter.dstW = imageParameter.srcW;
215 imageParameter.dstH = imageParameter.srcH;
216 break;
217 case ImageFit::COVER:
218 imageParameter.dstW = std::max(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
219 imageParameter.dstH = std::max(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
220 break;
221 case ImageFit::FIT_WIDTH:
222 imageParameter.dstH = imageParameter.frameW / imageParameter.ratio;
223 break;
224 case ImageFit::FIT_HEIGHT:
225 imageParameter.dstW = imageParameter.frameH * imageParameter.ratio;
226 break;
227 case ImageFit::SCALE_DOWN:
228 if (imageParameter.srcW < imageParameter.frameW && imageParameter.srcH < imageParameter.frameH) {
229 imageParameter.dstW = imageParameter.srcW;
230 imageParameter.dstH = imageParameter.srcH;
231 } else {
232 imageParameter.dstW = std::min(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
233 imageParameter.dstH = std::min(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
234 }
235 break;
236 case ImageFit::COVER_TOP_LEFT:
237 imageParameter.dstW = std::max(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
238 imageParameter.dstH = std::max(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
239 tempRectF.SetAll(0, 0, std::ceil(imageParameter.dstW), std::ceil(imageParameter.dstH));
240 return tempRectF;
241 case ImageFit::CONTAIN:
242 default:
243 imageParameter.dstW = std::min(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
244 imageParameter.dstH = std::min(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
245 break;
246 }
247 constexpr float horizontalAlignmentFactor = 2.f;
248 constexpr float verticalAlignmentFactor = 2.f;
249 tempRectF.SetAll(std::floor((imageParameter.frameW - imageParameter.dstW) / horizontalAlignmentFactor),
250 std::floor((imageParameter.frameH - imageParameter.dstH) / verticalAlignmentFactor),
251 std::ceil(imageParameter.dstW),
252 std::ceil(imageParameter.dstH));
253 return tempRectF;
254 }
255
ApplyImageFit()256 void RSImage::ApplyImageFit()
257 {
258 if (scale_ == 0) {
259 RS_LOGE("RSImage::ApplyImageFit failed, scale_ is zero ");
260 return;
261 }
262 const float srcW = srcRect_.width_ / scale_;
263 const float srcH = srcRect_.height_ / scale_;
264 const float frameW = frameRect_.width_;
265 const float frameH = frameRect_.height_;
266 float dstW = frameW;
267 float dstH = frameH;
268 if (srcH == 0) {
269 RS_LOGE("RSImage::ApplyImageFit failed, srcH is zero ");
270 return;
271 }
272 float ratio = srcW / srcH;
273 if (ratio == 0) {
274 RS_LOGE("RSImage::ApplyImageFit failed, ratio is zero ");
275 return;
276 }
277 ImageParameter imageParameter;
278 imageParameter.ratio = ratio;
279 imageParameter.srcW = srcW;
280 imageParameter.srcH = srcH;
281 imageParameter.frameW = frameW;
282 imageParameter.frameH = frameH;
283 imageParameter.dstW = dstW;
284 imageParameter.dstH = dstH;
285 RectF tempRectF = dstRect_;
286 dstRect_ = ApplyImageFitSwitch(imageParameter, imageFit_, tempRectF);
287 }
288
GetImageFit()289 ImageFit RSImage::GetImageFit()
290 {
291 return imageFit_;
292 }
293
GetAdaptiveImageInfoWithCustomizedFrameRect(const Drawing::Rect & frameRect) const294 Drawing::AdaptiveImageInfo RSImage::GetAdaptiveImageInfoWithCustomizedFrameRect(const Drawing::Rect& frameRect) const
295 {
296 Drawing::AdaptiveImageInfo imageInfo = {
297 .fitNum = static_cast<int32_t>(imageFit_),
298 .repeatNum = static_cast<int32_t>(imageRepeat_),
299 .radius = { radius_[0], radius_[1], radius_[2], radius_[3] },
300 .scale = scale_,
301 .uniqueId = 0,
302 .width = 0,
303 .height = 0,
304 .dynamicRangeMode = dynamicRangeMode_,
305 .frameRect = frameRect
306 };
307 return imageInfo;
308 }
309
GetDstRect()310 RectF RSImage::GetDstRect()
311 {
312 return dstRect_;
313 }
314
SetFrameRect(RectF frameRect)315 void RSImage::SetFrameRect(RectF frameRect)
316 {
317 frameRect_ = frameRect;
318 }
319
HasRadius() const320 bool RSImage::HasRadius() const
321 {
322 return hasRadius_;
323 }
324
ApplyCanvasClip(Drawing::Canvas & canvas)325 void RSImage::ApplyCanvasClip(Drawing::Canvas& canvas)
326 {
327 if (!HasRadius()) {
328 return;
329 }
330 auto rect = (imageRepeat_ == ImageRepeat::NO_REPEAT) ? dstRect_.IntersectRect(frameRect_) : frameRect_;
331 Drawing::RoundRect rrect(RSPropertiesPainter::Rect2DrawingRect(rect), radius_);
332 canvas.ClipRoundRect(rrect, Drawing::ClipOp::INTERSECT, true);
333 }
334
335 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
PixelFormatToCompressedType(Media::PixelFormat pixelFormat)336 static Drawing::CompressedType PixelFormatToCompressedType(Media::PixelFormat pixelFormat)
337 {
338 switch (pixelFormat) {
339 case Media::PixelFormat::ASTC_4x4: return Drawing::CompressedType::ASTC_RGBA8_4x4;
340 case Media::PixelFormat::ASTC_6x6: return Drawing::CompressedType::ASTC_RGBA8_6x6;
341 case Media::PixelFormat::ASTC_8x8: return Drawing::CompressedType::ASTC_RGBA8_8x8;
342 case Media::PixelFormat::UNKNOWN:
343 default: return Drawing::CompressedType::NoneType;
344 }
345 }
346
ColorSpaceToDrawingColorSpace(ColorManager::ColorSpaceName colorSpaceName)347 static std::shared_ptr<Drawing::ColorSpace> ColorSpaceToDrawingColorSpace(ColorManager::ColorSpaceName
348 colorSpaceName)
349 {
350 switch (colorSpaceName) {
351 case ColorManager::ColorSpaceName::DISPLAY_P3:
352 return Drawing::ColorSpace::CreateRGB(
353 Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::DCIP3);
354 case ColorManager::ColorSpaceName::LINEAR_SRGB:
355 return Drawing::ColorSpace::CreateSRGBLinear();
356 case ColorManager::ColorSpaceName::SRGB:
357 return Drawing::ColorSpace::CreateSRGB();
358 default:
359 return Drawing::ColorSpace::CreateSRGB();
360 }
361 }
362 #endif
363
UploadGpu(Drawing::Canvas & canvas)364 void RSImage::UploadGpu(Drawing::Canvas& canvas)
365 {
366 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
367 if (compressData_) {
368 auto cache = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_, gettid());
369 std::lock_guard<std::mutex> lock(mutex_);
370 if (cache) {
371 image_ = cache;
372 } else {
373 if (canvas.GetGPUContext() == nullptr) {
374 return;
375 }
376 Media::ImageInfo imageInfo;
377 pixelMap_->GetImageInfo(imageInfo);
378 Media::Size realSize;
379 pixelMap_->GetAstcRealSize(realSize);
380 auto image = std::make_shared<Drawing::Image>();
381 std::shared_ptr<Drawing::ColorSpace> colorSpace =
382 ColorSpaceToDrawingColorSpace(pixelMap_->InnerGetGrColorSpace().GetColorSpaceName());
383 bool result = image->BuildFromCompressed(*canvas.GetGPUContext(), compressData_,
384 static_cast<int>(realSize.width), static_cast<int>(realSize.height),
385 PixelFormatToCompressedType(imageInfo.pixelFormat), colorSpace);
386 if (result) {
387 image_ = image;
388 SKResourceManager::Instance().HoldResource(image);
389 RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image, gettid());
390 } else {
391 RS_LOGE("make astc image %{public}d (%{public}d, %{public}d) failed",
392 (int)uniqueId_, (int)srcRect_.width_, (int)srcRect_.height_);
393 }
394 compressData_ = nullptr;
395 }
396 return;
397 }
398 if (isYUVImage_) {
399 ProcessYUVImage(canvas.GetGPUContext());
400 }
401 #endif
402 }
403
DrawImageRepeatRect(const Drawing::SamplingOptions & samplingOptions,Drawing::Canvas & canvas)404 void RSImage::DrawImageRepeatRect(const Drawing::SamplingOptions& samplingOptions, Drawing::Canvas& canvas)
405 {
406 ReMapPixelMap(pixelMap_);
407 int minX = 0;
408 int minY = 0;
409 int maxX = 0;
410 int maxY = 0;
411 CalcRepeatBounds(minX, maxX, minY, maxY);
412 // draw repeat rect
413 ConvertPixelMapToDrawingImage();
414 UploadGpu(canvas);
415 bool hdrImageDraw = HDRConvert(samplingOptions, canvas);
416 src_ = RSPropertiesPainter::Rect2DrawingRect(srcRect_);
417 bool isAstc = pixelMap_ != nullptr && pixelMap_->IsAstc();
418 for (int i = minX; i <= maxX; ++i) {
419 auto left = dstRect_.left_ + i * dstRect_.width_;
420 auto right = left + dstRect_.width_;
421 for (int j = minY; j <= maxY; ++j) {
422 auto top = dstRect_.top_ + j * dstRect_.height_;
423 dst_ = Drawing::Rect(left, top, right, top + dstRect_.height_);
424 if (isAstc) {
425 canvas.Save();
426 RSPixelMapUtil::TransformDataSetForAstc(pixelMap_, src_, dst_, canvas);
427 }
428 if (image_) {
429 DrawImageOnCanvas(samplingOptions, canvas, hdrImageDraw);
430 }
431 if (isAstc) {
432 canvas.Restore();
433 }
434 }
435 }
436 if (imageRepeat_ == ImageRepeat::NO_REPEAT) {
437 isDrawn_ = true;
438 }
439 }
440
CalcRepeatBounds(int & minX,int & maxX,int & minY,int & maxY)441 void RSImage::CalcRepeatBounds(int& minX, int& maxX, int& minY, int& maxY)
442 {
443 float left = frameRect_.left_;
444 float right = frameRect_.GetRight();
445 float top = frameRect_.top_;
446 float bottom = frameRect_.GetBottom();
447 // calculate REPEAT_XY
448 float eps = 0.01; // set epsilon
449 if (ImageRepeat::REPEAT_X == imageRepeat_ || ImageRepeat::REPEAT == imageRepeat_) {
450 while (dstRect_.left_ + minX * dstRect_.width_ > left + eps) {
451 --minX;
452 }
453 while (dstRect_.left_ + maxX * dstRect_.width_ < right - eps) {
454 ++maxX;
455 }
456 }
457 if (ImageRepeat::REPEAT_Y == imageRepeat_ || ImageRepeat::REPEAT == imageRepeat_) {
458 while (dstRect_.top_ + minY * dstRect_.height_ > top + eps) {
459 --minY;
460 }
461 while (dstRect_.top_ + maxY * dstRect_.height_ < bottom - eps) {
462 ++maxY;
463 }
464 }
465 }
466
DrawImageOnCanvas(const Drawing::SamplingOptions & samplingOptions,Drawing::Canvas & canvas,const bool hdrImageDraw)467 void RSImage::DrawImageOnCanvas(
468 const Drawing::SamplingOptions& samplingOptions, Drawing::Canvas& canvas, const bool hdrImageDraw)
469 {
470 if (canvas.GetTotalMatrix().HasPerspective()) {
471 // In case of perspective transformation, make dstRect 1px outset to anti-alias
472 dst_.MakeOutset(1, 1);
473 }
474 if (innerRect_.has_value()) {
475 canvas.DrawImageNine(image_.get(), innerRect_.value(), dst_, Drawing::FilterMode::LINEAR);
476 } else if (hdrImageDraw) {
477 canvas.DrawRect(dst_);
478 } else {
479 canvas.DrawImageRect(
480 *image_, src_, dst_, samplingOptions, Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
481 }
482 }
483
SetCompressData(const std::shared_ptr<Drawing::Data> data,const uint32_t id,const int width,const int height)484 void RSImage::SetCompressData(
485 const std::shared_ptr<Drawing::Data> data, const uint32_t id, const int width, const int height)
486 {
487 #ifdef RS_ENABLE_GL
488 if (RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL) {
489 return;
490 }
491 compressData_ = data;
492 if (compressData_) {
493 srcRect_.SetAll(0.0, 0.0, width, height);
494 GenUniqueId(image_ ? image_->GetUniqueID() : id);
495 image_ = nullptr;
496 }
497 #endif
498 }
499
500 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined (RS_ENABLE_VK))
SetCompressData(const std::shared_ptr<Drawing::Data> compressData)501 void RSImage::SetCompressData(const std::shared_ptr<Drawing::Data> compressData)
502 {
503 isDrawn_ = false;
504 compressData_ = compressData;
505 canPurgeShareMemFlag_ = CanPurgeFlag::DISABLED;
506 }
507 #endif
508
SetImageFit(int fitNum)509 void RSImage::SetImageFit(int fitNum)
510 {
511 imageFit_ = static_cast<ImageFit>(fitNum);
512 }
513
SetImageRepeat(int repeatNum)514 void RSImage::SetImageRepeat(int repeatNum)
515 {
516 imageRepeat_ = static_cast<ImageRepeat>(repeatNum);
517 }
518
SetRadius(const std::vector<Drawing::Point> & radius)519 void RSImage::SetRadius(const std::vector<Drawing::Point>& radius)
520 {
521 hasRadius_ = false;
522 for (auto i = 0; i < CORNER_SIZE; i++) {
523 radius_[i] = radius[i];
524 hasRadius_ = hasRadius_ || !radius_[i].IsZero();
525 }
526 }
527
SetScale(double scale)528 void RSImage::SetScale(double scale)
529 {
530 if (scale > 0.0) {
531 scale_ = scale;
532 }
533 }
534
SetNodeId(NodeId nodeId)535 void RSImage::SetNodeId(NodeId nodeId)
536 {
537 nodeId_ = nodeId;
538 }
539
SetPaint(Drawing::Paint paint)540 void RSImage::SetPaint(Drawing::Paint paint)
541 {
542 paint_ = paint;
543 }
544
SetDyamicRangeMode(uint32_t dynamicRangeMode)545 void RSImage::SetDyamicRangeMode(uint32_t dynamicRangeMode)
546 {
547 dynamicRangeMode_ = dynamicRangeMode;
548 }
549
550 #ifdef ROSEN_OHOS
UnmarshallingIdAndSize(Parcel & parcel,uint64_t & uniqueId,int & width,int & height)551 static bool UnmarshallingIdAndSize(Parcel& parcel, uint64_t& uniqueId, int& width, int& height)
552 {
553 if (!RSMarshallingHelper::Unmarshalling(parcel, uniqueId)) {
554 RS_LOGE("RSImage::Unmarshalling uniqueId fail");
555 return false;
556 }
557 RS_PROFILER_PATCH_NODE_ID(parcel, uniqueId);
558 if (!RSMarshallingHelper::Unmarshalling(parcel, width)) {
559 RS_LOGE("RSImage::Unmarshalling width fail");
560 return false;
561 }
562 if (!RSMarshallingHelper::Unmarshalling(parcel, height)) {
563 RS_LOGE("RSImage::Unmarshalling height fail");
564 return false;
565 }
566 return true;
567 }
568
UnmarshallingCompressData(Parcel & parcel,bool skipData,std::shared_ptr<Drawing::Data> & compressData)569 static bool UnmarshallingCompressData(Parcel& parcel, bool skipData, std::shared_ptr<Drawing::Data>& compressData)
570 {
571 if (skipData) {
572 if (!RSMarshallingHelper::SkipData(parcel)) {
573 RS_LOGE("RSImage::Unmarshalling SkipData fail");
574 return false;
575 }
576 } else {
577 if (!RSMarshallingHelper::UnmarshallingWithCopy(parcel, compressData)) {
578 RS_LOGE("RSImage::Unmarshalling UnmarshallingWithCopy Data fail");
579 return false;
580 }
581 }
582 return true;
583 }
584
Marshalling(Parcel & parcel) const585 bool RSImage::Marshalling(Parcel& parcel) const
586 {
587 int imageFit = static_cast<int>(imageFit_);
588 int imageRepeat = static_cast<int>(imageRepeat_);
589
590 std::lock_guard<std::mutex> lock(mutex_);
591 auto image = image_;
592 auto compressData = compressData_;
593 if (image && image->IsTextureBacked()) {
594 image = nullptr;
595 ROSEN_LOGE("RSImage::Marshalling skip texture image");
596 }
597 RS_PROFILER_MARSHAL_DRAWINGIMAGE(image, compressData);
598 bool success = RSMarshallingHelper::Marshalling(parcel, uniqueId_) &&
599 RSMarshallingHelper::Marshalling(parcel, static_cast<int>(srcRect_.width_)) &&
600 RSMarshallingHelper::Marshalling(parcel, static_cast<int>(srcRect_.height_)) &&
601 RSMarshallingHelper::Marshalling(parcel, nodeId_) &&
602 parcel.WriteBool(pixelMap_ == nullptr) &&
603 RSMarshallingHelper::Marshalling(parcel, image) &&
604 RSMarshallingHelper::Marshalling(parcel, pixelMap_) &&
605 RSMarshallingHelper::Marshalling(parcel, compressData) &&
606 RSMarshallingHelper::Marshalling(parcel, imageFit) &&
607 RSMarshallingHelper::Marshalling(parcel, imageRepeat) &&
608 RSMarshallingHelper::Marshalling(parcel, radius_) &&
609 RSMarshallingHelper::Marshalling(parcel, scale_);
610 return success;
611 }
612
Unmarshalling(Parcel & parcel)613 RSImage* RSImage::Unmarshalling(Parcel& parcel)
614 {
615 uint64_t uniqueId;
616 int width;
617 int height;
618 NodeId nodeId;
619 if (!UnmarshalIdSizeAndNodeId(parcel, uniqueId, width, height, nodeId)) {
620 return nullptr;
621 }
622 bool useSkImage;
623 std::shared_ptr<Drawing::Image> img;
624 std::shared_ptr<Media::PixelMap> pixelMap;
625 void* imagepixelAddr = nullptr;
626 if (!UnmarshallingDrawingImageAndPixelMap(parcel, uniqueId, useSkImage, img, pixelMap, imagepixelAddr)) {
627 return nullptr;
628 }
629 std::shared_ptr<Drawing::Data> compressData;
630 bool skipData = img != nullptr || !useSkImage;
631 if (!UnmarshallingCompressData(parcel, skipData, compressData)) {
632 return nullptr;
633 }
634 int fitNum;
635 int repeatNum;
636 std::vector<Drawing::Point> radius(CORNER_SIZE);
637 double scale;
638 if (!UnmarshalImageProperties(parcel, fitNum, repeatNum, radius, scale)) {
639 return nullptr;
640 }
641 RSImage* rsImage = new RSImage();
642 rsImage->SetImage(img);
643 rsImage->SetImagePixelAddr(imagepixelAddr);
644 rsImage->SetCompressData(compressData, uniqueId, width, height);
645 rsImage->SetPixelMap(pixelMap);
646 rsImage->SetImageFit(fitNum);
647 rsImage->SetImageRepeat(repeatNum);
648 rsImage->SetRadius(radius);
649 rsImage->SetScale(scale);
650 rsImage->SetNodeId(nodeId);
651 ProcessImageAfterCreation(rsImage, uniqueId, useSkImage, pixelMap);
652 return rsImage;
653 }
654
UnmarshalIdSizeAndNodeId(Parcel & parcel,uint64_t & uniqueId,int & width,int & height,NodeId & nodeId)655 bool RSImage::UnmarshalIdSizeAndNodeId(Parcel& parcel, uint64_t& uniqueId, int& width, int& height, NodeId& nodeId)
656 {
657 if (!UnmarshallingIdAndSize(parcel, uniqueId, width, height)) {
658 RS_LOGE("RSImage::Unmarshalling UnmarshallingIdAndSize fail");
659 return false;
660 }
661 if (!RSMarshallingHelper::Unmarshalling(parcel, nodeId)) {
662 RS_LOGE("RSImage::Unmarshalling nodeId fail");
663 return false;
664 }
665 RS_PROFILER_PATCH_NODE_ID(parcel, nodeId);
666 return true;
667 }
668
UnmarshalImageProperties(Parcel & parcel,int & fitNum,int & repeatNum,std::vector<Drawing::Point> & radius,double & scale)669 bool RSImage::UnmarshalImageProperties(
670 Parcel& parcel, int& fitNum, int& repeatNum, std::vector<Drawing::Point>& radius, double& scale)
671 {
672 if (!RSMarshallingHelper::Unmarshalling(parcel, fitNum)) {
673 RS_LOGE("RSImage::Unmarshalling fitNum fail");
674 return false;
675 }
676
677 if (!RSMarshallingHelper::Unmarshalling(parcel, repeatNum)) {
678 RS_LOGE("RSImage::Unmarshalling repeatNum fail");
679 return false;
680 }
681
682 if (!RSMarshallingHelper::Unmarshalling(parcel, radius)) {
683 RS_LOGE("RSImage::Unmarshalling radius fail");
684 return false;
685 }
686
687 if (!RSMarshallingHelper::Unmarshalling(parcel, scale)) {
688 RS_LOGE("RSImage::Unmarshalling scale fail");
689 return false;
690 }
691
692 return true;
693 }
694
ProcessImageAfterCreation(RSImage * rsImage,const uint64_t uniqueId,const bool useSkImage,const std::shared_ptr<Media::PixelMap> & pixelMap)695 void RSImage::ProcessImageAfterCreation(
696 RSImage* rsImage, const uint64_t uniqueId, const bool useSkImage, const std::shared_ptr<Media::PixelMap>& pixelMap)
697 {
698 rsImage->uniqueId_ = uniqueId;
699 rsImage->MarkRenderServiceImage();
700 RSImageBase::IncreaseCacheRefCount(uniqueId, useSkImage, pixelMap);
701 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_GL) && defined(RS_ENABLE_PARALLEL_UPLOAD)
702 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
703 #if defined(RS_ENABLE_UNI_RENDER)
704 if (pixelMap != nullptr && pixelMap->GetAllocatorType() != Media::AllocatorType::DMA_ALLOC) {
705 rsImage->ConvertPixelMapToDrawingImage(true);
706 }
707 #endif
708 }
709 #endif
710 }
711 #endif
712 } // namespace Rosen
713 } // namespace OHOS
714