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