• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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 "rs_vk_image_manager.h"
17 
18 #include <parameter.h>
19 #include <parameters.h>
20 #include "include/core/SkColorSpace.h"
21 #include "native_buffer_inner.h"
22 #include "platform/common/rs_log.h"
23 #ifdef USE_M133_SKIA
24 #include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
25 #else
26 #include "include/gpu/GrBackendSurface.h"
27 #endif
28 #include "pipeline/hardware_thread/rs_hardware_thread.h"
29 #include "pipeline/rs_task_dispatcher.h"
30 #include "rs_trace.h"
31 #include "common/rs_optional_trace.h"
32 #include "params/rs_surface_render_params.h"
33 
34 #ifdef USE_M133_SKIA
35 #include "src/gpu/ganesh/gl/GrGLDefines.h"
36 #else
37 #include "src/gpu/gl/GrGLDefines.h"
38 #endif
39 
40 namespace OHOS {
41 namespace Rosen {
42 namespace {
WaitAcquireFence(const sptr<SyncFence> & acquireFence)43 void WaitAcquireFence(const sptr<SyncFence>& acquireFence)
44 {
45     if (acquireFence == nullptr) {
46         return;
47     }
48     acquireFence->Wait(3000); // 3000ms
49 }
50 
51 constexpr size_t MAX_CACHE_SIZE = 16;
52 constexpr size_t MAX_CACHE_SIZE_FOR_REUSE = 40;
53 static const bool ENABLE_VKIMAGE_DFX = system::GetBoolParameter("persist.graphic.enable_vkimage_dfx", false);
54 static const bool ENABLE_SEMAPHORE =
55     system::GetBoolParameter("persist.sys.graphic.rs_vkimgmgr_enable_semaphore", true);
56 
57 #define DFX_LOG(enableDfx, format, ...) \
58     ((enableDfx) ? (void) HILOG_ERROR(LOG_CORE, format, ##__VA_ARGS__) : (void) 0)
59 #define DFX_LOGD(enableDfx, format, ...) \
60     ((enableDfx) ? (void) HILOG_ERROR(LOG_CORE, format, ##__VA_ARGS__) : \
61                    (void) HILOG_DEBUG(LOG_CORE, format, ##__VA_ARGS__))
62 }
63 
~VkImageResource()64 VkImageResource::~VkImageResource()
65 {
66     NativeBufferUtils::DeleteVkImage(mVulkanCleanupHelper);
67     DestroyNativeWindowBuffer(mNativeWindowBuffer);
68 }
69 
Create(sptr<OHOS::SurfaceBuffer> buffer)70 std::shared_ptr<VkImageResource> VkImageResource::Create(sptr<OHOS::SurfaceBuffer> buffer)
71 {
72     if (buffer == nullptr) {
73         ROSEN_LOGE("VkImageResource::Create buffer is nullptr");
74         return nullptr;
75     }
76     auto width = buffer->GetSurfaceBufferWidth();
77     auto height = buffer->GetSurfaceBufferHeight();
78     NativeWindowBuffer* nativeWindowBuffer = CreateNativeWindowBufferFromSurfaceBuffer(&buffer);
79     bool isProtected = (buffer->GetUsage() & BUFFER_USAGE_PROTECTED) != 0;
80     auto backendTexture = NativeBufferUtils::MakeBackendTextureFromNativeBuffer(nativeWindowBuffer,
81         width, height, isProtected);
82     if (!backendTexture.IsValid() || !backendTexture.GetTextureInfo().GetVKTextureInfo()) {
83         DestroyNativeWindowBuffer(nativeWindowBuffer);
84         return nullptr;
85     }
86     return std::make_unique<VkImageResource>(
87         nativeWindowBuffer,
88         backendTexture,
89         new NativeBufferUtils::VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
90             backendTexture.GetTextureInfo().GetVKTextureInfo()->vkImage,
91             backendTexture.GetTextureInfo().GetVKTextureInfo()->vkAlloc.memory));
92 }
93 
WaitVKSemaphore(Drawing::Surface * drawingSurface,const sptr<SyncFence> & acquireFence)94 bool RSVkImageManager::WaitVKSemaphore(Drawing::Surface *drawingSurface, const sptr<SyncFence>& acquireFence)
95 {
96     if (drawingSurface == nullptr || acquireFence == nullptr) {
97         return false;
98     }
99 
100     VkSemaphore semaphore = VK_NULL_HANDLE;
101     VkSemaphoreCreateInfo semaphoreInfo;
102     semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
103     semaphoreInfo.pNext = nullptr;
104     semaphoreInfo.flags = 0;
105     auto& vkInterface = RsVulkanContext::GetSingleton().GetRsVulkanInterface();
106     auto res = vkInterface.vkCreateSemaphore(vkInterface.GetDevice(), &semaphoreInfo, nullptr, &semaphore);
107     if (res != VK_SUCCESS) {
108         ROSEN_LOGE("RSVkImageManager: CreateVkSemaphore vkCreateSemaphore failed %{public}d", res);
109         return false;
110     }
111 
112     VkImportSemaphoreFdInfoKHR importSemaphoreFdInfo;
113     importSemaphoreFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
114     importSemaphoreFdInfo.pNext = nullptr;
115     importSemaphoreFdInfo.semaphore = semaphore;
116     importSemaphoreFdInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
117     importSemaphoreFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
118     importSemaphoreFdInfo.fd = acquireFence->Dup();
119     res = vkInterface.vkImportSemaphoreFdKHR(vkInterface.GetDevice(), &importSemaphoreFdInfo);
120     if (res != VK_SUCCESS) {
121         ROSEN_LOGE("RSVkImageManager: CreateVkSemaphore vkImportSemaphoreFdKHR failed %{public}d", res);
122         vkInterface.vkDestroySemaphore(vkInterface.GetDevice(), semaphore, nullptr);
123         close(importSemaphoreFdInfo.fd);
124         return false;
125     }
126 
127     drawingSurface->Wait(1, semaphore); // 1 means only one VKSemaphore need to wait
128     return true;
129 }
130 
MapVkImageFromSurfaceBuffer(const sptr<OHOS::SurfaceBuffer> & buffer,const sptr<SyncFence> & acquireFence,pid_t threadIndex,Drawing::Surface * drawingSurface)131 std::shared_ptr<VkImageResource> RSVkImageManager::MapVkImageFromSurfaceBuffer(
132     const sptr<OHOS::SurfaceBuffer>& buffer,
133     const sptr<SyncFence>& acquireFence,
134     pid_t threadIndex, Drawing::Surface *drawingSurface)
135 {
136     if (buffer == nullptr) {
137         ROSEN_LOGE("RSVkImageManager::MapVkImageFromSurfaceBuffer buffer is nullptr");
138         return nullptr;
139     }
140     if (!ENABLE_SEMAPHORE || !WaitVKSemaphore(drawingSurface, acquireFence)) {
141         WaitAcquireFence(acquireFence);
142     }
143     std::lock_guard<std::mutex> lock(opMutex_);
144     bool isProtectedCondition = (buffer->GetUsage() & BUFFER_USAGE_PROTECTED) ||
145         RsVulkanContext::GetSingleton().GetIsProtected();
146     auto bufferId = buffer->GetSeqNum();
147     if (isProtectedCondition || imageCacheSeqs_.find(bufferId) == imageCacheSeqs_.end()) {
148         RS_TRACE_NAME_FMT("create vkImage, bufferId=%u", bufferId);
149         return NewImageCacheFromBuffer(buffer, threadIndex, isProtectedCondition);
150     } else {
151         RS_TRACE_NAME_FMT("find cache vkImage, bufferId=%u", bufferId);
152         return imageCacheSeqs_[bufferId];
153     }
154 }
155 
CreateImageCacheFromBuffer(const sptr<OHOS::SurfaceBuffer> buffer,const sptr<SyncFence> & acquireFence)156 std::shared_ptr<VkImageResource> RSVkImageManager::CreateImageCacheFromBuffer(const sptr<OHOS::SurfaceBuffer> buffer,
157     const sptr<SyncFence>& acquireFence)
158 {
159     WaitAcquireFence(acquireFence);
160     if (buffer == nullptr) {
161         ROSEN_LOGE("RSVkImageManager::CreateImageCacheFromBuffer buffer is nullptr");
162         return nullptr;
163     }
164     auto bufferId = buffer->GetSeqNum();
165     auto imageCache = VkImageResource::Create(buffer);
166     if (imageCache == nullptr) {
167         ROSEN_LOGE(
168             "RSVkImageManager::CreateImageCacheFromBuffer: failed to create ImageCache for buffer id %{public}d.",
169             bufferId);
170         return nullptr;
171     }
172     return imageCache;
173 }
174 
NewImageCacheFromBuffer(const sptr<OHOS::SurfaceBuffer> & buffer,pid_t threadIndex,bool isProtectedCondition)175 std::shared_ptr<VkImageResource> RSVkImageManager::NewImageCacheFromBuffer(
176     const sptr<OHOS::SurfaceBuffer>& buffer, pid_t threadIndex, bool isProtectedCondition)
177 {
178     if (buffer == nullptr) {
179         ROSEN_LOGE("RSVkImageManager::NewImageCacheFromBuffer buffer is nullptr");
180         return {};
181     }
182     auto bufferId = buffer->GetSeqNum();
183     auto deleteFlag = buffer->GetBufferDeleteFromCacheFlag();
184     auto imageCache = VkImageResource::Create(buffer);
185     if (imageCache == nullptr) {
186         ROSEN_LOGE("RSVkImageManager::NewImageCacheFromBuffer: failed to create ImageCache for buffer id %{public}d.",
187             bufferId);
188         return {};
189     }
190 
191     size_t imageCacheSeqSize = imageCacheSeqs_.size();
192     DFX_LOGD(ENABLE_VKIMAGE_DFX, "RSVkImageManagerDfx: create image, bufferId=%{public}u, threadIndex=%{public}d, "
193         "deleteFlag=%{public}d, isProtected=%{public}d,cacheSeq=%{public}lu",
194         bufferId, threadIndex, deleteFlag, isProtectedCondition, imageCacheSeqSize);
195     RS_TRACE_NAME_FMT("RSVkImageManagerDfx: create image, bufferId=%u, "
196         "deleteFlag=%d, isProtected=%d, cacheSeq=%lu",
197         bufferId, deleteFlag, isProtectedCondition, imageCacheSeqSize);
198     imageCache->SetThreadIndex(threadIndex);
199     imageCache->SetBufferDeleteFromCacheFlag(deleteFlag);
200     if (isProtectedCondition) {
201         return imageCache;
202     }
203 
204     RS_LOGD("RSVkImageManager::NewImageCacheFromBuffer %{public}u", bufferId);
205     if (imageCacheSeqSize < MAX_CACHE_SIZE_FOR_REUSE) {
206         imageCacheSeqs_.emplace(bufferId, imageCache);
207     }
208 
209     return imageCache;
210 }
211 
UnMapImageFromSurfaceBuffer(int32_t seqNum)212 void RSVkImageManager::UnMapImageFromSurfaceBuffer(int32_t seqNum)
213 {
214     DFX_LOG(ENABLE_VKIMAGE_DFX, "RSVkImageManagerDfx: tryUnmapImage, bufferId=%{public}u", seqNum);
215     pid_t threadIndex = UNI_RENDER_THREAD_INDEX;
216     {
217         std::lock_guard<std::mutex> lock(opMutex_);
218         if (imageCacheSeqs_.count(seqNum) == 0) {
219             return;
220         }
221         threadIndex = imageCacheSeqs_[seqNum]->GetThreadIndex();
222     }
223     auto func = [this, seqNum]() {
224         std::lock_guard<std::mutex> lock(opMutex_);
225         auto iter = imageCacheSeqs_.find(seqNum);
226         if (iter == imageCacheSeqs_.end()) {
227             return;
228         }
229         RS_TRACE_NAME_FMT("RSVkImageManagerDfx: unmap image, bufferId=%u", seqNum);
230         imageCacheSeqs_.erase(iter);
231         DFX_LOGD(ENABLE_VKIMAGE_DFX, "RSVkImageManagerDfx: UnmapImage, bufferId=%{public}u, "
232             "cacheSeq=[%{public}lu]",
233             seqNum, imageCacheSeqs_.size());
234     };
235     DFX_LOGD(ENABLE_VKIMAGE_DFX, "RSVkImageManagerDfx: findImageToUnmap, bufferId=%{public}u", seqNum);
236     RSTaskDispatcher::GetInstance().PostTask(threadIndex, func);
237 }
238 
DumpVkImageInfo(std::string & dumpString)239 void RSVkImageManager::DumpVkImageInfo(std::string &dumpString)
240 {
241     std::lock_guard<std::mutex> lock(opMutex_);
242     dumpString.append("\n---------RSVkImageManager-DumpVkImageInfo-Begin----------\n");
243     dumpString.append("imageCacheSeqs size: " + std::to_string(imageCacheSeqs_.size()) + "\n");
244     for (auto iter = imageCacheSeqs_.begin(); iter != imageCacheSeqs_.end(); ++iter) {
245         dumpString.append("vkimageinfo: bufferId=" + std::to_string(iter->first) +
246             ", threadIndex=" + std::to_string(iter->second->GetThreadIndex()) +
247             ", deleteFlag=" + std::to_string(iter->second->GetBufferDeleteFromCacheFlag()) + "\n");
248     }
249     dumpString.append("\n---------RSVkImageManager-DumpVkImageInfo-End----------\n");
250 }
251 
CreateImageFromBuffer(RSPaintFilterCanvas & canvas,const BufferDrawParam & params,const std::shared_ptr<Drawing::ColorSpace> & drawingColorSpace)252 std::shared_ptr<Drawing::Image> RSVkImageManager::CreateImageFromBuffer(
253     RSPaintFilterCanvas& canvas, const BufferDrawParam& params,
254     const std::shared_ptr<Drawing::ColorSpace>& drawingColorSpace)
255 {
256     const sptr<SurfaceBuffer>& buffer = params.buffer;
257     const sptr<SyncFence>& acquireFence = params.acquireFence;
258     const pid_t threadIndex = params.threadIndex;
259     const Drawing::AlphaType alphaType = params.alphaType;
260 
261     auto image = std::make_shared<Drawing::Image>();
262     if (buffer == nullptr) {
263         RS_LOGE("RSVkImageManager::CreateImageFromBuffer: buffer is nullptr");
264         return nullptr;
265     }
266     auto imageCache = MapVkImageFromSurfaceBuffer(buffer,
267         acquireFence, threadIndex, canvas.GetSurface());
268     if (imageCache == nullptr) {
269         RS_LOGE("RSVkImageManager::MapImageFromSurfaceBuffer failed!");
270         return nullptr;
271     }
272     if (buffer != nullptr && buffer->GetBufferDeleteFromCacheFlag()) {
273         RS_LOGD_IF(DEBUG_COMPOSER, "  - Buffer %{public}u marked for deletion from cache, unmapping",
274             buffer->GetSeqNum());
275         UnMapImageFromSurfaceBuffer(buffer->GetSeqNum());
276     }
277     auto bitmapFormat = RSBaseRenderUtil::GenerateDrawingBitmapFormat(buffer, alphaType);
278     auto screenColorSpace = RSBaseRenderEngine::GetCanvasColorSpace(canvas);
279     if (screenColorSpace && drawingColorSpace &&
280         drawingColorSpace->IsSRGB() != screenColorSpace->IsSRGB()) {
281         bitmapFormat.alphaType = Drawing::AlphaType::ALPHATYPE_OPAQUE;
282     }
283     RS_LOGD_IF(DEBUG_COMPOSER, "  - Generated bitmap format: colorType = %{public}d, alphaType = %{public}d",
284         bitmapFormat.colorType, bitmapFormat.alphaType);
285     auto surfaceOrigin = Drawing::TextureOrigin::TOP_LEFT;
286     RS_LOGD_IF(DEBUG_COMPOSER, "  - Texture origin: %{public}d", static_cast<int>(surfaceOrigin));
287     auto contextDrawingVk = canvas.GetGPUContext();
288     if (contextDrawingVk == nullptr) {
289         RS_LOGE("contextDrawingVk is nullptr.");
290         return nullptr;
291     }
292     auto& backendTexture = imageCache->GetBackendTexture();
293     if (!image->BuildFromTexture(*contextDrawingVk, backendTexture.GetTextureInfo(),
294         surfaceOrigin, bitmapFormat, drawingColorSpace,
295         NativeBufferUtils::DeleteVkImage, imageCache->RefCleanupHelper())) {
296         RS_LOGE("RSVkImageManager::CreateImageFromBuffer: backendTexture is not valid!!!");
297         return nullptr;
298     }
299     return image;
300 }
301 
GetIntersectImage(Drawing::RectI & imgCutRect,const std::shared_ptr<Drawing::GPUContext> & context,const sptr<OHOS::SurfaceBuffer> & buffer,const sptr<SyncFence> & acquireFence,pid_t threadIndex)302 std::shared_ptr<Drawing::Image> RSVkImageManager::GetIntersectImage(Drawing::RectI& imgCutRect,
303     const std::shared_ptr<Drawing::GPUContext>& context, const sptr<OHOS::SurfaceBuffer>& buffer,
304     const sptr<SyncFence>& acquireFence, pid_t threadIndex)
305 {
306     if (buffer == nullptr) {
307         ROSEN_LOGE("RSVkImageManager::GetIntersectImageFromVK context or buffer is nullptr!");
308         return nullptr;
309     }
310     auto imageCache = CreateImageCacheFromBuffer(buffer, acquireFence);
311     if (imageCache == nullptr) {
312         ROSEN_LOGE("RSVkImageManager::GetIntersectImageFromVK imageCache == nullptr!");
313         return nullptr;
314     }
315     auto& backendTexture = imageCache->GetBackendTexture();
316     Drawing::BitmapFormat bitmapFormat = RSBaseRenderUtil::GenerateDrawingBitmapFormat(buffer);
317 
318     std::shared_ptr<Drawing::Image> layerImage = std::make_shared<Drawing::Image>();
319     if (!layerImage->BuildFromTexture(*context, backendTexture.GetTextureInfo(),
320         Drawing::TextureOrigin::TOP_LEFT, bitmapFormat, nullptr,
321         NativeBufferUtils::DeleteVkImage, imageCache->RefCleanupHelper())) {
322         ROSEN_LOGE("RSVkImageManager::GetIntersectImageFromVK image BuildFromTexture failed.");
323         return nullptr;
324     }
325 
326     std::shared_ptr<Drawing::Image> cutDownImage = std::make_shared<Drawing::Image>();
327     bool res = cutDownImage->BuildSubset(layerImage, imgCutRect, *context);
328     if (!res) {
329         ROSEN_LOGE("RSVkImageManager::GetIntersectImageFromVK cutDownImage BuildSubset failed.");
330         return nullptr;
331     }
332     return cutDownImage;
333 }
334 } // namespace Rosen
335 } // namespace OHOS