• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }