• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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