• 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 #include "image_type.h"
20 #include "image/image.h"
21 #include "common/rs_background_thread.h"
22 #ifdef RS_ENABLE_PARALLEL_UPLOAD
23 #include "render/rs_resource_manager.h"
24 #endif
25 #include "common/rs_common_def.h"
26 #include "platform/common/rs_log.h"
27 #include "pipeline/rs_task_dispatcher.h"
28 #include "pipeline/sk_resource_manager.h"
29 #include "property/rs_properties_painter.h"
30 #include "render/rs_image_cache.h"
31 #include "render/rs_pixel_map_util.h"
32 #include "memory/rs_memory_track.h"
33 #include "rs_trace.h"
34 #include "sandbox_utils.h"
35 #include "rs_profiler.h"
36 
37 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
38 #include "native_buffer_inner.h"
39 #include "native_window.h"
40 #include "platform/ohos/backend/native_buffer_utils.h"
41 #include "platform/ohos/backend/rs_vulkan_context.h"
42 #endif
43 namespace OHOS::Rosen {
44 namespace {
45 #ifdef ROSEN_OHOS
PixelMapCanBePurge(std::shared_ptr<Media::PixelMap> & pixelMap)46 bool PixelMapCanBePurge(std::shared_ptr<Media::PixelMap>& pixelMap)
47 {
48     return RSSystemProperties::GetRSImagePurgeEnabled() && pixelMap &&
49         pixelMap->GetAllocatorType() == Media::AllocatorType::SHARE_MEM_ALLOC &&
50         !RSPixelMapUtil::IsYUVFormat(pixelMap) &&
51         !pixelMap->IsEditable() && !pixelMap->IsAstc() && !pixelMap->IsHdr();
52 }
53 #endif
54 }
~RSImageBase()55 RSImageBase::~RSImageBase()
56 {
57     if (pixelMap_) {
58 #ifdef ROSEN_OHOS
59         pixelMap_->DecreaseUseCount();
60 #endif
61         pixelMap_ = nullptr;
62         if (uniqueId_ > 0) {
63             if (renderServiceImage_ || isDrawn_) {
64                 RSImageCache::Instance().CollectUniqueId(uniqueId_);
65             } else {
66                 RSImageCache::Instance().ReleasePixelMapCache(uniqueId_);
67             }
68         }
69 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
70     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
71         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
72         RSTaskDispatcher::GetInstance().PostTask(tid_, [nativeWindowBuffer = nativeWindowBuffer_,
73             cleanupHelper = cleanUpHelper_]() {
74             if (nativeWindowBuffer != nullptr) {
75                 DestroyNativeWindowBuffer(nativeWindowBuffer);
76             }
77             if (cleanupHelper != nullptr) {
78                 NativeBufferUtils::DeleteVkImage(cleanupHelper);
79             }
80         });
81     }
82 #endif
83     } else { // if pixelMap_ not nullptr, do not release skImage cache
84         if (image_) {
85             image_ = nullptr;
86             if (uniqueId_ > 0) {
87                 // if image_ is obtained by RSPixelMapUtil::ExtractSkImage, uniqueId_ here is related to pixelMap,
88                 // image_ is not in SkiaImageCache, but still check it here
89                 // in this case, the cached image_ will be removed when pixelMap cache is removed
90                 RSImageCache::Instance().ReleaseDrawingImageCache(uniqueId_);
91             }
92         }
93     }
94 }
95 
96 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
GetColorTypeWithVKFormat(VkFormat vkFormat)97 Drawing::ColorType GetColorTypeWithVKFormat(VkFormat vkFormat)
98 {
99     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
100         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
101         return Drawing::COLORTYPE_RGBA_8888;
102     }
103     switch (vkFormat) {
104         case VK_FORMAT_R8G8B8A8_UNORM:
105             return Drawing::COLORTYPE_RGBA_8888;
106         case VK_FORMAT_R16G16B16A16_SFLOAT:
107             return Drawing::COLORTYPE_RGBA_F16;
108         case VK_FORMAT_R5G6B5_UNORM_PACK16:
109             return Drawing::COLORTYPE_RGB_565;
110         case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
111             return Drawing::COLORTYPE_RGBA_1010102;
112         default:
113             return Drawing::COLORTYPE_RGBA_8888;
114     }
115 }
116 #endif
117 
DrawImage(Drawing::Canvas & canvas,const Drawing::SamplingOptions & samplingOptions,Drawing::SrcRectConstraint constraint)118 void RSImageBase::DrawImage(Drawing::Canvas& canvas, const Drawing::SamplingOptions& samplingOptions,
119     Drawing::SrcRectConstraint constraint)
120 {
121 #ifdef ROSEN_OHOS
122     auto pixelMapUseCountGuard = PixelMapUseCountGuard(pixelMap_, IsPurgeable());
123     DePurge();
124 #endif
125 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
126     if (pixelMap_ && pixelMap_->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC) {
127         BindPixelMapToDrawingImage(canvas);
128     }
129 #endif
130     if (!image_) {
131         ConvertPixelMapToDrawingImage();
132     }
133     auto src = RSPropertiesPainter::Rect2DrawingRect(srcRect_);
134     auto dst = RSPropertiesPainter::Rect2DrawingRect(dstRect_);
135     if (image_ == nullptr) {
136         RS_LOGE("RSImageBase::DrawImage image_ is nullptr");
137         return;
138     }
139     canvas.DrawImageRect(*image_, src, dst, samplingOptions, constraint);
140 }
141 
DrawImageNine(Drawing::Canvas & canvas,const Drawing::RectI & center,const Drawing::Rect & dst,Drawing::FilterMode filterMode)142 void RSImageBase::DrawImageNine(Drawing::Canvas& canvas, const Drawing::RectI& center, const Drawing::Rect& dst,
143     Drawing::FilterMode filterMode)
144 {
145 #ifdef ROSEN_OHOS
146     auto pixelMapUseCountGuard = PixelMapUseCountGuard(pixelMap_, IsPurgeable());
147     DePurge();
148 #endif
149 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
150     if (pixelMap_ && pixelMap_->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC) {
151         BindPixelMapToDrawingImage(canvas);
152     }
153 #endif
154     if (!image_) {
155         ConvertPixelMapToDrawingImage();
156     }
157     if (image_ == nullptr) {
158         RS_LOGE("RSImageBase::DrawImage image_ is nullptr");
159         return;
160     }
161     canvas.DrawImageNine(image_.get(), center, dst, filterMode, nullptr);
162 }
163 
DrawImageLattice(Drawing::Canvas & canvas,const Drawing::Lattice & lattice,const Drawing::Rect & dst,Drawing::FilterMode filterMode)164 void RSImageBase::DrawImageLattice(Drawing::Canvas& canvas, const Drawing::Lattice& lattice, const Drawing::Rect& dst,
165     Drawing::FilterMode filterMode)
166 {
167 #ifdef ROSEN_OHOS
168     auto pixelMapUseCountGuard = PixelMapUseCountGuard(pixelMap_, IsPurgeable());
169     DePurge();
170 #endif
171 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
172     if (pixelMap_ && pixelMap_->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC) {
173         BindPixelMapToDrawingImage(canvas);
174     }
175 #endif
176     if (!image_) {
177         ConvertPixelMapToDrawingImage();
178     }
179     if (image_ == nullptr) {
180         RS_LOGE("RSImageBase::DrawImage image_ is nullptr");
181         return;
182     }
183     canvas.DrawImageLattice(image_.get(), lattice, dst, filterMode);
184 }
185 
SetImage(const std::shared_ptr<Drawing::Image> image)186 void RSImageBase::SetImage(const std::shared_ptr<Drawing::Image> image)
187 {
188     isDrawn_ = false;
189     image_ = image;
190     if (image_) {
191 #ifndef ROSEN_ARKUI_X
192         SKResourceManager::Instance().HoldResource(image);
193 #endif
194         srcRect_.SetAll(0.0, 0.0, image_->GetWidth(), image_->GetHeight());
195         GenUniqueId(image_->GetUniqueID());
196     }
197 }
198 
199 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
SetDmaImage(const std::shared_ptr<Drawing::Image> image)200 void RSImageBase::SetDmaImage(const std::shared_ptr<Drawing::Image> image)
201 {
202     isDrawn_ = false;
203     image_ = image;
204 }
205 
MarkYUVImage()206 void RSImageBase::MarkYUVImage()
207 {
208     isDrawn_ = false;
209     isYUVImage_ = true;
210     canPurgeShareMemFlag_ = CanPurgeFlag::DISABLED;
211 }
212 #endif
213 
SetPixelMap(const std::shared_ptr<Media::PixelMap> & pixelmap)214 void RSImageBase::SetPixelMap(const std::shared_ptr<Media::PixelMap>& pixelmap)
215 {
216 #ifdef ROSEN_OHOS
217     if (pixelMap_) {
218         pixelMap_->DecreaseUseCount();
219     }
220     if (pixelmap) {
221         pixelmap->IncreaseUseCount();
222     }
223 #endif
224     pixelMap_ = pixelmap;
225     if (pixelMap_) {
226         srcRect_.SetAll(0.0, 0.0, pixelMap_->GetWidth(), pixelMap_->GetHeight());
227         image_ = nullptr;
228         GenUniqueId(pixelMap_->GetUniqueId());
229     }
230 }
231 
DumpPicture(DfxString & info) const232 void RSImageBase::DumpPicture(DfxString& info) const
233 {
234     if (!pixelMap_) {
235         return;
236     }
237     info.AppendFormat("%d    [%d * %d]  %p\n", pixelMap_->GetByteCount(), pixelMap_->GetWidth(), pixelMap_->GetHeight(),
238         pixelMap_.get());
239 }
240 
SetSrcRect(const RectF & srcRect)241 void RSImageBase::SetSrcRect(const RectF& srcRect)
242 {
243     srcRect_ = srcRect;
244 }
245 
SetDstRect(const RectF & dstRect)246 void RSImageBase::SetDstRect(const RectF& dstRect)
247 {
248     if (dstRect_ != dstRect) {
249         isDrawn_ = false;
250     }
251     dstRect_ = dstRect;
252 }
253 
SetImagePixelAddr(void * addr)254 void RSImageBase::SetImagePixelAddr(void* addr)
255 {
256     imagePixelAddr_ = addr;
257     if (imagePixelAddr_) {
258         canPurgeShareMemFlag_ = CanPurgeFlag::DISABLED;
259     }
260 }
261 
UpdateNodeIdToPicture(NodeId nodeId)262 void RSImageBase::UpdateNodeIdToPicture(NodeId nodeId)
263 {
264     if (!nodeId) {
265         return;
266     }
267     if (pixelMap_) {
268 #ifndef ROSEN_ARKUI_X
269 #ifdef ROSEN_OHOS
270     if (RSSystemProperties::GetClosePixelMapFdEnabled()) {
271         MemoryTrack::Instance().UpdatePictureInfo(pixelMap_->GetPixels(), nodeId, ExtractPid(nodeId));
272     } else {
273         MemoryTrack::Instance().UpdatePictureInfo(pixelMap_->GetFd(), nodeId, ExtractPid(nodeId));
274     }
275 #else
276         MemoryTrack::Instance().UpdatePictureInfo(pixelMap_->GetPixels(), nodeId, ExtractPid(nodeId));
277 #endif
278 #endif
279     }
280     if (image_ || imagePixelAddr_) {
281 #ifndef ROSEN_ARKUI_X
282         MemoryTrack::Instance().UpdatePictureInfo(imagePixelAddr_, nodeId, ExtractPid(nodeId));
283 #endif
284     }
285 }
286 
Purge()287 void RSImageBase::Purge()
288 {
289 #ifdef ROSEN_OHOS
290     if (canPurgeShareMemFlag_ != CanPurgeFlag::ENABLED ||
291         uniqueId_ <= 0 || !pixelMap_ || pixelMap_->IsUnMap()) {
292         return;
293     }
294 
295     constexpr int USE_COUNT_FOR_PURGE = 2; // one in this RSImage, one in RSImageCache
296     auto imageUseCount = image_.use_count();
297     auto pixelMapCount = pixelMap_.use_count();
298     if (!(imageUseCount == USE_COUNT_FOR_PURGE && pixelMapCount == USE_COUNT_FOR_PURGE + 1) &&
299         !(imageUseCount == 0 && pixelMapCount == USE_COUNT_FOR_PURGE)) {
300         return;
301     }
302     // skip purge if multi RsImage Holds this PixelMap
303     if (!RSImageCache::Instance().CheckRefCntAndReleaseImageCache(uniqueId_, pixelMap_)) {
304         return;
305     }
306     isDrawn_ = false;
307     image_ = nullptr;
308     bool unmapResult = pixelMap_->UnMap();
309     if (unmapResult && pixelMap_.use_count() > USE_COUNT_FOR_PURGE) {
310         RS_LOGW("UNMAP_LOG Purge while use_count > USE_COUNT_FOR_PURGE");
311     }
312 #endif
313 }
314 
DePurge()315 void RSImageBase::DePurge()
316 {
317 #ifdef ROSEN_OHOS
318     if (canPurgeShareMemFlag_ != CanPurgeFlag::ENABLED ||
319         uniqueId_ <= 0 || !pixelMap_ || !pixelMap_->IsUnMap()) {
320         return;
321     }
322     if (image_ != nullptr) {
323         RS_LOGW("UNMAP_LOG Image is not reset when PixelMap is unmap");
324         isDrawn_ = false;
325         image_ = nullptr;
326     }
327     pixelMap_->ReMap();
328 #endif
329 }
330 
MarkRenderServiceImage()331 void RSImageBase::MarkRenderServiceImage()
332 {
333     renderServiceImage_ = true;
334 }
335 
MarkPurgeable()336 void RSImageBase::MarkPurgeable()
337 {
338 #ifdef ROSEN_OHOS
339     if (renderServiceImage_ && canPurgeShareMemFlag_ == CanPurgeFlag::UNINITED && PixelMapCanBePurge(pixelMap_)) {
340         canPurgeShareMemFlag_ = CanPurgeFlag::ENABLED;
341     }
342 #endif
343 }
344 
IsPurgeable() const345 bool RSImageBase::IsPurgeable() const
346 {
347     return canPurgeShareMemFlag_ == CanPurgeFlag::ENABLED;
348 }
349 
350 #ifdef ROSEN_OHOS
UnmarshallingAndCacheDrawingImage(Parcel & parcel,std::shared_ptr<Drawing::Image> & img,uint64_t uniqueId,void * & imagepixelAddr)351 static bool UnmarshallingAndCacheDrawingImage(
352     Parcel& parcel, std::shared_ptr<Drawing::Image>& img, uint64_t uniqueId, void*& imagepixelAddr)
353 {
354     if (img != nullptr) {
355         // match a cached SkImage
356         if (!RSMarshallingHelper::SkipImage(parcel)) {
357             RS_LOGE("UnmarshalAndCacheSkImage SkipSkImage fail");
358             return false;
359         }
360     } else if (RSMarshallingHelper::Unmarshalling(parcel, img, imagepixelAddr)) {
361         // unmarshalling the SkImage and cache it
362         RSImageCache::Instance().CacheDrawingImage(uniqueId, img);
363     } else {
364         RS_LOGE("UnmarshalAndCacheSkImage fail");
365         return false;
366     }
367     return true;
368 }
369 
370 
UnmarshallingAndCachePixelMap(Parcel & parcel,std::shared_ptr<Media::PixelMap> & pixelMap,uint64_t uniqueId,uint32_t versionId)371 static bool UnmarshallingAndCachePixelMap(Parcel& parcel, std::shared_ptr<Media::PixelMap>& pixelMap,
372     uint64_t uniqueId, uint32_t versionId)
373 {
374     if (pixelMap != nullptr) {
375         // match a cached pixelMap
376         if (versionId == pixelMap->GetVersionId()) {
377             if (!RSMarshallingHelper::SkipPixelMap(parcel)) {
378                 return false;
379             }
380         } else {
381             RSImageCache::Instance().ReleasePixelMapCache(uniqueId);
382             if (!RSMarshallingHelper::Unmarshalling(parcel, pixelMap)) {
383                 return false;
384             }
385             // unmarshalling the pixelmap and cache it
386             RSImageCache::Instance().CachePixelMap(uniqueId, pixelMap);
387         }
388     } else if (RSMarshallingHelper::Unmarshalling(parcel, pixelMap)) {
389         if (pixelMap) {
390             // unmarshalling the pixelMap and cache it
391             RSImageCache::Instance().CachePixelMap(uniqueId, pixelMap);
392         }
393     } else {
394         return false;
395     }
396     return true;
397 }
398 
UnmarshallingIdAndRect(Parcel & parcel,uint64_t & uniqueId,RectF & srcRect,RectF & dstRect)399 static bool UnmarshallingIdAndRect(Parcel& parcel, uint64_t& uniqueId, RectF& srcRect, RectF& dstRect)
400 {
401     if (!RSMarshallingHelper::Unmarshalling(parcel, uniqueId)) {
402         RS_LOGE("RSImage::Unmarshalling uniqueId fail");
403         return false;
404     }
405     RS_PROFILER_PATCH_NODE_ID(parcel, uniqueId);
406     if (!RSMarshallingHelper::Unmarshalling(parcel, srcRect)) {
407         RS_LOGE("RSImage::Unmarshalling srcRect fail");
408         return false;
409     }
410     if (!RSMarshallingHelper::Unmarshalling(parcel, dstRect)) {
411         RS_LOGE("RSImage::Unmarshalling dstRect fail");
412         return false;
413     }
414     return true;
415 }
416 
UnmarshallingDrawingImageAndPixelMap(Parcel & parcel,uint64_t uniqueId,bool & useSkImage,std::shared_ptr<Drawing::Image> & img,std::shared_ptr<Media::PixelMap> & pixelMap,void * & imagepixelAddr)417 bool RSImageBase::UnmarshallingDrawingImageAndPixelMap(Parcel& parcel, uint64_t uniqueId, bool& useSkImage,
418     std::shared_ptr<Drawing::Image>& img, std::shared_ptr<Media::PixelMap>& pixelMap, void*& imagepixelAddr)
419 {
420     if (!RSMarshallingHelper::Unmarshalling(parcel, useSkImage)) {
421         return false;
422     }
423     uint32_t versionId = 0;
424     if (!RSMarshallingHelper::Unmarshalling(parcel, versionId)) {
425         return false;
426     }
427     if (useSkImage) {
428         img = RSImageCache::Instance().GetDrawingImageCache(uniqueId);
429         RS_TRACE_NAME_FMT("RSImageBase::Unmarshalling Image uniqueId:%lu, size:[%d %d], cached:%d",
430             uniqueId, img ? img->GetWidth() : 0, img ? img->GetHeight() : 0, img != nullptr);
431         if (!UnmarshallingAndCacheDrawingImage(parcel, img, uniqueId, imagepixelAddr)) {
432             RS_LOGE("RSImageBase::Unmarshalling UnmarshalAndCacheSkImage fail");
433             return false;
434         }
435         RSMarshallingHelper::SkipPixelMap(parcel);
436     } else {
437         if (!RSMarshallingHelper::SkipImage(parcel)) {
438             return false;
439         }
440         pixelMap = RSImageCache::Instance().GetPixelMapCache(uniqueId);
441         RS_TRACE_NAME_FMT("RSImageBase::Unmarshalling pixelMap uniqueId:%lu, size:[%d %d], cached:%d",
442             uniqueId, pixelMap ? pixelMap->GetWidth() : 0, pixelMap ? pixelMap->GetHeight() : 0, pixelMap != nullptr);
443         if (!UnmarshallingAndCachePixelMap(parcel, pixelMap, uniqueId, versionId)) {
444             RS_LOGE("RSImageBase::Unmarshalling UnmarshalAndCachePixelMap fail");
445             return false;
446         }
447     }
448     return true;
449 }
450 
IncreaseCacheRefCount(uint64_t uniqueId,bool useSkImage,std::shared_ptr<Media::PixelMap> pixelMap)451 void RSImageBase::IncreaseCacheRefCount(uint64_t uniqueId, bool useSkImage, std::shared_ptr<Media::PixelMap>
452     pixelMap)
453 {
454     if (useSkImage) {
455         RSImageCache::Instance().IncreaseDrawingImageCacheRefCount(uniqueId);
456     } else if (pixelMap) {
457         RSImageCache::Instance().IncreasePixelMapCacheRefCount(uniqueId);
458     }
459 }
460 
Marshalling(Parcel & parcel) const461 bool RSImageBase::Marshalling(Parcel& parcel) const
462 {
463     std::lock_guard<std::mutex> lock(mutex_);
464     uint32_t versionId = pixelMap_ == nullptr ? 0 : pixelMap_->GetVersionId();
465     bool success = RSMarshallingHelper::Marshalling(parcel, uniqueId_) &&
466                    RSMarshallingHelper::Marshalling(parcel, srcRect_) &&
467                    RSMarshallingHelper::Marshalling(parcel, dstRect_) &&
468                    parcel.WriteBool(pixelMap_ == nullptr) &&
469                    RSMarshallingHelper::Marshalling(parcel, versionId) &&
470                    RSMarshallingHelper::Marshalling(parcel, image_) &&
471                    RSMarshallingHelper::Marshalling(parcel, pixelMap_);
472     if (!success) {
473         RS_LOGE("RSImageBase::Marshalling parcel fail");
474     }
475     return success;
476 }
477 
Unmarshalling(Parcel & parcel)478 RSImageBase* RSImageBase::Unmarshalling(Parcel& parcel)
479 {
480     uint64_t uniqueId;
481     RectF srcRect;
482     RectF dstRect;
483     if (!UnmarshallingIdAndRect(parcel, uniqueId, srcRect, dstRect)) {
484         RS_LOGE("RSImage::Unmarshalling UnmarshalIdAndSize fail");
485         return nullptr;
486     }
487 
488     bool useSkImage;
489     std::shared_ptr<Drawing::Image> img = std::make_shared<Drawing::Image>();
490     std::shared_ptr<Media::PixelMap> pixelMap;
491     void* imagepixelAddr = nullptr;
492     if (!UnmarshallingDrawingImageAndPixelMap(parcel, uniqueId, useSkImage, img, pixelMap, imagepixelAddr)) {
493         return nullptr;
494     }
495 
496     RSImageBase* rsImage = new RSImageBase();
497     rsImage->SetImage(img);
498     rsImage->SetImagePixelAddr(imagepixelAddr);
499     rsImage->SetPixelMap(pixelMap);
500     rsImage->SetSrcRect(srcRect);
501     rsImage->SetDstRect(dstRect);
502     rsImage->uniqueId_ = uniqueId;
503     rsImage->MarkRenderServiceImage();
504     IncreaseCacheRefCount(uniqueId, useSkImage, pixelMap);
505     return rsImage;
506 }
507 #endif
508 
ConvertPixelMapToDrawingImage(bool paraUpload)509 void RSImageBase::ConvertPixelMapToDrawingImage(bool paraUpload)
510 {
511 #if defined(ROSEN_OHOS)
512     // paraUpload only enable in render_service or UnmarshalThread
513     pid_t tid = paraUpload ? getpid() : gettid();
514 #endif
515     if (!image_ && pixelMap_ && !pixelMap_->IsAstc() && !isYUVImage_) {
516 #if defined(ROSEN_OHOS)
517             image_ = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_, tid);
518 #else
519             image_ = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_);
520 #endif
521         if (!image_) {
522             image_ = RSPixelMapUtil::ExtractDrawingImage(pixelMap_);
523 #if defined(ROSEN_OHOS)
524             RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image_, tid);
525 #else
526             RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image_);
527 #endif
528 #ifdef RS_ENABLE_PARALLEL_UPLOAD
529             RSResourceManager::Instance().UploadTexture(paraUpload && renderServiceImage_, image_,
530                 pixelMap_, uniqueId_);
531 #endif
532         }
533     }
534 }
535 
GetUniqueId() const536 uint64_t RSImageBase::GetUniqueId() const
537 {
538     return uniqueId_;
539 }
540 
GenUniqueId(uint32_t id)541 void RSImageBase::GenUniqueId(uint32_t id)
542 {
543     static uint64_t shiftedPid = static_cast<uint64_t>(GetRealPid()) << 32; // 32 for 64-bit unsignd number shift
544     uniqueId_ = shiftedPid | id;
545 }
546 
547 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
ProcessYUVImage(std::shared_ptr<Drawing::GPUContext> gpuContext)548 void RSImageBase::ProcessYUVImage(std::shared_ptr<Drawing::GPUContext> gpuContext)
549 {
550     if (!gpuContext) {
551         return;
552     }
553     auto cache = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_, gettid());
554     std::lock_guard<std::mutex> lock(mutex_);
555     if (cache) {
556         image_ = cache;
557         return;
558     }
559     RS_TRACE_NAME("make yuv img");
560     auto image = RSPixelMapUtil::ConvertYUVPixelMapToDrawingImage(gpuContext, pixelMap_);
561     if (image) {
562         image_ = image;
563         SKResourceManager::Instance().HoldResource(image);
564         RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image, gettid());
565     } else {
566         RS_LOGE("make yuv image %{public}d (%{public}d, %{public}d) failed",
567             (int)uniqueId_, (int)srcRect_.width_, (int)srcRect_.height_);
568     }
569 }
570 #endif
571 
GetPixelMap() const572 std::shared_ptr<Media::PixelMap> RSImageBase::GetPixelMap() const
573 {
574     return pixelMap_;
575 }
576 
577 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
MakeFromTextureForVK(Drawing::Canvas & canvas,SurfaceBuffer * surfaceBuffer)578 std::shared_ptr<Drawing::Image> RSImageBase::MakeFromTextureForVK(
579     Drawing::Canvas& canvas, SurfaceBuffer* surfaceBuffer)
580 {
581     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
582         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
583         return nullptr;
584     }
585     if (!surfaceBuffer || !canvas.GetGPUContext()) {
586         RS_LOGE("RSImageBase MakeFromTextureForVK surfaceBuffer is nullptr");
587         return nullptr;
588     }
589     if (nativeWindowBuffer_ == nullptr) {
590         sptr<SurfaceBuffer> sfBuffer(surfaceBuffer);
591         nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&sfBuffer);
592         if (!nativeWindowBuffer_) {
593             RS_LOGE("RSImageBase MakeFromTextureForVK create native window buffer fail");
594             return nullptr;
595         }
596     }
597     if (!backendTexture_.IsValid()) {
598         backendTexture_ = NativeBufferUtils::MakeBackendTextureFromNativeBuffer(
599             nativeWindowBuffer_, surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight(), false);
600         if (backendTexture_.IsValid()) {
601             auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
602             cleanUpHelper_ = new NativeBufferUtils::VulkanCleanupHelper(
603                 RsVulkanContext::GetSingleton(), vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory);
604         } else {
605             return nullptr;
606         }
607         tid_ = gettid();
608     }
609 
610     std::shared_ptr<Drawing::Image> dmaImage = std::make_shared<Drawing::Image>();
611     auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
612     Drawing::ColorType colorType = GetColorTypeWithVKFormat(vkTextureInfo->format);
613     Drawing::BitmapFormat bitmapFormat = { colorType, Drawing::AlphaType::ALPHATYPE_PREMUL };
614     if (!dmaImage->BuildFromTexture(*canvas.GetGPUContext(), backendTexture_.GetTextureInfo(),
615         Drawing::TextureOrigin::TOP_LEFT, bitmapFormat, nullptr, NativeBufferUtils::DeleteVkImage,
616         cleanUpHelper_->Ref())) {
617         RS_LOGE("RSImageBase MakeFromTextureForVK build image failed");
618         return nullptr;
619     }
620     return dmaImage;
621 }
622 
BindPixelMapToDrawingImage(Drawing::Canvas & canvas)623 void RSImageBase::BindPixelMapToDrawingImage(Drawing::Canvas& canvas)
624 {
625     if (pixelMap_ && !pixelMap_->IsAstc()) {
626         std::shared_ptr<Drawing::Image> imageCache = nullptr;
627         if (!pixelMap_->IsEditable()) {
628             imageCache = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_, gettid());
629         }
630         if (imageCache) {
631             image_ = imageCache;
632         } else {
633             image_ = MakeFromTextureForVK(canvas, reinterpret_cast<SurfaceBuffer*>(pixelMap_->GetFd()));
634             if (image_) {
635                 SKResourceManager::Instance().HoldResource(image_);
636                 RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image_, gettid());
637             }
638         }
639     }
640 }
641 #endif
642 
643 #ifdef ROSEN_OHOS
PixelMapUseCountGuard(std::shared_ptr<Media::PixelMap> pixelMap,bool purgeable)644 RSImageBase::PixelMapUseCountGuard::PixelMapUseCountGuard(std::shared_ptr<Media::PixelMap> pixelMap, bool purgeable)
645     : pixelMap_(pixelMap), purgeable_(purgeable)
646 {
647     if (purgeable_) {
648         pixelMap_->IncreaseUseCount();
649     }
650 }
651 
~PixelMapUseCountGuard()652 RSImageBase::PixelMapUseCountGuard::~PixelMapUseCountGuard()
653 {
654     if (purgeable_) {
655         pixelMap_->DecreaseUseCount();
656     }
657 }
658 #endif
659 }
660