• 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 #ifndef USE_ROSEN_DRAWING
19 #include "include/core/SkImage.h"
20 #else
21 #include "image/image.h"
22 #endif
23 #include "common/rs_background_thread.h"
24 #include "common/rs_common_def.h"
25 #include "platform/common/rs_log.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 "memory/rs_memory_track.h"
30 #include "rs_trace.h"
31 #include "sandbox_utils.h"
32 
33 namespace OHOS::Rosen {
~RSImageBase()34 RSImageBase::~RSImageBase()
35 {
36     if (pixelMap_) {
37         pixelMap_ = nullptr;
38         if (uniqueId_ > 0) {
39             if (renderServiceImage_) {
40                 auto task = [uniqueId = uniqueId_]() {
41                     RSImageCache::Instance().ReleasePixelMapCache(uniqueId);
42                 };
43                 RSBackgroundThread::Instance().PostTask(task);
44             } else {
45                 RSImageCache::Instance().ReleasePixelMapCache(uniqueId_);
46             }
47         }
48     } else { // if pixelMap_ not nullptr, do not release skImage cache
49         if (image_) {
50             image_ = nullptr;
51             if (uniqueId_ > 0) {
52                 // if image_ is obtained by RSPixelMapUtil::ExtractSkImage, uniqueId_ here is related to pixelMap,
53                 // image_ is not in SkiaImageCache, but still check it here
54                 // in this case, the cached image_ will be removed when pixelMap cache is removed
55 #ifndef USE_ROSEN_DRAWING
56                 RSImageCache::Instance().ReleaseSkiaImageCache(uniqueId_);
57 #else
58                 RSImageCache::Instance().ReleaseDrawingImageCache(uniqueId_);
59 #endif
60             }
61         }
62     }
63 }
64 
65 #ifndef USE_ROSEN_DRAWING
66 #ifdef NEW_SKIA
DrawImage(SkCanvas & canvas,const SkSamplingOptions & samplingOptions,const SkPaint & paint)67 void RSImageBase::DrawImage(SkCanvas& canvas, const SkSamplingOptions& samplingOptions, const SkPaint& paint)
68 #else
69 void RSImageBase::DrawImage(SkCanvas& canvas, const SkPaint& paint)
70 #endif
71 {
72     ConvertPixelMapToSkImage();
73     auto src = RSPropertiesPainter::Rect2SkRect(srcRect_);
74     auto dst = RSPropertiesPainter::Rect2SkRect(dstRect_);
75 #ifdef NEW_SKIA
76     canvas.drawImageRect(image_, src, dst, samplingOptions, &paint, SkCanvas::kStrict_SrcRectConstraint);
77 #else
78     canvas.drawImageRect(image_, src, dst, &paint);
79 #endif
80 }
81 #else
DrawImage(Drawing::Canvas & canvas,const Drawing::Brush & brush)82 void RSImageBase::DrawImage(Drawing::Canvas& canvas, const Drawing::Brush& brush)
83 {
84     ConvertPixelMapToDrawingImage();
85     auto src = RSPropertiesPainter::Rect2DrawingRect(srcRect_);
86     auto dst = RSPropertiesPainter::Rect2DrawingRect(dstRect_);
87     if (image_ == nullptr) {
88         RS_LOGE("RSImageBase::DrawImage image_ is nullptr");
89         return;
90     }
91     canvas.AttachBrush(brush);
92     canvas.DrawImageRect(*image_, src, dst, Drawing::SamplingOptions());
93     canvas.DetachBrush();
94 }
95 #endif
96 
97 #ifndef USE_ROSEN_DRAWING
SetImage(const sk_sp<SkImage> image)98 void RSImageBase::SetImage(const sk_sp<SkImage> image)
99 #else
100 void RSImageBase::SetImage(const std::shared_ptr<Drawing::Image> image)
101 #endif
102 {
103     image_ = image;
104     if (image_) {
105 #ifndef USE_ROSEN_DRAWING
106         srcRect_.SetAll(0.0, 0.0, image_->width(), image_->height());
107         GenUniqueId(image_->uniqueID());
108 #else
109         srcRect_.SetAll(0.0, 0.0, image_->GetWidth(), image_->GetHeight());
110         GenUniqueId(image_->GetUniqueID());
111 #endif
112     }
113 }
114 
SetPixelMap(const std::shared_ptr<Media::PixelMap> & pixelmap)115 void RSImageBase::SetPixelMap(const std::shared_ptr<Media::PixelMap>& pixelmap)
116 {
117     pixelMap_ = pixelmap;
118     if (pixelMap_) {
119         srcRect_.SetAll(0.0, 0.0, pixelMap_->GetWidth(), pixelMap_->GetHeight());
120         image_ = nullptr;
121         GenUniqueId(pixelMap_->GetUniqueId());
122     }
123 }
124 
SetSrcRect(const RectF & srcRect)125 void RSImageBase::SetSrcRect(const RectF& srcRect)
126 {
127     srcRect_ = srcRect;
128 }
129 
SetDstRect(const RectF & dstRect)130 void RSImageBase::SetDstRect(const RectF& dstRect)
131 {
132     dstRect_ = dstRect;
133 }
134 
SetImagePixelAddr(void * addr)135 void RSImageBase::SetImagePixelAddr(void* addr)
136 {
137     imagePixelAddr_ = addr;
138 }
139 
UpdateNodeIdToPicture(NodeId nodeId)140 void RSImageBase::UpdateNodeIdToPicture(NodeId nodeId)
141 {
142     if (!nodeId) {
143         return;
144     }
145     if (pixelMap_) {
146         MemoryTrack::Instance().UpdatePictureInfo(pixelMap_->GetPixels(), nodeId, ExtractPid(nodeId));
147     }
148     if (image_ || imagePixelAddr_) {
149         MemoryTrack::Instance().UpdatePictureInfo(imagePixelAddr_, nodeId, ExtractPid(nodeId));
150     }
151 }
152 
MarkRenderServiceImage()153 void RSImageBase::MarkRenderServiceImage()
154 {
155     renderServiceImage_ = true;
156 }
157 
158 #ifdef ROSEN_OHOS
159 #ifndef USE_ROSEN_DRAWING
UnmarshallingAndCacheSkImage(Parcel & parcel,sk_sp<SkImage> & img,uint64_t uniqueId,void * & imagepixelAddr)160 static bool UnmarshallingAndCacheSkImage(Parcel& parcel, sk_sp<SkImage>& img, uint64_t uniqueId, void*& imagepixelAddr)
161 {
162     if (img != nullptr) {
163         // match a cached SkImage
164         if (!RSMarshallingHelper::SkipSkImage(parcel)) {
165             RS_LOGE("UnmarshalAndCacheSkImage SkipSkImage fail");
166             return false;
167         }
168     } else if (RSMarshallingHelper::Unmarshalling(parcel, img, imagepixelAddr)) {
169         // unmarshalling the SkImage and cache it
170         RSImageCache::Instance().CacheSkiaImage(uniqueId, img);
171     } else {
172         RS_LOGE("UnmarshalAndCacheSkImage fail");
173         return false;
174     }
175     return true;
176 }
177 #else
UnmarshallingAndCacheDrawingImage(Parcel & parcel,std::shared_ptr<Drawing::Image> & img,uint64_t uniqueId,void * & imagepixelAddr)178 static bool UnmarshallingAndCacheDrawingImage(
179     Parcel& parcel, std::shared_ptr<Drawing::Image>& img, uint64_t uniqueId, void*& imagepixelAddr)
180 {
181     if (img != nullptr) {
182         // match a cached SkImage
183         if (!RSMarshallingHelper::SkipImage(parcel)) {
184             RS_LOGE("UnmarshalAndCacheSkImage SkipSkImage fail");
185             return false;
186         }
187     } else if (RSMarshallingHelper::Unmarshalling(parcel, img, imagepixelAddr)) {
188         // unmarshalling the SkImage and cache it
189         RSImageCache::Instance().CacheDrawingImage(uniqueId, img);
190     } else {
191         RS_LOGE("UnmarshalAndCacheSkImage fail");
192         return false;
193     }
194     return true;
195 }
196 #endif
197 
198 
UnmarshallingAndCachePixelMap(Parcel & parcel,std::shared_ptr<Media::PixelMap> & pixelMap,uint64_t uniqueId)199 static bool UnmarshallingAndCachePixelMap(Parcel& parcel, std::shared_ptr<Media::PixelMap>& pixelMap, uint64_t uniqueId)
200 {
201     if (pixelMap != nullptr) {
202         // match a cached pixelMap
203         if (!RSMarshallingHelper::SkipPixelMap(parcel)) {
204             return false;
205         }
206     } else if (RSMarshallingHelper::Unmarshalling(parcel, pixelMap)) {
207         if (pixelMap && !pixelMap->IsEditable()) {
208             // unmarshalling the pixelMap and cache it
209             RSImageCache::Instance().CachePixelMap(uniqueId, pixelMap);
210         }
211     } else {
212         return false;
213     }
214     return true;
215 }
216 
UnmarshallingIdAndRect(Parcel & parcel,uint64_t & uniqueId,RectF & srcRect,RectF & dstRect)217 static bool UnmarshallingIdAndRect(Parcel& parcel, uint64_t& uniqueId, RectF& srcRect, RectF& dstRect)
218 {
219     if (!RSMarshallingHelper::Unmarshalling(parcel, uniqueId)) {
220         RS_LOGE("RSImage::Unmarshalling uniqueId fail");
221         return false;
222     }
223     if (!RSMarshallingHelper::Unmarshalling(parcel, srcRect)) {
224         RS_LOGE("RSImage::Unmarshalling srcRect fail");
225         return false;
226     }
227     if (!RSMarshallingHelper::Unmarshalling(parcel, dstRect)) {
228         RS_LOGE("RSImage::Unmarshalling dstRect fail");
229         return false;
230     }
231     return true;
232 }
233 
234 #ifndef USE_ROSEN_DRAWING
UnmarshallingSkImageAndPixelMap(Parcel & parcel,uint64_t uniqueId,bool & useSkImage,sk_sp<SkImage> & img,std::shared_ptr<Media::PixelMap> & pixelMap,void * & imagepixelAddr)235 bool RSImageBase::UnmarshallingSkImageAndPixelMap(Parcel& parcel, uint64_t uniqueId, bool& useSkImage,
236     sk_sp<SkImage>& img, std::shared_ptr<Media::PixelMap>& pixelMap, void*& imagepixelAddr)
237 #else
238 bool RSImageBase::UnmarshallingDrawingImageAndPixelMap(Parcel& parcel, uint64_t uniqueId, bool& useSkImage,
239     std::shared_ptr<Drawing::Image>& img, std::shared_ptr<Media::PixelMap>& pixelMap, void*& imagepixelAddr)
240 #endif
241 {
242     if (!RSMarshallingHelper::Unmarshalling(parcel, useSkImage)) {
243         return false;
244     }
245     if (useSkImage) {
246 #ifndef USE_ROSEN_DRAWING
247         img = RSImageCache::Instance().GetSkiaImageCache(uniqueId);
248         RS_TRACE_NAME_FMT("RSImageBase::Unmarshalling skImage uniqueId:%lu, size:[%d %d], cached:%d",
249             uniqueId, img ? img->width() : 0, img ? img->height() : 0, img != nullptr);
250         if (!UnmarshallingAndCacheSkImage(parcel, img, uniqueId, imagepixelAddr)) {
251 #else
252         img = RSImageCache::Instance().GetDrawingImageCache(uniqueId);
253         RS_TRACE_NAME_FMT("RSImageBase::Unmarshalling Image uniqueId:%lu, size:[%d %d], cached:%d",
254             uniqueId, img ? img->GetWidth() : 0, img ? img->GetHeight() : 0, img != nullptr);
255         if (!UnmarshallingAndCacheDrawingImage(parcel, img, uniqueId, imagepixelAddr)) {
256 #endif
257             RS_LOGE("RSImageBase::Unmarshalling UnmarshalAndCacheSkImage fail");
258             return false;
259         }
260         RSMarshallingHelper::SkipPixelMap(parcel);
261     } else {
262 #ifndef USE_ROSEN_DRAWING
263         if (!RSMarshallingHelper::SkipSkImage(parcel)) {
264 #else
265         if (!RSMarshallingHelper::SkipImage(parcel)) {
266 #endif
267             return false;
268         }
269         pixelMap = RSImageCache::Instance().GetPixelMapCache(uniqueId);
270         RS_TRACE_NAME_FMT("RSImageBase::Unmarshalling pixelMap uniqueId:%lu, size:[%d %d], cached:%d",
271             uniqueId, pixelMap ? pixelMap->GetWidth() : 0, pixelMap ? pixelMap->GetHeight() : 0, pixelMap != nullptr);
272         if (!UnmarshallingAndCachePixelMap(parcel, pixelMap, uniqueId)) {
273             RS_LOGE("RSImageBase::Unmarshalling UnmarshalAndCachePixelMap fail");
274             return false;
275         }
276     }
277     return true;
278 }
279 
280 void RSImageBase::IncreaseCacheRefCount(uint64_t uniqueId, bool useSkImage, std::shared_ptr<Media::PixelMap>
281     pixelMap)
282 {
283     if (useSkImage) {
284 #ifndef USE_ROSEN_DRAWING
285         RSImageCache::Instance().IncreaseSkiaImageCacheRefCount(uniqueId);
286 #else
287         RSImageCache::Instance().IncreaseDrawingImageCacheRefCount(uniqueId);
288 #endif
289     } else if (pixelMap && !pixelMap->IsEditable()) {
290         RSImageCache::Instance().IncreasePixelMapCacheRefCount(uniqueId);
291     }
292 }
293 
294 bool RSImageBase::Marshalling(Parcel& parcel) const
295 {
296     std::lock_guard<std::mutex> lock(mutex_);
297     bool success = RSMarshallingHelper::Marshalling(parcel, uniqueId_) &&
298                    RSMarshallingHelper::Marshalling(parcel, srcRect_) &&
299                    RSMarshallingHelper::Marshalling(parcel, dstRect_) &&
300                    parcel.WriteBool(pixelMap_ == nullptr) &&
301                    RSMarshallingHelper::Marshalling(parcel, image_) &&
302                    RSMarshallingHelper::Marshalling(parcel, pixelMap_);
303     return success;
304 }
305 
306 RSImageBase* RSImageBase::Unmarshalling(Parcel& parcel)
307 {
308     uint64_t uniqueId;
309     RectF srcRect;
310     RectF dstRect;
311     if (!UnmarshallingIdAndRect(parcel, uniqueId, srcRect, dstRect)) {
312         RS_LOGE("RSImage::Unmarshalling UnmarshalIdAndSize fail");
313         return nullptr;
314     }
315 
316     bool useSkImage;
317 #ifndef USE_ROSEN_DRAWING
318     sk_sp<SkImage> img;
319     std::shared_ptr<Media::PixelMap> pixelMap;
320     void* imagepixelAddr = nullptr;
321     if (!UnmarshallingSkImageAndPixelMap(parcel, uniqueId, useSkImage, img, pixelMap, imagepixelAddr)) {
322         return nullptr;
323     }
324 #else
325     std::shared_ptr<Drawing::Image> img = std::make_shared<Drawing::Image>();
326     std::shared_ptr<Media::PixelMap> pixelMap;
327     void* imagepixelAddr = nullptr;
328     if (!UnmarshallingDrawingImageAndPixelMap(parcel, uniqueId, useSkImage, img, pixelMap, imagepixelAddr)) {
329         return nullptr;
330     }
331 #endif
332 
333     RSImageBase* rsImage = new RSImageBase();
334     rsImage->SetImage(img);
335     rsImage->SetImagePixelAddr(imagepixelAddr);
336     rsImage->SetPixelMap(pixelMap);
337     rsImage->SetSrcRect(srcRect);
338     rsImage->SetDstRect(dstRect);
339     rsImage->uniqueId_ = uniqueId;
340     rsImage->MarkRenderServiceImage();
341     IncreaseCacheRefCount(uniqueId, useSkImage, pixelMap);
342     return rsImage;
343 }
344 #endif
345 
346 #ifndef USE_ROSEN_DRAWING
347 void RSImageBase::ConvertPixelMapToSkImage()
348 {
349     if (!image_ && pixelMap_) {
350         if (!pixelMap_->IsEditable()) {
351             image_ = RSImageCache::Instance().GetRenderSkiaImageCacheByPixelMapId(uniqueId_);
352         }
353         if (!image_) {
354             image_ = RSPixelMapUtil::ExtractSkImage(pixelMap_);
355             if (!pixelMap_->IsEditable()) {
356                 RSImageCache::Instance().CacheRenderSkiaImageByPixelMapId(uniqueId_, image_);
357             }
358         }
359     }
360 }
361 #else
362 void RSImageBase::ConvertPixelMapToDrawingImage()
363 {
364     if (!image_ && pixelMap_) {
365         if (!pixelMap_->IsEditable()) {
366             image_ = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_);
367         }
368         if (!image_) {
369             image_ = RSPixelMapUtil::ExtractDrawingImage(pixelMap_);
370             if (!pixelMap_->IsEditable()) {
371                 RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image_);
372             }
373         }
374     }
375 }
376 #endif
377 
378 void RSImageBase::GenUniqueId(uint32_t id)
379 {
380     static uint64_t shiftedPid = static_cast<uint64_t>(GetRealPid()) << 32; // 32 for 64-bit unsignd number shift
381     uniqueId_ = shiftedPid | id;
382 }
383 
384 std::shared_ptr<Media::PixelMap> RSImageBase::GetPixelMap() const
385 {
386     return pixelMap_;
387 }
388 }