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 if (!isDrawn_ || rect != lastRect_) {
131 UpdateNodeIdToPicture(nodeId_);
132 Drawing::AutoCanvasRestore acr(canvas, HasRadius());
133 if (!canvas.GetOffscreen()) {
134 frameRect_.SetAll(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
135 }
136 if (!isBackground) {
137 ApplyImageFit();
138 ApplyCanvasClip(canvas);
139 }
140 if (rotateDegree_ != 0) {
141 canvas.Save();
142 canvas.Rotate(rotateDegree_);
143 auto axis = CalculateByDegree(rect);
144 canvas.Translate(axis.first, axis.second);
145 DrawImageRepeatRect(samplingOptions, canvas);
146 canvas.Restore();
147 } else {
148 DrawImageRepeatRect(samplingOptions, canvas);
149 }
150 } else {
151 Drawing::AutoCanvasRestore acr(canvas, HasRadius());
152 if (pixelMap_ != nullptr && pixelMap_->IsAstc()) {
153 canvas.Save();
154 RSPixelMapUtil::TransformDataSetForAstc(pixelMap_, src_, dst_, canvas);
155 }
156 ReMapPixelMap(pixelMap_);
157 if (image_) {
158 if (!isBackground) {
159 ApplyCanvasClip(canvas);
160 }
161 if (innerRect_.has_value()) {
162 canvas.DrawImageNine(image_.get(), innerRect_.value(), dst_, Drawing::FilterMode::LINEAR);
163 } else if (HDRConvert(samplingOptions, canvas)) {
164 canvas.DrawRect(dst_);
165 } else {
166 DrawImageWithRotateDegree(canvas, rect, samplingOptions);
167 }
168 }
169 if (pixelMap_ != nullptr && pixelMap_->IsAstc()) {
170 canvas.Restore();
171 }
172 }
173 lastRect_ = rect;
174 }
175
DrawImageWithRotateDegree(Drawing::Canvas & canvas,const Drawing::Rect & rect,const Drawing::SamplingOptions & samplingOptions)176 void RSImage::DrawImageWithRotateDegree(
177 Drawing::Canvas& canvas, const Drawing::Rect& rect, const Drawing::SamplingOptions& samplingOptions)
178 {
179 Drawing::AutoCanvasRestore acr(canvas, true);
180 if (rotateDegree_ != 0) {
181 canvas.Rotate(rotateDegree_);
182 auto axis = CalculateByDegree(rect);
183 canvas.Translate(axis.first, axis.second);
184 }
185 canvas.DrawImageRect(*image_, src_, dst_, samplingOptions, Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
186 }
187
188 struct ImageParameter {
189 float ratio;
190 float srcW;
191 float srcH;
192 float frameW;
193 float frameH;
194 float dstW;
195 float dstH;
196 };
197
ApplyImageFitSwitch(ImageParameter & imageParameter,ImageFit imageFit_,RectF tempRectF)198 RectF ApplyImageFitSwitch(ImageParameter &imageParameter, ImageFit imageFit_, RectF tempRectF)
199 {
200 switch (imageFit_) {
201 case ImageFit::TOP_LEFT:
202 tempRectF.SetAll(0.f, 0.f, imageParameter.srcW, imageParameter.srcH);
203 return tempRectF;
204 case ImageFit::TOP:
205 tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR, 0.f,
206 imageParameter.srcW, imageParameter.srcH);
207 return tempRectF;
208 case ImageFit::TOP_RIGHT:
209 tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW, 0.f, imageParameter.srcW, imageParameter.srcH);
210 return tempRectF;
211 case ImageFit::LEFT:
212 tempRectF.SetAll(0.f, (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
213 imageParameter.srcW, imageParameter.srcH);
214 return tempRectF;
215 case ImageFit::CENTER:
216 tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR,
217 (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
218 imageParameter.srcW, imageParameter.srcH);
219 return tempRectF;
220 case ImageFit::RIGHT:
221 tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW,
222 (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
223 imageParameter.srcW, imageParameter.srcH);
224 return tempRectF;
225 case ImageFit::BOTTOM_LEFT:
226 tempRectF.SetAll(0.f, imageParameter.dstH - imageParameter.srcH, imageParameter.srcW, imageParameter.srcH);
227 return tempRectF;
228 case ImageFit::BOTTOM:
229 tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR,
230 imageParameter.dstH - imageParameter.srcH, imageParameter.srcW, imageParameter.srcH);
231 return tempRectF;
232 case ImageFit::BOTTOM_RIGHT:
233 tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW, imageParameter.dstH - imageParameter.srcH,
234 imageParameter.srcW, imageParameter.srcH);
235 return tempRectF;
236 case ImageFit::FILL:
237 break;
238 case ImageFit::NONE:
239 imageParameter.dstW = imageParameter.srcW;
240 imageParameter.dstH = imageParameter.srcH;
241 break;
242 case ImageFit::COVER:
243 imageParameter.dstW = std::max(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
244 imageParameter.dstH = std::max(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
245 break;
246 case ImageFit::FIT_WIDTH:
247 imageParameter.dstH = imageParameter.frameW / imageParameter.ratio;
248 break;
249 case ImageFit::FIT_HEIGHT:
250 imageParameter.dstW = imageParameter.frameH * imageParameter.ratio;
251 break;
252 case ImageFit::SCALE_DOWN:
253 if (imageParameter.srcW < imageParameter.frameW && imageParameter.srcH < imageParameter.frameH) {
254 imageParameter.dstW = imageParameter.srcW;
255 imageParameter.dstH = imageParameter.srcH;
256 } else {
257 imageParameter.dstW = std::min(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
258 imageParameter.dstH = std::min(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
259 }
260 break;
261 case ImageFit::COVER_TOP_LEFT:
262 imageParameter.dstW = std::max(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
263 imageParameter.dstH = std::max(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
264 tempRectF.SetAll(0, 0, std::ceil(imageParameter.dstW), std::ceil(imageParameter.dstH));
265 return tempRectF;
266 case ImageFit::CONTAIN:
267 default:
268 imageParameter.dstW = std::min(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
269 imageParameter.dstH = std::min(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
270 break;
271 }
272 constexpr float horizontalAlignmentFactor = 2.f;
273 constexpr float verticalAlignmentFactor = 2.f;
274 tempRectF.SetAll(std::floor((imageParameter.frameW - imageParameter.dstW) / horizontalAlignmentFactor),
275 std::floor((imageParameter.frameH - imageParameter.dstH) / verticalAlignmentFactor),
276 std::ceil(imageParameter.dstW),
277 std::ceil(imageParameter.dstH));
278 return tempRectF;
279 }
280
ApplyImageFit()281 void RSImage::ApplyImageFit()
282 {
283 if (scale_ == 0) {
284 RS_LOGE("RSImage::ApplyImageFit failed, scale_ is zero ");
285 return;
286 }
287 const float srcW = srcRect_.width_ / scale_;
288 const float srcH = srcRect_.height_ / scale_;
289 float frameW = frameRect_.width_;
290 float frameH = frameRect_.height_;
291 if (rotateDegree_ == DEGREE_NINETY || rotateDegree_ == -DEGREE_NINETY) {
292 std::swap(frameW, frameH);
293 }
294 float dstW = frameW;
295 float dstH = frameH;
296 if (srcH == 0) {
297 RS_LOGE("RSImage::ApplyImageFit failed, srcH is zero ");
298 return;
299 }
300 float ratio = srcW / srcH;
301 if (ratio == 0) {
302 RS_LOGE("RSImage::ApplyImageFit failed, ratio is zero ");
303 return;
304 }
305 ImageParameter imageParameter;
306 imageParameter.ratio = ratio;
307 imageParameter.srcW = srcW;
308 imageParameter.srcH = srcH;
309 imageParameter.frameW = frameW;
310 imageParameter.frameH = frameH;
311 imageParameter.dstW = dstW;
312 imageParameter.dstH = dstH;
313 RectF tempRectF = dstRect_;
314 dstRect_ = ApplyImageFitSwitch(imageParameter, imageFit_, tempRectF);
315 }
316
SetImageRotateDegree(int32_t degree)317 void RSImage::SetImageRotateDegree(int32_t degree)
318 {
319 rotateDegree_ = degree;
320 }
321
CalculateByDegree(const Drawing::Rect & rect)322 std::pair<float, float> RSImage::CalculateByDegree(const Drawing::Rect& rect)
323 {
324 if (rotateDegree_ == DEGREE_NINETY) {
325 return { 0, -rect.GetWidth() };
326 } else if (rotateDegree_ == -DEGREE_NINETY) {
327 return { -rect.GetHeight(), 0 };
328 } else {
329 return { -rect.GetWidth(), -rect.GetHeight() };
330 }
331 }
332
GetImageFit()333 ImageFit RSImage::GetImageFit()
334 {
335 return imageFit_;
336 }
337
GetAdaptiveImageInfoWithCustomizedFrameRect(const Drawing::Rect & frameRect) const338 Drawing::AdaptiveImageInfo RSImage::GetAdaptiveImageInfoWithCustomizedFrameRect(const Drawing::Rect& frameRect) const
339 {
340 Drawing::AdaptiveImageInfo imageInfo = {
341 .fitNum = static_cast<int32_t>(imageFit_),
342 .repeatNum = static_cast<int32_t>(imageRepeat_),
343 .radius = { radius_[0], radius_[1], radius_[2], radius_[3] },
344 .scale = scale_,
345 .uniqueId = 0,
346 .width = 0,
347 .height = 0,
348 .dynamicRangeMode = dynamicRangeMode_,
349 .rotateDegree = rotateDegree_,
350 .frameRect = frameRect,
351 };
352 return imageInfo;
353 }
354
GetDstRect()355 RectF RSImage::GetDstRect()
356 {
357 return dstRect_;
358 }
359
SetFrameRect(RectF frameRect)360 void RSImage::SetFrameRect(RectF frameRect)
361 {
362 frameRect_ = frameRect;
363 }
364
HasRadius() const365 bool RSImage::HasRadius() const
366 {
367 return hasRadius_;
368 }
369
ApplyCanvasClip(Drawing::Canvas & canvas)370 void RSImage::ApplyCanvasClip(Drawing::Canvas& canvas)
371 {
372 if (!HasRadius()) {
373 return;
374 }
375 auto dstRect = dstRect_;
376 if (rotateDegree_ == DEGREE_NINETY || rotateDegree_ == -DEGREE_NINETY) {
377 dstRect = RectF(dstRect_.GetTop(), dstRect_.GetLeft(), dstRect_.GetHeight(), dstRect_.GetWidth());
378 }
379 auto rect = (imageRepeat_ == ImageRepeat::NO_REPEAT) ? dstRect.IntersectRect(frameRect_) : frameRect_;
380 Drawing::RoundRect rrect(RSPropertiesPainter::Rect2DrawingRect(rect), radius_);
381 canvas.ClipRoundRect(rrect, Drawing::ClipOp::INTERSECT, true);
382 }
383
384 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
PixelFormatToCompressedType(Media::PixelFormat pixelFormat)385 static Drawing::CompressedType PixelFormatToCompressedType(Media::PixelFormat pixelFormat)
386 {
387 switch (pixelFormat) {
388 case Media::PixelFormat::ASTC_4x4: return Drawing::CompressedType::ASTC_RGBA8_4x4;
389 case Media::PixelFormat::ASTC_6x6: return Drawing::CompressedType::ASTC_RGBA8_6x6;
390 case Media::PixelFormat::ASTC_8x8: return Drawing::CompressedType::ASTC_RGBA8_8x8;
391 case Media::PixelFormat::UNKNOWN:
392 default: return Drawing::CompressedType::NoneType;
393 }
394 }
395
ColorSpaceToDrawingColorSpace(ColorManager::ColorSpaceName colorSpaceName)396 static std::shared_ptr<Drawing::ColorSpace> ColorSpaceToDrawingColorSpace(ColorManager::ColorSpaceName
397 colorSpaceName)
398 {
399 switch (colorSpaceName) {
400 case ColorManager::ColorSpaceName::DISPLAY_P3:
401 return Drawing::ColorSpace::CreateRGB(
402 Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::DCIP3);
403 case ColorManager::ColorSpaceName::LINEAR_SRGB:
404 return Drawing::ColorSpace::CreateSRGBLinear();
405 case ColorManager::ColorSpaceName::SRGB:
406 return Drawing::ColorSpace::CreateSRGB();
407 default:
408 return Drawing::ColorSpace::CreateSRGB();
409 }
410 }
411 #endif
412
UploadGpu(Drawing::Canvas & canvas)413 void RSImage::UploadGpu(Drawing::Canvas& canvas)
414 {
415 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
416 if (compressData_) {
417 auto cache = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_, gettid());
418 std::lock_guard<std::mutex> lock(mutex_);
419 if (cache) {
420 image_ = cache;
421 } else {
422 if (canvas.GetGPUContext() == nullptr) {
423 return;
424 }
425 RS_TRACE_NAME("make compress img");
426 Media::ImageInfo imageInfo;
427 pixelMap_->GetImageInfo(imageInfo);
428 Media::Size realSize;
429 pixelMap_->GetAstcRealSize(realSize);
430 auto image = std::make_shared<Drawing::Image>();
431 std::shared_ptr<Drawing::ColorSpace> colorSpace =
432 ColorSpaceToDrawingColorSpace(pixelMap_->InnerGetGrColorSpace().GetColorSpaceName());
433 bool result = image->BuildFromCompressed(*canvas.GetGPUContext(), compressData_,
434 static_cast<int>(realSize.width), static_cast<int>(realSize.height),
435 PixelFormatToCompressedType(imageInfo.pixelFormat), colorSpace);
436 if (result) {
437 image_ = image;
438 SKResourceManager::Instance().HoldResource(image);
439 RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image, gettid());
440 } else {
441 RS_LOGE("make astc image %{public}d (%{public}d, %{public}d) failed",
442 (int)uniqueId_, (int)srcRect_.width_, (int)srcRect_.height_);
443 }
444 compressData_ = nullptr;
445 }
446 return;
447 }
448 if (isYUVImage_) {
449 ProcessYUVImage(canvas.GetGPUContext());
450 }
451 #endif
452 }
453
DrawImageRepeatRect(const Drawing::SamplingOptions & samplingOptions,Drawing::Canvas & canvas)454 void RSImage::DrawImageRepeatRect(const Drawing::SamplingOptions& samplingOptions, Drawing::Canvas& canvas)
455 {
456 ReMapPixelMap(pixelMap_);
457 int minX = 0;
458 int minY = 0;
459 int maxX = 0;
460 int maxY = 0;
461 CalcRepeatBounds(minX, maxX, minY, maxY);
462 // draw repeat rect
463 ConvertPixelMapToDrawingImage();
464 UploadGpu(canvas);
465 bool hdrImageDraw = HDRConvert(samplingOptions, canvas);
466 src_ = RSPropertiesPainter::Rect2DrawingRect(srcRect_);
467 bool isAstc = pixelMap_ != nullptr && pixelMap_->IsAstc();
468 for (int i = minX; i <= maxX; ++i) {
469 auto left = dstRect_.left_ + i * dstRect_.width_;
470 auto right = left + dstRect_.width_;
471 for (int j = minY; j <= maxY; ++j) {
472 auto top = dstRect_.top_ + j * dstRect_.height_;
473 dst_ = Drawing::Rect(left, top, right, top + dstRect_.height_);
474 if (isAstc) {
475 canvas.Save();
476 RSPixelMapUtil::TransformDataSetForAstc(pixelMap_, src_, dst_, canvas);
477 }
478 if (image_) {
479 DrawImageOnCanvas(samplingOptions, canvas, hdrImageDraw);
480 }
481 if (isAstc) {
482 canvas.Restore();
483 }
484 }
485 }
486 if (imageRepeat_ == ImageRepeat::NO_REPEAT) {
487 isDrawn_ = true;
488 }
489 }
490
CalcRepeatBounds(int & minX,int & maxX,int & minY,int & maxY)491 void RSImage::CalcRepeatBounds(int& minX, int& maxX, int& minY, int& maxY)
492 {
493 float left = frameRect_.left_;
494 float right = frameRect_.GetRight();
495 float top = frameRect_.top_;
496 float bottom = frameRect_.GetBottom();
497 // calculate REPEAT_XY
498 float eps = 0.01; // set epsilon
499 auto repeat_x = ImageRepeat::REPEAT_X;
500 auto repeat_y = ImageRepeat::REPEAT_Y;
501 if (rotateDegree_ == DEGREE_NINETY || rotateDegree_ == -DEGREE_NINETY) {
502 std::swap(right, bottom);
503 std::swap(repeat_x, repeat_y);
504 }
505 if (repeat_x == imageRepeat_ || ImageRepeat::REPEAT == imageRepeat_) {
506 while (dstRect_.left_ + minX * dstRect_.width_ > left + eps) {
507 --minX;
508 }
509 while (dstRect_.left_ + maxX * dstRect_.width_ < right - eps) {
510 ++maxX;
511 }
512 }
513 if (repeat_y == imageRepeat_ || ImageRepeat::REPEAT == imageRepeat_) {
514 while (dstRect_.top_ + minY * dstRect_.height_ > top + eps) {
515 --minY;
516 }
517 while (dstRect_.top_ + maxY * dstRect_.height_ < bottom - eps) {
518 ++maxY;
519 }
520 }
521 }
522
DrawImageOnCanvas(const Drawing::SamplingOptions & samplingOptions,Drawing::Canvas & canvas,const bool hdrImageDraw)523 void RSImage::DrawImageOnCanvas(
524 const Drawing::SamplingOptions& samplingOptions, Drawing::Canvas& canvas, const bool hdrImageDraw)
525 {
526 if (canvas.GetTotalMatrix().HasPerspective()) {
527 // In case of perspective transformation, make dstRect 1px outset to anti-alias
528 dst_.MakeOutset(1, 1);
529 }
530 if (innerRect_.has_value()) {
531 canvas.DrawImageNine(image_.get(), innerRect_.value(), dst_, Drawing::FilterMode::LINEAR);
532 } else if (hdrImageDraw) {
533 canvas.DrawRect(dst_);
534 } else {
535 canvas.DrawImageRect(
536 *image_, src_, dst_, samplingOptions, Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
537 }
538 }
539
SetCompressData(const std::shared_ptr<Drawing::Data> data,const uint32_t id,const int width,const int height)540 void RSImage::SetCompressData(
541 const std::shared_ptr<Drawing::Data> data, const uint32_t id, const int width, const int height)
542 {
543 #ifdef RS_ENABLE_GL
544 if (RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL) {
545 return;
546 }
547 compressData_ = data;
548 if (compressData_) {
549 srcRect_.SetAll(0.0, 0.0, width, height);
550 GenUniqueId(image_ ? image_->GetUniqueID() : id);
551 image_ = nullptr;
552 }
553 #endif
554 }
555
556 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined (RS_ENABLE_VK))
SetCompressData(const std::shared_ptr<Drawing::Data> compressData)557 void RSImage::SetCompressData(const std::shared_ptr<Drawing::Data> compressData)
558 {
559 isDrawn_ = false;
560 compressData_ = compressData;
561 canPurgeShareMemFlag_ = CanPurgeFlag::DISABLED;
562 }
563 #endif
564
SetImageFit(int fitNum)565 void RSImage::SetImageFit(int fitNum)
566 {
567 imageFit_ = static_cast<ImageFit>(fitNum);
568 }
569
SetImageRepeat(int repeatNum)570 void RSImage::SetImageRepeat(int repeatNum)
571 {
572 imageRepeat_ = static_cast<ImageRepeat>(repeatNum);
573 }
574
SetRadius(const std::vector<Drawing::Point> & radius)575 void RSImage::SetRadius(const std::vector<Drawing::Point>& radius)
576 {
577 hasRadius_ = false;
578 for (auto i = 0; i < CORNER_SIZE; i++) {
579 radius_[i] = radius[i];
580 hasRadius_ = hasRadius_ || !radius_[i].IsZero();
581 }
582 }
583
SetScale(double scale)584 void RSImage::SetScale(double scale)
585 {
586 if (scale > 0.0) {
587 scale_ = scale;
588 }
589 }
590
SetNodeId(NodeId nodeId)591 void RSImage::SetNodeId(NodeId nodeId)
592 {
593 nodeId_ = nodeId;
594 }
595
SetPaint(Drawing::Paint paint)596 void RSImage::SetPaint(Drawing::Paint paint)
597 {
598 paint_ = paint;
599 }
600
SetDynamicRangeMode(uint32_t dynamicRangeMode)601 void RSImage::SetDynamicRangeMode(uint32_t dynamicRangeMode)
602 {
603 dynamicRangeMode_ = dynamicRangeMode;
604 }
605
606 #ifdef ROSEN_OHOS
UnmarshallingIdAndSize(Parcel & parcel,uint64_t & uniqueId,int & width,int & height)607 static bool UnmarshallingIdAndSize(Parcel& parcel, uint64_t& uniqueId, int& width, int& height)
608 {
609 if (!RSMarshallingHelper::Unmarshalling(parcel, uniqueId)) {
610 RS_LOGE("RSImage::Unmarshalling uniqueId fail");
611 return false;
612 }
613 RS_PROFILER_PATCH_NODE_ID(parcel, uniqueId);
614 if (!RSMarshallingHelper::Unmarshalling(parcel, width)) {
615 RS_LOGE("RSImage::Unmarshalling width fail");
616 return false;
617 }
618 if (!RSMarshallingHelper::Unmarshalling(parcel, height)) {
619 RS_LOGE("RSImage::Unmarshalling height fail");
620 return false;
621 }
622 return true;
623 }
624
UnmarshallingCompressData(Parcel & parcel,bool skipData,std::shared_ptr<Drawing::Data> & compressData)625 static bool UnmarshallingCompressData(Parcel& parcel, bool skipData, std::shared_ptr<Drawing::Data>& compressData)
626 {
627 if (skipData) {
628 if (!RSMarshallingHelper::SkipData(parcel)) {
629 RS_LOGE("RSImage::Unmarshalling SkipData fail");
630 return false;
631 }
632 } else {
633 if (!RSMarshallingHelper::UnmarshallingWithCopy(parcel, compressData)) {
634 RS_LOGE("RSImage::Unmarshalling UnmarshallingWithCopy Data fail");
635 return false;
636 }
637 }
638 return true;
639 }
640
Marshalling(Parcel & parcel) const641 bool RSImage::Marshalling(Parcel& parcel) const
642 {
643 int imageFit = static_cast<int>(imageFit_);
644 int imageRepeat = static_cast<int>(imageRepeat_);
645
646 std::lock_guard<std::mutex> lock(mutex_);
647 auto image = image_;
648 auto compressData = compressData_;
649 if (image && image->IsTextureBacked()) {
650 image = nullptr;
651 ROSEN_LOGE("RSImage::Marshalling skip texture image");
652 }
653 RS_PROFILER_MARSHAL_DRAWINGIMAGE(image, compressData);
654 bool success = RSMarshallingHelper::Marshalling(parcel, uniqueId_) &&
655 RSMarshallingHelper::Marshalling(parcel, static_cast<int>(srcRect_.width_)) &&
656 RSMarshallingHelper::Marshalling(parcel, static_cast<int>(srcRect_.height_)) &&
657 RSMarshallingHelper::Marshalling(parcel, nodeId_) &&
658 parcel.WriteBool(pixelMap_ == nullptr) &&
659 RSMarshallingHelper::Marshalling(parcel, image) &&
660 RSMarshallingHelper::Marshalling(parcel, pixelMap_) &&
661 RSMarshallingHelper::Marshalling(parcel, compressData) &&
662 RSMarshallingHelper::Marshalling(parcel, imageFit) &&
663 RSMarshallingHelper::Marshalling(parcel, imageRepeat) &&
664 RSMarshallingHelper::Marshalling(parcel, radius_) &&
665 RSMarshallingHelper::Marshalling(parcel, scale_) &&
666 RSMarshallingHelper::Marshalling(parcel, rotateDegree_);
667 return success;
668 }
669
Unmarshalling(Parcel & parcel)670 RSImage* RSImage::Unmarshalling(Parcel& parcel)
671 {
672 uint64_t uniqueId;
673 int width;
674 int height;
675 NodeId nodeId;
676 if (!UnmarshalIdSizeAndNodeId(parcel, uniqueId, width, height, nodeId)) {
677 return nullptr;
678 }
679 bool useSkImage;
680 std::shared_ptr<Drawing::Image> img;
681 std::shared_ptr<Media::PixelMap> pixelMap;
682 void* imagepixelAddr = nullptr;
683 if (!UnmarshallingDrawingImageAndPixelMap(parcel, uniqueId, useSkImage, img, pixelMap, imagepixelAddr)) {
684 return nullptr;
685 }
686 std::shared_ptr<Drawing::Data> compressData;
687 bool skipData = img != nullptr || !useSkImage;
688 if (!UnmarshallingCompressData(parcel, skipData, compressData)) {
689 return nullptr;
690 }
691 int fitNum;
692 int repeatNum;
693 std::vector<Drawing::Point> radius(CORNER_SIZE);
694 double scale;
695 int32_t degree = 0;
696 if (!UnmarshalImageProperties(parcel, fitNum, repeatNum, radius, scale, degree)) {
697 return nullptr;
698 }
699 RSImage* rsImage = new RSImage();
700 rsImage->SetImage(img);
701 rsImage->SetImagePixelAddr(imagepixelAddr);
702 rsImage->SetCompressData(compressData, uniqueId, width, height);
703 rsImage->SetPixelMap(pixelMap);
704 rsImage->SetImageFit(fitNum);
705 rsImage->SetImageRepeat(repeatNum);
706 rsImage->SetRadius(radius);
707 rsImage->SetScale(scale);
708 rsImage->SetNodeId(nodeId);
709 rsImage->SetImageRotateDegree(degree);
710 ProcessImageAfterCreation(rsImage, uniqueId, useSkImage, pixelMap);
711 return rsImage;
712 }
713
UnmarshalIdSizeAndNodeId(Parcel & parcel,uint64_t & uniqueId,int & width,int & height,NodeId & nodeId)714 bool RSImage::UnmarshalIdSizeAndNodeId(Parcel& parcel, uint64_t& uniqueId, int& width, int& height, NodeId& nodeId)
715 {
716 if (!UnmarshallingIdAndSize(parcel, uniqueId, width, height)) {
717 RS_LOGE("RSImage::Unmarshalling UnmarshallingIdAndSize fail");
718 return false;
719 }
720 if (!RSMarshallingHelper::Unmarshalling(parcel, nodeId)) {
721 RS_LOGE("RSImage::Unmarshalling nodeId fail");
722 return false;
723 }
724 RS_PROFILER_PATCH_NODE_ID(parcel, nodeId);
725 return true;
726 }
727
UnmarshalImageProperties(Parcel & parcel,int & fitNum,int & repeatNum,std::vector<Drawing::Point> & radius,double & scale,int32_t & degree)728 bool RSImage::UnmarshalImageProperties(
729 Parcel& parcel, int& fitNum, int& repeatNum, std::vector<Drawing::Point>& radius, double& scale, int32_t& degree)
730 {
731 if (!RSMarshallingHelper::Unmarshalling(parcel, fitNum)) {
732 RS_LOGE("RSImage::Unmarshalling fitNum fail");
733 return false;
734 }
735
736 if (!RSMarshallingHelper::Unmarshalling(parcel, repeatNum)) {
737 RS_LOGE("RSImage::Unmarshalling repeatNum fail");
738 return false;
739 }
740
741 if (!RSMarshallingHelper::Unmarshalling(parcel, radius)) {
742 RS_LOGE("RSImage::Unmarshalling radius fail");
743 return false;
744 }
745
746 if (!RSMarshallingHelper::Unmarshalling(parcel, scale)) {
747 RS_LOGE("RSImage::Unmarshalling scale fail");
748 return false;
749 }
750
751 if (!RSMarshallingHelper::Unmarshalling(parcel, degree)) {
752 RS_LOGE("RSImage::Unmarshalling rotateDegree fail");
753 return false;
754 }
755
756 return true;
757 }
758
ProcessImageAfterCreation(RSImage * rsImage,const uint64_t uniqueId,const bool useSkImage,const std::shared_ptr<Media::PixelMap> & pixelMap)759 void RSImage::ProcessImageAfterCreation(
760 RSImage* rsImage, const uint64_t uniqueId, const bool useSkImage, const std::shared_ptr<Media::PixelMap>& pixelMap)
761 {
762 rsImage->uniqueId_ = uniqueId;
763 rsImage->MarkRenderServiceImage();
764 RSImageBase::IncreaseCacheRefCount(uniqueId, useSkImage, pixelMap);
765 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_GL) && defined(RS_ENABLE_PARALLEL_UPLOAD)
766 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
767 #if defined(RS_ENABLE_UNI_RENDER)
768 if (pixelMap != nullptr && pixelMap->GetAllocatorType() != Media::AllocatorType::DMA_ALLOC) {
769 rsImage->ConvertPixelMapToDrawingImage(true);
770 }
771 #endif
772 }
773 #endif
774 }
775 #endif
776 } // namespace Rosen
777 } // namespace OHOS
778