1 /*
2 * Copyright (c) 2023 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_base.h"
17
18 #include <unistd.h>
19 #ifndef USE_ROSEN_DRAWING
20 #include "include/core/SkImage.h"
21 #include "src/core/SkImagePriv.h"
22 #else
23 #include "image/image.h"
24 #endif
25 #include "common/rs_background_thread.h"
26 #ifdef RS_ENABLE_PARALLEL_UPLOAD
27 #include "render/rs_resource_manager.h"
28 #endif
29 #include "common/rs_common_def.h"
30 #include "platform/common/rs_log.h"
31 #include "pipeline/rs_task_dispatcher.h"
32 #include "pipeline/sk_resource_manager.h"
33 #include "property/rs_properties_painter.h"
34 #include "render/rs_image_cache.h"
35 #include "render/rs_pixel_map_util.h"
36 #include "memory/rs_memory_track.h"
37 #include "rs_trace.h"
38 #include "sandbox_utils.h"
39
40 namespace OHOS::Rosen {
~RSImageBase()41 RSImageBase::~RSImageBase()
42 {
43 if (pixelMap_) {
44 pixelMap_ = nullptr;
45 if (uniqueId_ > 0) {
46 if (renderServiceImage_) {
47 auto task = [uniqueId = uniqueId_]() {
48 RSImageCache::Instance().ReleasePixelMapCache(uniqueId);
49 };
50 RSBackgroundThread::Instance().PostTask(task);
51 } else {
52 RSImageCache::Instance().ReleasePixelMapCache(uniqueId_);
53 }
54 }
55 } else { // if pixelMap_ not nullptr, do not release skImage cache
56 if (image_) {
57 image_ = nullptr;
58 if (uniqueId_ > 0) {
59 // if image_ is obtained by RSPixelMapUtil::ExtractSkImage, uniqueId_ here is related to pixelMap,
60 // image_ is not in SkiaImageCache, but still check it here
61 // in this case, the cached image_ will be removed when pixelMap cache is removed
62 #ifndef USE_ROSEN_DRAWING
63 RSImageCache::Instance().ReleaseSkiaImageCache(uniqueId_);
64 #else
65 RSImageCache::Instance().ReleaseDrawingImageCache(uniqueId_);
66 #endif
67 }
68 }
69 }
70 }
71
72 #ifndef USE_ROSEN_DRAWING
73 #ifdef NEW_SKIA
DrawImage(RSPaintFilterCanvas & canvas,const SkSamplingOptions & samplingOptions,const SkPaint & paint)74 void RSImageBase::DrawImage(RSPaintFilterCanvas& canvas, const SkSamplingOptions& samplingOptions, const SkPaint& paint)
75 #else
76 void RSImageBase::DrawImage(RSPaintFilterCanvas& canvas, const SkPaint& paint)
77 #endif
78 {
79 ConvertPixelMapToSkImage();
80 auto src = RSPropertiesPainter::Rect2SkRect(srcRect_);
81 auto dst = RSPropertiesPainter::Rect2SkRect(dstRect_);
82 if (image_ == nullptr) {
83 RS_LOGE("RSImageBase::DrawImage image_ is nullptr");
84 return;
85 }
86 #ifdef NEW_SKIA
87 auto texture = image_->getBackendTexture(true);
88 auto image = SkImage::MakeFromTexture(canvas.recordingContext(), texture, kBottomLeft_GrSurfaceOrigin,
89 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
90 if (image == nullptr) {
91 canvas.drawImageRect(image_, src, dst, samplingOptions, &paint, SkCanvas::kStrict_SrcRectConstraint);
92 return;
93 }
94 canvas.drawImageRect(image, src, dst, samplingOptions, &paint, SkCanvas::kStrict_SrcRectConstraint);
95 #else
96 canvas.drawImageRect(image_, src, dst, &paint);
97 #endif
98 }
99 #else
DrawImage(Drawing::Canvas & canvas,const Drawing::SamplingOptions & samplingOptions)100 void RSImageBase::DrawImage(Drawing::Canvas& canvas, const Drawing::SamplingOptions& samplingOptions)
101 {
102 ConvertPixelMapToDrawingImage();
103 auto src = RSPropertiesPainter::Rect2DrawingRect(srcRect_);
104 auto dst = RSPropertiesPainter::Rect2DrawingRect(dstRect_);
105 if (image_ == nullptr) {
106 RS_LOGE("RSImageBase::DrawImage image_ is nullptr");
107 return;
108 }
109 canvas.DrawImageRect(*image_, src, dst, samplingOptions);
110 }
111 #endif
112
113 #ifndef USE_ROSEN_DRAWING
SetImage(const sk_sp<SkImage> image)114 void RSImageBase::SetImage(const sk_sp<SkImage> image)
115 #else
116 void RSImageBase::SetImage(const std::shared_ptr<Drawing::Image> image)
117 #endif
118 {
119 isDrawn_ = false;
120 image_ = image;
121 if (image_) {
122 #ifndef ROSEN_ARKUI_X
123 SKResourceManager::Instance().HoldResource(image);
124 #endif
125 #ifndef USE_ROSEN_DRAWING
126 srcRect_.SetAll(0.0, 0.0, image_->width(), image_->height());
127 GenUniqueId(image_->uniqueID());
128 #else
129 srcRect_.SetAll(0.0, 0.0, image_->GetWidth(), image_->GetHeight());
130 GenUniqueId(image_->GetUniqueID());
131 #endif
132 }
133 }
134
135 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
136 #ifndef USE_ROSEN_DRAWING
SetDmaImage(const sk_sp<SkImage> image)137 void RSImageBase::SetDmaImage(const sk_sp<SkImage> image)
138 #else
139 void RSImageBase::SetDmaImage(const std::shared_ptr<Drawing::Image> image)
140 #endif
141 {
142 isDrawn_ = false;
143 image_ = image;
144 #ifndef ROSEN_ARKUI_X
145 SKResourceManager::Instance().HoldResource(image);
146 #endif
147 }
148 #endif
149
SetPixelMap(const std::shared_ptr<Media::PixelMap> & pixelmap)150 void RSImageBase::SetPixelMap(const std::shared_ptr<Media::PixelMap>& pixelmap)
151 {
152 pixelMap_ = pixelmap;
153 if (pixelMap_) {
154 srcRect_.SetAll(0.0, 0.0, pixelMap_->GetWidth(), pixelMap_->GetHeight());
155 image_ = nullptr;
156 GenUniqueId(pixelMap_->GetUniqueId());
157 }
158 }
159
DumpPicture(DfxString & info) const160 void RSImageBase::DumpPicture(DfxString& info) const
161 {
162 if (!pixelMap_) {
163 return;
164 }
165 info.AppendFormat("%d [%d * %d] %p\n", pixelMap_->GetByteCount(), pixelMap_->GetWidth(), pixelMap_->GetHeight(),
166 pixelMap_.get());
167 }
168
SetSrcRect(const RectF & srcRect)169 void RSImageBase::SetSrcRect(const RectF& srcRect)
170 {
171 srcRect_ = srcRect;
172 }
173
SetDstRect(const RectF & dstRect)174 void RSImageBase::SetDstRect(const RectF& dstRect)
175 {
176 if (dstRect_ != dstRect) {
177 isDrawn_ = false;
178 }
179 dstRect_ = dstRect;
180 }
181
SetImagePixelAddr(void * addr)182 void RSImageBase::SetImagePixelAddr(void* addr)
183 {
184 imagePixelAddr_ = addr;
185 }
186
UpdateNodeIdToPicture(NodeId nodeId)187 void RSImageBase::UpdateNodeIdToPicture(NodeId nodeId)
188 {
189 if (!nodeId) {
190 return;
191 }
192 if (pixelMap_) {
193 #ifndef ROSEN_ARKUI_X
194 MemoryTrack::Instance().UpdatePictureInfo(pixelMap_->GetPixels(), nodeId, ExtractPid(nodeId));
195 #endif
196 }
197 if (image_ || imagePixelAddr_) {
198 #ifndef ROSEN_ARKUI_X
199 MemoryTrack::Instance().UpdatePictureInfo(imagePixelAddr_, nodeId, ExtractPid(nodeId));
200 #endif
201 }
202 }
203
MarkRenderServiceImage()204 void RSImageBase::MarkRenderServiceImage()
205 {
206 renderServiceImage_ = true;
207 }
208
209 #ifdef ROSEN_OHOS
210 #ifndef USE_ROSEN_DRAWING
UnmarshallingAndCacheSkImage(Parcel & parcel,sk_sp<SkImage> & img,uint64_t uniqueId,void * & imagepixelAddr)211 static bool UnmarshallingAndCacheSkImage(Parcel& parcel, sk_sp<SkImage>& img, uint64_t uniqueId, void*& imagepixelAddr)
212 {
213 if (img != nullptr) {
214 // match a cached SkImage
215 if (!RSMarshallingHelper::SkipSkImage(parcel)) {
216 RS_LOGE("UnmarshalAndCacheSkImage SkipSkImage fail");
217 return false;
218 }
219 } else if (RSMarshallingHelper::Unmarshalling(parcel, img, imagepixelAddr)) {
220 // unmarshalling the SkImage and cache it
221 RSImageCache::Instance().CacheSkiaImage(uniqueId, img);
222 } else {
223 RS_LOGE("UnmarshalAndCacheSkImage fail");
224 return false;
225 }
226 return true;
227 }
228 #else
UnmarshallingAndCacheDrawingImage(Parcel & parcel,std::shared_ptr<Drawing::Image> & img,uint64_t uniqueId,void * & imagepixelAddr)229 static bool UnmarshallingAndCacheDrawingImage(
230 Parcel& parcel, std::shared_ptr<Drawing::Image>& img, uint64_t uniqueId, void*& imagepixelAddr)
231 {
232 if (img != nullptr) {
233 // match a cached SkImage
234 if (!RSMarshallingHelper::SkipImage(parcel)) {
235 RS_LOGE("UnmarshalAndCacheSkImage SkipSkImage fail");
236 return false;
237 }
238 } else if (RSMarshallingHelper::Unmarshalling(parcel, img, imagepixelAddr)) {
239 // unmarshalling the SkImage and cache it
240 RSImageCache::Instance().CacheDrawingImage(uniqueId, img);
241 } else {
242 RS_LOGE("UnmarshalAndCacheSkImage fail");
243 return false;
244 }
245 return true;
246 }
247 #endif
248
249
UnmarshallingAndCachePixelMap(Parcel & parcel,std::shared_ptr<Media::PixelMap> & pixelMap,uint64_t uniqueId)250 static bool UnmarshallingAndCachePixelMap(Parcel& parcel, std::shared_ptr<Media::PixelMap>& pixelMap, uint64_t uniqueId)
251 {
252 if (pixelMap != nullptr) {
253 // match a cached pixelMap
254 if (!RSMarshallingHelper::SkipPixelMap(parcel)) {
255 return false;
256 }
257 } else if (RSMarshallingHelper::Unmarshalling(parcel, pixelMap)) {
258 if (pixelMap && !pixelMap->IsEditable()) {
259 // unmarshalling the pixelMap and cache it
260 RSImageCache::Instance().CachePixelMap(uniqueId, pixelMap);
261 }
262 } else {
263 return false;
264 }
265 return true;
266 }
267
UnmarshallingIdAndRect(Parcel & parcel,uint64_t & uniqueId,RectF & srcRect,RectF & dstRect)268 static bool UnmarshallingIdAndRect(Parcel& parcel, uint64_t& uniqueId, RectF& srcRect, RectF& dstRect)
269 {
270 if (!RSMarshallingHelper::Unmarshalling(parcel, uniqueId)) {
271 RS_LOGE("RSImage::Unmarshalling uniqueId fail");
272 return false;
273 }
274 if (!RSMarshallingHelper::Unmarshalling(parcel, srcRect)) {
275 RS_LOGE("RSImage::Unmarshalling srcRect fail");
276 return false;
277 }
278 if (!RSMarshallingHelper::Unmarshalling(parcel, dstRect)) {
279 RS_LOGE("RSImage::Unmarshalling dstRect fail");
280 return false;
281 }
282 return true;
283 }
284
285 #ifndef USE_ROSEN_DRAWING
UnmarshallingSkImageAndPixelMap(Parcel & parcel,uint64_t uniqueId,bool & useSkImage,sk_sp<SkImage> & img,std::shared_ptr<Media::PixelMap> & pixelMap,void * & imagepixelAddr)286 bool RSImageBase::UnmarshallingSkImageAndPixelMap(Parcel& parcel, uint64_t uniqueId, bool& useSkImage,
287 sk_sp<SkImage>& img, std::shared_ptr<Media::PixelMap>& pixelMap, void*& imagepixelAddr)
288 #else
289 bool RSImageBase::UnmarshallingDrawingImageAndPixelMap(Parcel& parcel, uint64_t uniqueId, bool& useSkImage,
290 std::shared_ptr<Drawing::Image>& img, std::shared_ptr<Media::PixelMap>& pixelMap, void*& imagepixelAddr)
291 #endif
292 {
293 if (!RSMarshallingHelper::Unmarshalling(parcel, useSkImage)) {
294 return false;
295 }
296 if (useSkImage) {
297 #ifndef USE_ROSEN_DRAWING
298 img = RSImageCache::Instance().GetSkiaImageCache(uniqueId);
299 RS_TRACE_NAME_FMT("RSImageBase::Unmarshalling skImage uniqueId:%lu, size:[%d %d], cached:%d",
300 uniqueId, img ? img->width() : 0, img ? img->height() : 0, img != nullptr);
301 if (!UnmarshallingAndCacheSkImage(parcel, img, uniqueId, imagepixelAddr)) {
302 #else
303 img = RSImageCache::Instance().GetDrawingImageCache(uniqueId);
304 RS_TRACE_NAME_FMT("RSImageBase::Unmarshalling Image uniqueId:%lu, size:[%d %d], cached:%d",
305 uniqueId, img ? img->GetWidth() : 0, img ? img->GetHeight() : 0, img != nullptr);
306 if (!UnmarshallingAndCacheDrawingImage(parcel, img, uniqueId, imagepixelAddr)) {
307 #endif
308 RS_LOGE("RSImageBase::Unmarshalling UnmarshalAndCacheSkImage fail");
309 return false;
310 }
311 RSMarshallingHelper::SkipPixelMap(parcel);
312 } else {
313 #ifndef USE_ROSEN_DRAWING
314 if (!RSMarshallingHelper::SkipSkImage(parcel)) {
315 #else
316 if (!RSMarshallingHelper::SkipImage(parcel)) {
317 #endif
318 return false;
319 }
320 pixelMap = RSImageCache::Instance().GetPixelMapCache(uniqueId);
321 RS_TRACE_NAME_FMT("RSImageBase::Unmarshalling pixelMap uniqueId:%lu, size:[%d %d], cached:%d",
322 uniqueId, pixelMap ? pixelMap->GetWidth() : 0, pixelMap ? pixelMap->GetHeight() : 0, pixelMap != nullptr);
323 if (!UnmarshallingAndCachePixelMap(parcel, pixelMap, uniqueId)) {
324 RS_LOGE("RSImageBase::Unmarshalling UnmarshalAndCachePixelMap fail");
325 return false;
326 }
327 }
328 return true;
329 }
330
331 void RSImageBase::IncreaseCacheRefCount(uint64_t uniqueId, bool useSkImage, std::shared_ptr<Media::PixelMap>
332 pixelMap)
333 {
334 if (useSkImage) {
335 #ifndef USE_ROSEN_DRAWING
336 RSImageCache::Instance().IncreaseSkiaImageCacheRefCount(uniqueId);
337 #else
338 RSImageCache::Instance().IncreaseDrawingImageCacheRefCount(uniqueId);
339 #endif
340 } else if (pixelMap && !pixelMap->IsEditable()) {
341 RSImageCache::Instance().IncreasePixelMapCacheRefCount(uniqueId);
342 }
343 }
344
345 bool RSImageBase::Marshalling(Parcel& parcel) const
346 {
347 std::lock_guard<std::mutex> lock(mutex_);
348 bool success = RSMarshallingHelper::Marshalling(parcel, uniqueId_) &&
349 RSMarshallingHelper::Marshalling(parcel, srcRect_) &&
350 RSMarshallingHelper::Marshalling(parcel, dstRect_) &&
351 parcel.WriteBool(pixelMap_ == nullptr) &&
352 RSMarshallingHelper::Marshalling(parcel, image_) &&
353 RSMarshallingHelper::Marshalling(parcel, pixelMap_);
354 return success;
355 }
356
357 RSImageBase* RSImageBase::Unmarshalling(Parcel& parcel)
358 {
359 uint64_t uniqueId;
360 RectF srcRect;
361 RectF dstRect;
362 if (!UnmarshallingIdAndRect(parcel, uniqueId, srcRect, dstRect)) {
363 RS_LOGE("RSImage::Unmarshalling UnmarshalIdAndSize fail");
364 return nullptr;
365 }
366
367 bool useSkImage;
368 #ifndef USE_ROSEN_DRAWING
369 sk_sp<SkImage> img;
370 std::shared_ptr<Media::PixelMap> pixelMap;
371 void* imagepixelAddr = nullptr;
372 if (!UnmarshallingSkImageAndPixelMap(parcel, uniqueId, useSkImage, img, pixelMap, imagepixelAddr)) {
373 return nullptr;
374 }
375 #else
376 std::shared_ptr<Drawing::Image> img = std::make_shared<Drawing::Image>();
377 std::shared_ptr<Media::PixelMap> pixelMap;
378 void* imagepixelAddr = nullptr;
379 if (!UnmarshallingDrawingImageAndPixelMap(parcel, uniqueId, useSkImage, img, pixelMap, imagepixelAddr)) {
380 return nullptr;
381 }
382 #endif
383
384 RSImageBase* rsImage = new RSImageBase();
385 rsImage->SetImage(img);
386 rsImage->SetImagePixelAddr(imagepixelAddr);
387 rsImage->SetPixelMap(pixelMap);
388 rsImage->SetSrcRect(srcRect);
389 rsImage->SetDstRect(dstRect);
390 rsImage->uniqueId_ = uniqueId;
391 rsImage->MarkRenderServiceImage();
392 IncreaseCacheRefCount(uniqueId, useSkImage, pixelMap);
393 return rsImage;
394 }
395 #endif
396
397 #ifndef USE_ROSEN_DRAWING
398 void RSImageBase::ConvertPixelMapToSkImage(bool paraUpload)
399 {
400 #if defined(ROSEN_OHOS)
401 // paraUpload only enable in render_service or UnmarshalThread
402 pid_t tid = paraUpload ? getpid() : gettid();
403 #endif
404 if (!image_ && pixelMap_ && !pixelMap_->IsAstc()) {
405 if (!pixelMap_->IsEditable()) {
406 #if defined(ROSEN_OHOS)
407 image_ = RSImageCache::Instance().GetRenderSkiaImageCacheByPixelMapId(uniqueId_, tid);
408 #else
409 image_ = RSImageCache::Instance().GetRenderSkiaImageCacheByPixelMapId(uniqueId_);
410 #endif
411 }
412 if (!image_) {
413 image_ = RSPixelMapUtil::ExtractSkImage(pixelMap_);
414 if (!pixelMap_->IsEditable()) {
415 #if defined(ROSEN_OHOS)
416 RSImageCache::Instance().CacheRenderSkiaImageByPixelMapId(uniqueId_, image_, tid);
417 #else
418 RSImageCache::Instance().CacheRenderSkiaImageByPixelMapId(uniqueId_, image_);
419 #endif
420 }
421 #ifdef RS_ENABLE_PARALLEL_UPLOAD
422 RSResourceManager::Instance().UploadTexture(paraUpload&renderServiceImage_, image_, pixelMap_, uniqueId_);
423 #endif
424 }
425 }
426 }
427 #else
428 void RSImageBase::ConvertPixelMapToDrawingImage(bool paraUpload)
429 {
430 #if defined(ROSEN_OHOS)
431 // paraUpload only enable in render_service or UnmarshalThread
432 pid_t tid = paraUpload ? getpid() : gettid();
433 #endif
434 if (!image_ && pixelMap_ && !pixelMap_->IsAstc()) {
435 if (!pixelMap_->IsEditable()) {
436 #if defined(ROSEN_OHOS)
437 image_ = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_, tid);
438 #else
439 image_ = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_);
440 #endif
441 }
442 if (!image_) {
443 image_ = RSPixelMapUtil::ExtractDrawingImage(pixelMap_);
444 if (!pixelMap_->IsEditable()) {
445 #if defined(ROSEN_OHOS)
446 RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image_, tid);
447 #else
448 RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image_);
449 #endif
450 }
451 #ifdef RS_ENABLE_PARALLEL_UPLOAD
452 RSResourceManager::Instance().UploadTexture(paraUpload&renderServiceImage_, image_, pixelMap_, uniqueId_);
453 #endif
454 }
455 }
456 }
457 #endif
458
459 void RSImageBase::GenUniqueId(uint32_t id)
460 {
461 static uint64_t shiftedPid = static_cast<uint64_t>(GetRealPid()) << 32; // 32 for 64-bit unsignd number shift
462 uniqueId_ = shiftedPid | id;
463 }
464
465 std::shared_ptr<Media::PixelMap> RSImageBase::GetPixelMap() const
466 {
467 return pixelMap_;
468 }
469 }