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