• 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 #include "common/rs_common_def.h"
23 #ifdef RS_MEMORY_INFO_MANAGER
24 #include "feature/memory_info_manager/rs_memory_info_manager.h"
25 #endif
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 #ifdef SUBTREE_PARALLEL_ENABLE
37 #include "rs_parallel_misc.h"
38 #endif
39 
40 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
41 #include "native_buffer_inner.h"
42 #include "native_window.h"
43 #include "platform/ohos/backend/native_buffer_utils.h"
44 #include "platform/ohos/backend/rs_vulkan_context.h"
45 #endif
46 namespace OHOS::Rosen {
47 namespace {
48 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_VK) || defined(RS_ENABLE_GL))
49 constexpr uint8_t ASTC_HEADER_SIZE = 16;
50 #endif
51 #ifdef ROSEN_OHOS
PixelMapCanBePurge(std::shared_ptr<Media::PixelMap> & pixelMap)52 bool PixelMapCanBePurge(std::shared_ptr<Media::PixelMap>& pixelMap)
53 {
54     return RSSystemProperties::GetRSImagePurgeEnabled() && pixelMap &&
55         pixelMap->GetAllocatorType() == Media::AllocatorType::SHARE_MEM_ALLOC &&
56         !RSPixelMapUtil::IsYUVFormat(pixelMap) &&
57         !pixelMap->IsEditable() && !pixelMap->IsAstc() && !pixelMap->IsHdr();
58 }
59 #endif
60 }
~RSImageBase()61 RSImageBase::~RSImageBase()
62 {
63     if (pixelMap_) {
64 #ifdef ROSEN_OHOS
65         pixelMap_->DecreaseUseCount();
66 #endif
67         pixelMap_ = nullptr;
68         if (uniqueId_ > 0) {
69             if (renderServiceImage_ || isDrawn_) {
70                 RSImageCache::Instance().CollectUniqueId(uniqueId_);
71             } else {
72                 RSImageCache::Instance().ReleasePixelMapCache(uniqueId_);
73             }
74         }
75 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
76     if (RSSystemProperties::IsUseVulkan()) {
77         pid_t targetTid = RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR ? 0 : tid_;
78         RSTaskDispatcher::GetInstance().PostTask(targetTid, [nativeWindowBuffer = nativeWindowBuffer_,
79             cleanupHelper = cleanUpHelper_]() {
80             if (nativeWindowBuffer != nullptr) {
81                 DestroyNativeWindowBuffer(nativeWindowBuffer);
82             }
83             if (cleanupHelper != nullptr) {
84                 NativeBufferUtils::DeleteVkImage(cleanupHelper);
85             }
86         });
87     }
88 #endif
89     } else { // if pixelMap_ not nullptr, do not release skImage cache
90         if (image_) {
91             image_ = nullptr;
92             if (uniqueId_ > 0) {
93                 // if image_ is obtained by RSPixelMapUtil::ExtractSkImage, uniqueId_ here is related to pixelMap,
94                 // image_ is not in SkiaImageCache, but still check it here
95                 // in this case, the cached image_ will be removed when pixelMap cache is removed
96                 RSImageCache::Instance().ReleaseDrawingImageCache(uniqueId_);
97             }
98         }
99     }
100 }
101 
102 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
GetColorTypeWithVKFormat(VkFormat vkFormat)103 Drawing::ColorType GetColorTypeWithVKFormat(VkFormat vkFormat)
104 {
105     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
106         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
107         return Drawing::COLORTYPE_RGBA_8888;
108     }
109     switch (vkFormat) {
110         case VK_FORMAT_R8G8B8A8_UNORM:
111             return Drawing::COLORTYPE_RGBA_8888;
112         case VK_FORMAT_R16G16B16A16_SFLOAT:
113             return Drawing::COLORTYPE_RGBA_F16;
114         case VK_FORMAT_R5G6B5_UNORM_PACK16:
115             return Drawing::COLORTYPE_RGB_565;
116         case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
117             return Drawing::COLORTYPE_RGBA_1010102;
118         default:
119             return Drawing::COLORTYPE_RGBA_8888;
120     }
121 }
122 #endif
123 
DrawImage(Drawing::Canvas & canvas,const Drawing::SamplingOptions & samplingOptions,Drawing::SrcRectConstraint constraint)124 void RSImageBase::DrawImage(Drawing::Canvas& canvas, const Drawing::SamplingOptions& samplingOptions,
125     Drawing::SrcRectConstraint constraint)
126 {
127 #ifdef ROSEN_OHOS
128     auto pixelMapUseCountGuard = PixelMapUseCountGuard(pixelMap_, IsPurgeable());
129     DePurge();
130 #endif
131 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
132     if (pixelMap_ && pixelMap_->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC && !pixelMap_->IsAstc()) {
133         BindPixelMapToDrawingImage(canvas);
134     }
135     if (pixelMap_ && pixelMap_->IsAstc()) {
136         SetCompressedDataForASTC();
137         UploadGpu(canvas);
138     }
139 #endif
140     if (!image_) {
141         ConvertPixelMapToDrawingImage();
142     }
143     auto src = RSPropertiesPainter::Rect2DrawingRect(srcRect_);
144     auto dst = RSPropertiesPainter::Rect2DrawingRect(dstRect_);
145     if (image_ == nullptr) {
146         RS_LOGE("RSImageBase::DrawImage image_ is nullptr");
147         return;
148     }
149     canvas.DrawImageRect(*image_, src, dst, samplingOptions, constraint);
150 }
151 
DrawImageNine(Drawing::Canvas & canvas,const Drawing::RectI & center,const Drawing::Rect & dst,Drawing::FilterMode filterMode)152 void RSImageBase::DrawImageNine(Drawing::Canvas& canvas, const Drawing::RectI& center, const Drawing::Rect& dst,
153     Drawing::FilterMode filterMode)
154 {
155 #ifdef ROSEN_OHOS
156     auto pixelMapUseCountGuard = PixelMapUseCountGuard(pixelMap_, IsPurgeable());
157     DePurge();
158 #endif
159 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
160     if (pixelMap_ && pixelMap_->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC) {
161         BindPixelMapToDrawingImage(canvas);
162     }
163 #endif
164     if (!image_) {
165         ConvertPixelMapToDrawingImage();
166     }
167     if (image_ == nullptr) {
168         RS_LOGE("RSImageBase::DrawImage image_ is nullptr");
169         return;
170     }
171     canvas.DrawImageNine(image_.get(), center, dst, filterMode, nullptr);
172 }
173 
DrawImageLattice(Drawing::Canvas & canvas,const Drawing::Lattice & lattice,const Drawing::Rect & dst,Drawing::FilterMode filterMode)174 void RSImageBase::DrawImageLattice(Drawing::Canvas& canvas, const Drawing::Lattice& lattice, const Drawing::Rect& dst,
175     Drawing::FilterMode filterMode)
176 {
177 #ifdef ROSEN_OHOS
178     auto pixelMapUseCountGuard = PixelMapUseCountGuard(pixelMap_, IsPurgeable());
179     DePurge();
180 #endif
181 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
182     if (pixelMap_ && pixelMap_->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC) {
183         BindPixelMapToDrawingImage(canvas);
184     }
185 #endif
186     if (!image_) {
187         ConvertPixelMapToDrawingImage();
188     }
189     if (image_ == nullptr) {
190         RS_LOGE("RSImageBase::DrawImage image_ is nullptr");
191         return;
192     }
193     canvas.DrawImageLattice(image_.get(), lattice, dst, filterMode);
194 }
195 
SetImage(const std::shared_ptr<Drawing::Image> image)196 void RSImageBase::SetImage(const std::shared_ptr<Drawing::Image> image)
197 {
198     isDrawn_ = false;
199     image_ = image;
200     if (image_) {
201 #ifndef ROSEN_ARKUI_X
202         SKResourceManager::Instance().HoldResource(image);
203 #endif
204         srcRect_.SetAll(0.0, 0.0, image_->GetWidth(), image_->GetHeight());
205         GenUniqueId(image_->GetUniqueID());
206     }
207 }
208 
209 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
SetDmaImage(const std::shared_ptr<Drawing::Image> image)210 void RSImageBase::SetDmaImage(const std::shared_ptr<Drawing::Image> image)
211 {
212     isDrawn_ = false;
213     image_ = image;
214 }
215 
MarkYUVImage()216 void RSImageBase::MarkYUVImage()
217 {
218     isDrawn_ = false;
219     isYUVImage_ = true;
220     canPurgeShareMemFlag_ = CanPurgeFlag::DISABLED;
221 }
222 #endif
223 
SetPixelMap(const std::shared_ptr<Media::PixelMap> & pixelmap)224 void RSImageBase::SetPixelMap(const std::shared_ptr<Media::PixelMap>& pixelmap)
225 {
226 #ifdef ROSEN_OHOS
227     if (pixelMap_) {
228         pixelMap_->DecreaseUseCount();
229     }
230     if (pixelmap) {
231         pixelmap->IncreaseUseCount();
232     }
233 #endif
234     pixelMap_ = pixelmap;
235     if (pixelMap_) {
236         srcRect_.SetAll(0.0, 0.0, pixelMap_->GetWidth(), pixelMap_->GetHeight());
237         image_ = nullptr;
238         GenUniqueId(pixelMap_->GetUniqueId());
239     }
240 }
241 
DumpPicture(DfxString & info) const242 void RSImageBase::DumpPicture(DfxString& info) const
243 {
244     if (!pixelMap_) {
245         return;
246     }
247     info.AppendFormat("%d    [%d * %d]  %p\n", pixelMap_->GetByteCount(), pixelMap_->GetWidth(), pixelMap_->GetHeight(),
248         pixelMap_.get());
249 }
250 
SetSrcRect(const RectF & srcRect)251 void RSImageBase::SetSrcRect(const RectF& srcRect)
252 {
253     srcRect_ = srcRect;
254 }
255 
SetDstRect(const RectF & dstRect)256 void RSImageBase::SetDstRect(const RectF& dstRect)
257 {
258     if (dstRect_ != dstRect) {
259         isDrawn_ = false;
260     }
261     dstRect_ = dstRect;
262 }
263 
SetImagePixelAddr(void * addr)264 void RSImageBase::SetImagePixelAddr(void* addr)
265 {
266     imagePixelAddr_ = addr;
267     if (imagePixelAddr_) {
268         canPurgeShareMemFlag_ = CanPurgeFlag::DISABLED;
269     }
270 }
271 
UpdateNodeIdToPicture(NodeId nodeId)272 void RSImageBase::UpdateNodeIdToPicture(NodeId nodeId)
273 {
274     if (!nodeId) {
275         return;
276     }
277     if (pixelMap_) {
278 #ifndef ROSEN_ARKUI_X
279 #ifdef ROSEN_OHOS
280     if (RSSystemProperties::GetClosePixelMapFdEnabled()) {
281         MemoryTrack::Instance().UpdatePictureInfo(pixelMap_->GetPixels(), nodeId, ExtractPid(nodeId));
282     } else {
283         MemoryTrack::Instance().UpdatePictureInfo(pixelMap_->GetFd(), nodeId, ExtractPid(nodeId));
284     }
285 #else
286         MemoryTrack::Instance().UpdatePictureInfo(pixelMap_->GetPixels(), nodeId, ExtractPid(nodeId));
287 #endif
288 #endif
289     }
290     if (image_ || imagePixelAddr_) {
291 #ifndef ROSEN_ARKUI_X
292         MemoryTrack::Instance().UpdatePictureInfo(imagePixelAddr_, nodeId, ExtractPid(nodeId));
293 #endif
294     }
295 }
296 
Purge()297 void RSImageBase::Purge()
298 {
299 #ifdef ROSEN_OHOS
300 #ifdef RS_MEMORY_INFO_MANAGER
301     RSMemoryInfoManager::SetImageMemoryInfo(pixelMap_);
302 #endif
303     if (canPurgeShareMemFlag_ != CanPurgeFlag::ENABLED ||
304         uniqueId_ <= 0 || !pixelMap_ || pixelMap_->IsUnMap()) {
305         return;
306     }
307 
308     constexpr int USE_COUNT_FOR_PURGE = 2; // one in this RSImage, one in RSImageCache
309     auto imageUseCount = image_.use_count();
310     auto pixelMapCount = pixelMap_.use_count();
311     if (imageUseCount > USE_COUNT_FOR_PURGE || imageUseCount == 1 ||
312         (imageUseCount == 0 && pixelMapCount > USE_COUNT_FOR_PURGE) ||
313         (imageUseCount == USE_COUNT_FOR_PURGE && pixelMapCount > USE_COUNT_FOR_PURGE + 1)) {
314         return;
315     }
316     // skip purge if multi RsImage Holds this PixelMap
317     if (!RSImageCache::Instance().CheckRefCntAndReleaseImageCache(uniqueId_, pixelMap_)) {
318         return;
319     }
320     isDrawn_ = false;
321     image_ = nullptr;
322     bool unmapResult = pixelMap_->UnMap();
323     if (unmapResult && pixelMap_.use_count() > USE_COUNT_FOR_PURGE) {
324         RS_LOGW("UNMAP_LOG Purge while use_count > USE_COUNT_FOR_PURGE");
325     }
326 #endif
327 }
328 
DePurge()329 void RSImageBase::DePurge()
330 {
331 #ifdef ROSEN_OHOS
332 #ifdef RS_MEMORY_INFO_MANAGER
333     RSMemoryInfoManager::SetImageMemoryInfo(pixelMap_);
334 #endif
335     if (canPurgeShareMemFlag_ != CanPurgeFlag::ENABLED ||
336         uniqueId_ <= 0 || !pixelMap_ || !pixelMap_->IsUnMap()) {
337         return;
338     }
339     if (image_ != nullptr) {
340         RS_LOGW("UNMAP_LOG Image is not reset when PixelMap is unmap");
341         isDrawn_ = false;
342         image_ = nullptr;
343     }
344     pixelMap_->ReMap();
345 #endif
346 }
347 
MarkRenderServiceImage()348 void RSImageBase::MarkRenderServiceImage()
349 {
350     renderServiceImage_ = true;
351 }
352 
MarkPurgeable()353 void RSImageBase::MarkPurgeable()
354 {
355 #ifdef ROSEN_OHOS
356     if (renderServiceImage_ && canPurgeShareMemFlag_ == CanPurgeFlag::UNINITED && PixelMapCanBePurge(pixelMap_)) {
357         canPurgeShareMemFlag_ = CanPurgeFlag::ENABLED;
358     }
359 #endif
360 }
361 
IsPurgeable() const362 bool RSImageBase::IsPurgeable() const
363 {
364     return canPurgeShareMemFlag_ == CanPurgeFlag::ENABLED;
365 }
366 
367 #ifdef ROSEN_OHOS
UnmarshallingAndCacheDrawingImage(Parcel & parcel,std::shared_ptr<Drawing::Image> & img,uint64_t uniqueId,void * & imagepixelAddr)368 static bool UnmarshallingAndCacheDrawingImage(
369     Parcel& parcel, std::shared_ptr<Drawing::Image>& img, uint64_t uniqueId, void*& imagepixelAddr)
370 {
371     if (img != nullptr) {
372         // match a cached SkImage
373         if (!RSMarshallingHelper::SkipImage(parcel)) {
374             RS_LOGE("UnmarshalAndCacheSkImage SkipSkImage fail");
375             return false;
376         }
377     } else if (RSMarshallingHelper::Unmarshalling(parcel, img, imagepixelAddr)) {
378         // unmarshalling the SkImage and cache it
379         RSImageCache::Instance().CacheDrawingImage(uniqueId, img);
380     } else {
381         RS_LOGE("UnmarshalAndCacheSkImage fail");
382         return false;
383     }
384     return true;
385 }
386 
387 
UnmarshallingAndCachePixelMap(Parcel & parcel,std::shared_ptr<Media::PixelMap> & pixelMap,uint64_t uniqueId,uint32_t versionId)388 static bool UnmarshallingAndCachePixelMap(Parcel& parcel, std::shared_ptr<Media::PixelMap>& pixelMap,
389     uint64_t uniqueId, uint32_t versionId)
390 {
391     if (pixelMap != nullptr) {
392         // match a cached pixelMap
393         if (versionId == pixelMap->GetVersionId()) {
394             if (!RSMarshallingHelper::SkipPixelMap(parcel)) {
395                 return false;
396             }
397         } else {
398             RSImageCache::Instance().ReleasePixelMapCache(uniqueId);
399             if (!RSMarshallingHelper::Unmarshalling(parcel, pixelMap)) {
400                 return false;
401             }
402             // unmarshalling the pixelmap and cache it
403             RSImageCache::Instance().CachePixelMap(uniqueId, pixelMap);
404         }
405     } else if (RSMarshallingHelper::Unmarshalling(parcel, pixelMap)) {
406         if (pixelMap) {
407             // unmarshalling the pixelMap and cache it
408             RSImageCache::Instance().CachePixelMap(uniqueId, pixelMap);
409         }
410     } else {
411         return false;
412     }
413     return true;
414 }
415 
UnmarshallingIdAndRect(Parcel & parcel,uint64_t & uniqueId,RectF & srcRect,RectF & dstRect)416 static bool UnmarshallingIdAndRect(Parcel& parcel, uint64_t& uniqueId, RectF& srcRect, RectF& dstRect)
417 {
418     if (!RSMarshallingHelper::UnmarshallingPidPlusId(parcel, uniqueId)) {
419         RS_LOGE("RSImage::Unmarshalling uniqueId fail");
420         return false;
421     }
422     if (!RSMarshallingHelper::Unmarshalling(parcel, srcRect)) {
423         RS_LOGE("RSImage::Unmarshalling srcRect fail");
424         return false;
425     }
426     if (!RSMarshallingHelper::Unmarshalling(parcel, dstRect)) {
427         RS_LOGE("RSImage::Unmarshalling dstRect fail");
428         return false;
429     }
430     return true;
431 }
432 
UnmarshallingDrawingImageAndPixelMap(Parcel & parcel,uint64_t uniqueId,bool & useSkImage,std::shared_ptr<Drawing::Image> & img,std::shared_ptr<Media::PixelMap> & pixelMap,void * & imagepixelAddr)433 bool RSImageBase::UnmarshallingDrawingImageAndPixelMap(Parcel& parcel, uint64_t uniqueId, bool& useSkImage,
434     std::shared_ptr<Drawing::Image>& img, std::shared_ptr<Media::PixelMap>& pixelMap, void*& imagepixelAddr)
435 {
436     if (!RSMarshallingHelper::Unmarshalling(parcel, useSkImage)) {
437         return false;
438     }
439     uint32_t versionId = 0;
440     if (!RSMarshallingHelper::Unmarshalling(parcel, versionId)) {
441         return false;
442     }
443     if (useSkImage) {
444         img = RSImageCache::Instance().GetDrawingImageCache(uniqueId);
445         RS_TRACE_NAME_FMT("RSImageBase::Unmarshalling Image uniqueId:%lu, size:[%d %d], cached:%d",
446             uniqueId, img ? img->GetWidth() : 0, img ? img->GetHeight() : 0, img != nullptr);
447         if (!UnmarshallingAndCacheDrawingImage(parcel, img, uniqueId, imagepixelAddr)) {
448             RS_LOGE("RSImageBase::Unmarshalling UnmarshalAndCacheSkImage fail");
449             return false;
450         }
451         RSMarshallingHelper::SkipPixelMap(parcel);
452     } else {
453         if (!RSMarshallingHelper::SkipImage(parcel)) {
454             return false;
455         }
456         pixelMap = RSImageCache::Instance().GetPixelMapCache(uniqueId);
457         RS_TRACE_NAME_FMT("RSImageBase::Unmarshalling pixelMap uniqueId:%lu, size:[%d %d], cached:%d",
458             uniqueId, pixelMap ? pixelMap->GetWidth() : 0, pixelMap ? pixelMap->GetHeight() : 0, pixelMap != nullptr);
459         if (!UnmarshallingAndCachePixelMap(parcel, pixelMap, uniqueId, versionId)) {
460             RS_LOGE("RSImageBase::Unmarshalling UnmarshalAndCachePixelMap fail");
461             return false;
462         }
463     }
464     return true;
465 }
466 
IncreaseCacheRefCount(uint64_t uniqueId,bool useSkImage,std::shared_ptr<Media::PixelMap> pixelMap)467 void RSImageBase::IncreaseCacheRefCount(uint64_t uniqueId, bool useSkImage, std::shared_ptr<Media::PixelMap>
468     pixelMap)
469 {
470     if (useSkImage) {
471         RSImageCache::Instance().IncreaseDrawingImageCacheRefCount(uniqueId);
472     } else if (pixelMap) {
473         RSImageCache::Instance().IncreasePixelMapCacheRefCount(uniqueId);
474     }
475 }
476 
Marshalling(Parcel & parcel) const477 bool RSImageBase::Marshalling(Parcel& parcel) const
478 {
479     std::lock_guard<std::mutex> lock(mutex_);
480     uint32_t versionId = pixelMap_ == nullptr ? 0 : pixelMap_->GetVersionId();
481     bool success = RSMarshallingHelper::Marshalling(parcel, uniqueId_) &&
482                    RSMarshallingHelper::Marshalling(parcel, srcRect_) &&
483                    RSMarshallingHelper::Marshalling(parcel, dstRect_) &&
484                    parcel.WriteBool(pixelMap_ == nullptr) &&
485                    RSMarshallingHelper::Marshalling(parcel, versionId) &&
486                    RSMarshallingHelper::Marshalling(parcel, image_) &&
487                    RSMarshallingHelper::Marshalling(parcel, pixelMap_);
488     if (!success) {
489         RS_LOGE("RSImageBase::Marshalling parcel fail");
490     }
491     return success;
492 }
493 
Unmarshalling(Parcel & parcel)494 RSImageBase* RSImageBase::Unmarshalling(Parcel& parcel)
495 {
496     uint64_t uniqueId;
497     RectF srcRect;
498     RectF dstRect;
499     if (!UnmarshallingIdAndRect(parcel, uniqueId, srcRect, dstRect)) {
500         RS_LOGE("RSImage::Unmarshalling UnmarshalIdAndSize fail");
501         return nullptr;
502     }
503 
504     bool useSkImage;
505     std::shared_ptr<Drawing::Image> img = std::make_shared<Drawing::Image>();
506     std::shared_ptr<Media::PixelMap> pixelMap;
507     void* imagepixelAddr = nullptr;
508     if (!UnmarshallingDrawingImageAndPixelMap(parcel, uniqueId, useSkImage, img, pixelMap, imagepixelAddr)) {
509         return nullptr;
510     }
511 
512     RSImageBase* rsImage = new RSImageBase();
513     rsImage->SetImage(img);
514     rsImage->SetImagePixelAddr(imagepixelAddr);
515     rsImage->SetPixelMap(pixelMap);
516     rsImage->SetSrcRect(srcRect);
517     rsImage->SetDstRect(dstRect);
518     rsImage->uniqueId_ = uniqueId;
519     rsImage->MarkRenderServiceImage();
520     IncreaseCacheRefCount(uniqueId, useSkImage, pixelMap);
521     return rsImage;
522 }
523 #endif
524 
ConvertPixelMapToDrawingImage()525 void RSImageBase::ConvertPixelMapToDrawingImage()
526 {
527     if (!image_ && pixelMap_ && !pixelMap_->IsAstc() && !isYUVImage_) {
528 #if defined(ROSEN_OHOS)
529             if (RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
530                 image_ = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_);
531             } else {
532                 image_ = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_, gettid());
533             }
534 #else
535             image_ = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_);
536 #endif
537         if (!image_) {
538             image_ = RSPixelMapUtil::ExtractDrawingImage(pixelMap_);
539 #if defined(ROSEN_OHOS)
540             if (RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
541                 RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image_);
542             } else {
543                 RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image_, gettid());
544             }
545 #else
546             RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image_);
547 #endif
548         }
549     }
550 }
551 
GetUniqueId() const552 uint64_t RSImageBase::GetUniqueId() const
553 {
554     return uniqueId_;
555 }
556 
GenUniqueId(uint32_t id)557 void RSImageBase::GenUniqueId(uint32_t id)
558 {
559     static uint64_t shiftedPid = static_cast<uint64_t>(GetRealPid()) << 32; // 32 for 64-bit unsignd number shift
560     uniqueId_ = shiftedPid | id;
561 }
562 
563 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
ProcessYUVImage(std::shared_ptr<Drawing::GPUContext> gpuContext,Drawing::Canvas & canvas)564 void RSImageBase::ProcessYUVImage(std::shared_ptr<Drawing::GPUContext> gpuContext, Drawing::Canvas& canvas)
565 {
566     if (!gpuContext) {
567         return;
568     }
569 
570     std::shared_ptr<Drawing::Image> cache;
571     pid_t threadId = gettid();
572 #ifdef SUBTREE_PARALLEL_ENABLE
573     // Adapt to the subtree feature to ensure the correct thread ID(TID) is set.
574     RSParallelMisc::AdaptSubTreeThreadId(canvas, threadId);
575 #endif
576     cache = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_, threadId);
577 
578     std::lock_guard<std::mutex> lock(mutex_);
579     if (cache) {
580         image_ = cache;
581         return;
582     }
583     RS_TRACE_NAME("make yuv img");
584     auto image = RSPixelMapUtil::ConvertYUVPixelMapToDrawingImage(gpuContext, pixelMap_);
585     if (image) {
586         image_ = image;
587         SKResourceManager::Instance().HoldResource(image);
588         RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image, threadId);
589     } else {
590         RS_LOGE("make yuv image %{public}d (%{public}d, %{public}d) failed",
591             (int)uniqueId_, (int)srcRect_.width_, (int)srcRect_.height_);
592     }
593 }
594 #endif
595 
SetCompressData(const std::shared_ptr<Drawing::Data> compressData)596 void RSImageBase::SetCompressData(const std::shared_ptr<Drawing::Data> compressData)
597 {
598 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
599     isDrawn_ = false;
600     compressData_ = compressData;
601     canPurgeShareMemFlag_ = CanPurgeFlag::DISABLED;
602 #endif
603 }
604 
605 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
SetCompressedDataForASTC()606 bool RSImageBase::SetCompressedDataForASTC()
607 {
608     if (!pixelMap_ || !pixelMap_->GetFd() || !pixelMap_->IsAstc()) {
609         RS_LOGE("%{public}s fail, pixelMap_ is invalid", __func__);
610         return false;
611     }
612     std::shared_ptr<Drawing::Data> fileData = std::make_shared<Drawing::Data>();
613 #if defined(RS_ENABLE_VK)
614     if (pixelMap_->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC &&
615         (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
616         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR)) {
617         sptr<SurfaceBuffer> surfaceBuf(reinterpret_cast<SurfaceBuffer *>(pixelMap_->GetFd()));
618         nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuf);
619         OH_NativeBuffer* nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(nativeWindowBuffer_);
620         if (nativeBuffer == nullptr || !fileData->BuildFromOHNativeBuffer(nativeBuffer, pixelMap_->GetCapacity())) {
621             RS_LOGE("%{public}s data BuildFromOHNativeBuffer fail", __func__);
622             return false;
623         }
624     } else {
625 #endif // RS_ENABLE_VK
626 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
627         const void* data = pixelMap_->GetPixels();
628         if (pixelMap_->GetCapacity() > ASTC_HEADER_SIZE &&
629             (data == nullptr || !fileData->BuildWithoutCopy(
630                 reinterpret_cast<const void *>(reinterpret_cast<const char *>(data) + ASTC_HEADER_SIZE),
631                 pixelMap_->GetCapacity() - ASTC_HEADER_SIZE))) {
632             RS_LOGE("%{public}s data BuildWithoutCopy fail", __func__);
633             return false;
634         }
635 #endif // RS_ENABLE_GL || RS_ENABLE_VK
636 #if defined(RS_ENABLE_VK)
637     }
638 #endif // RS_ENABLE_VK
639     SetCompressData(fileData);
640     return true;
641 }
642 #endif // ROSEN_OHOS && (RS_ENABLE_GL || RS_ENABLE_VK)
643 
GetPixelMap() const644 std::shared_ptr<Media::PixelMap> RSImageBase::GetPixelMap() const
645 {
646     return pixelMap_;
647 }
648 
649 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_VK)
MakeFromTextureForVK(Drawing::Canvas & canvas,SurfaceBuffer * surfaceBuffer)650 std::shared_ptr<Drawing::Image> RSImageBase::MakeFromTextureForVK(
651     Drawing::Canvas& canvas, SurfaceBuffer* surfaceBuffer)
652 {
653     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
654         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
655         return nullptr;
656     }
657     if (!surfaceBuffer || !canvas.GetGPUContext()) {
658         RS_LOGE("RSImageBase MakeFromTextureForVK surfaceBuffer is nullptr");
659         return nullptr;
660     }
661     if (nativeWindowBuffer_ == nullptr) {
662         sptr<SurfaceBuffer> sfBuffer(surfaceBuffer);
663         nativeWindowBuffer_ = CreateNativeWindowBufferFromSurfaceBuffer(&sfBuffer);
664         if (!nativeWindowBuffer_) {
665             RS_LOGE("RSImageBase MakeFromTextureForVK create native window buffer fail");
666             return nullptr;
667         }
668     }
669     if (!backendTexture_.IsValid()) {
670         backendTexture_ = NativeBufferUtils::MakeBackendTextureFromNativeBuffer(
671             nativeWindowBuffer_, surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight(), false);
672         if (backendTexture_.IsValid()) {
673             auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
674             cleanUpHelper_ = new NativeBufferUtils::VulkanCleanupHelper(
675                 RsVulkanContext::GetSingleton(), vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory);
676         } else {
677             return nullptr;
678         }
679         tid_ = gettid();
680     }
681 
682     std::shared_ptr<Drawing::Image> dmaImage = std::make_shared<Drawing::Image>();
683     auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
684     Drawing::ColorType colorType = GetColorTypeWithVKFormat(vkTextureInfo->format);
685     Drawing::BitmapFormat bitmapFormat = { colorType, Drawing::AlphaType::ALPHATYPE_PREMUL };
686     if (!dmaImage->BuildFromTexture(*canvas.GetGPUContext(), backendTexture_.GetTextureInfo(),
687         Drawing::TextureOrigin::TOP_LEFT, bitmapFormat, nullptr, NativeBufferUtils::DeleteVkImage,
688         cleanUpHelper_->Ref())) {
689         RS_LOGE("RSImageBase MakeFromTextureForVK build image failed");
690         return nullptr;
691     }
692     return dmaImage;
693 }
694 
BindPixelMapToDrawingImage(Drawing::Canvas & canvas)695 void RSImageBase::BindPixelMapToDrawingImage(Drawing::Canvas& canvas)
696 {
697     if (pixelMap_ && !pixelMap_->IsAstc()) {
698         std::shared_ptr<Drawing::Image> imageCache = nullptr;
699         pid_t threadId = gettid();
700 #ifdef SUBTREE_PARALLEL_ENABLE
701         // Adapt to the subtree feature to ensure the correct thread ID (TID) is set.
702         RSParallelMisc::AdaptSubTreeThreadId(canvas, threadId);
703 #endif
704         if (!pixelMap_->IsEditable()) {
705             imageCache = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_, threadId);
706         }
707         if (imageCache) {
708             image_ = imageCache;
709         } else {
710             image_ = MakeFromTextureForVK(canvas, reinterpret_cast<SurfaceBuffer*>(pixelMap_->GetFd()));
711             if (image_) {
712                 SKResourceManager::Instance().HoldResource(image_);
713                 RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image_, threadId);
714             }
715         }
716     }
717 }
718 #endif
719 
720 #ifdef ROSEN_OHOS
PixelMapUseCountGuard(std::shared_ptr<Media::PixelMap> pixelMap,bool purgeable)721 RSImageBase::PixelMapUseCountGuard::PixelMapUseCountGuard(std::shared_ptr<Media::PixelMap> pixelMap, bool purgeable)
722     : pixelMap_(pixelMap), purgeable_(purgeable)
723 {
724     if (purgeable_) {
725         pixelMap_->IncreaseUseCount();
726     }
727 }
728 
~PixelMapUseCountGuard()729 RSImageBase::PixelMapUseCountGuard::~PixelMapUseCountGuard()
730 {
731     if (purgeable_) {
732         pixelMap_->DecreaseUseCount();
733     }
734 }
735 #endif
736 
737 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
PixelFormatToCompressedType(Media::PixelFormat pixelFormat,bool isHdr)738 static Drawing::CompressedType PixelFormatToCompressedType(Media::PixelFormat pixelFormat, bool isHdr)
739 {
740     switch (pixelFormat) {
741         case Media::PixelFormat::ASTC_4x4: return isHdr ? Drawing::CompressedType::ASTC_RGBA10_4x4 :
742             Drawing::CompressedType::ASTC_RGBA8_4x4;
743         case Media::PixelFormat::ASTC_6x6: return Drawing::CompressedType::ASTC_RGBA8_6x6;
744         case Media::PixelFormat::ASTC_8x8: return Drawing::CompressedType::ASTC_RGBA8_8x8;
745         case Media::PixelFormat::UNKNOWN:
746         default: return Drawing::CompressedType::NoneType;
747     }
748 }
749 
ColorSpaceToDrawingColorSpace(ColorManager::ColorSpaceName colorSpaceName)750 static std::shared_ptr<Drawing::ColorSpace> ColorSpaceToDrawingColorSpace(ColorManager::ColorSpaceName
751  colorSpaceName)
752 {
753     switch (colorSpaceName) {
754         case ColorManager::ColorSpaceName::DISPLAY_P3:
755             return Drawing::ColorSpace::CreateRGB(
756                 Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::DCIP3);
757         case ColorManager::ColorSpaceName::LINEAR_SRGB:
758             return Drawing::ColorSpace::CreateSRGBLinear();
759         case ColorManager::ColorSpaceName::SRGB:
760             return Drawing::ColorSpace::CreateSRGB();
761         case ColorManager::ColorSpaceName::DISPLAY_BT2020_SRGB:
762             return Drawing::ColorSpace::CreateRGB(
763                 Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::REC2020);
764         case ColorManager::ColorSpaceName::ADOBE_RGB:
765             return Drawing::ColorSpace::CreateRGB(
766                 Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::ADOBE_RGB);
767         default:
768             return Drawing::ColorSpace::CreateSRGB();
769     }
770 }
771 #endif
772 
UploadGpu(Drawing::Canvas & canvas)773 void RSImageBase::UploadGpu(Drawing::Canvas& canvas)
774 {
775 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
776     if (compressData_) {
777         std::shared_ptr<Drawing::Image> cache;
778         if (RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
779             cache = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_);
780         } else {
781             cache = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_, gettid());
782         }
783         std::lock_guard<std::mutex> lock(mutex_);
784         if (cache) {
785             image_ = cache;
786         } else {
787             if (canvas.GetGPUContext() == nullptr) {
788                 return;
789             }
790             RS_TRACE_NAME("make compress img");
791             Media::ImageInfo imageInfo;
792             pixelMap_->GetImageInfo(imageInfo);
793             Media::Size realSize;
794             pixelMap_->GetAstcRealSize(realSize);
795             auto image = std::make_shared<Drawing::Image>();
796             std::shared_ptr<Drawing::ColorSpace> colorSpace =
797                 ColorSpaceToDrawingColorSpace(pixelMap_->InnerGetGrColorSpace().GetColorSpaceName());
798             bool result = image->BuildFromCompressed(*canvas.GetGPUContext(), compressData_,
799                 static_cast<int>(realSize.width), static_cast<int>(realSize.height),
800                 PixelFormatToCompressedType(imageInfo.pixelFormat, pixelMap_->IsHdr()), colorSpace);
801             if (result) {
802                 image_ = image;
803                 SKResourceManager::Instance().HoldResource(image);
804                 if (RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
805                     RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image);
806                 } else {
807                     RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image, gettid());
808                 }
809             } else {
810                 RS_LOGE("make astc image %{public}d (%{public}d, %{public}d) failed",
811                     (int)uniqueId_, (int)srcRect_.width_, (int)srcRect_.height_);
812             }
813             compressData_ = nullptr;
814         }
815         return;
816     }
817     if (isYUVImage_) {
818         ProcessYUVImage(canvas.GetGPUContext(), canvas);
819     }
820 #endif
821 }
822 }
823