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