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