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