• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "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 #include "include/gpu/GrBackendSurface.h"
24 #include "pipeline/hardware_thread/rs_hardware_thread.h"
25 #include "pipeline/rs_task_dispatcher.h"
26 #include "rs_trace.h"
27 #include "common/rs_optional_trace.h"
28 #include "params/rs_surface_render_params.h"
29 
30 namespace OHOS {
31 namespace Rosen {
32 namespace {
WaitAcquireFence(const sptr<SyncFence> & acquireFence)33 void WaitAcquireFence(const sptr<SyncFence>& acquireFence)
34 {
35     if (acquireFence == nullptr) {
36         return;
37     }
38     acquireFence->Wait(3000); // 3000ms
39 }
40 
41 constexpr size_t MAX_CACHE_SIZE = 16;
42 constexpr size_t MAX_CACHE_SIZE_FOR_VIRTUAL_SCREEN = 40;
43 static const bool ENABLE_VKIMAGE_DFX = system::GetBoolParameter("persist.graphic.enable_vkimage_dfx", false);
44 
45 #define DFX_LOG(enableDfx, format, ...) \
46     ((enableDfx) ? (void) HILOG_ERROR(LOG_CORE, format, ##__VA_ARGS__) : (void) 0)
47 #define DFX_LOGD(enableDfx, format, ...) \
48     ((enableDfx) ? (void) HILOG_ERROR(LOG_CORE, format, ##__VA_ARGS__) : \
49                    (void) HILOG_DEBUG(LOG_CORE, format, ##__VA_ARGS__))
50 }
51 
~NativeVkImageRes()52 NativeVkImageRes::~NativeVkImageRes()
53 {
54     NativeBufferUtils::DeleteVkImage(mVulkanCleanupHelper);
55     DestroyNativeWindowBuffer(mNativeWindowBuffer);
56 }
57 
Create(sptr<OHOS::SurfaceBuffer> buffer)58 std::shared_ptr<NativeVkImageRes> NativeVkImageRes::Create(sptr<OHOS::SurfaceBuffer> buffer)
59 {
60     if (buffer == nullptr) {
61         ROSEN_LOGE("NativeVkImageRes::Create buffer is nullptr");
62         return nullptr;
63     }
64     auto width = buffer->GetSurfaceBufferWidth();
65     auto height = buffer->GetSurfaceBufferHeight();
66     NativeWindowBuffer* nativeWindowBuffer = CreateNativeWindowBufferFromSurfaceBuffer(&buffer);
67     bool isProtected = (buffer->GetUsage() & BUFFER_USAGE_PROTECTED) != 0;
68     auto backendTexture = NativeBufferUtils::MakeBackendTextureFromNativeBuffer(nativeWindowBuffer,
69         width, height, isProtected);
70     if (!backendTexture.IsValid() || !backendTexture.GetTextureInfo().GetVKTextureInfo()) {
71         DestroyNativeWindowBuffer(nativeWindowBuffer);
72         return nullptr;
73     }
74     return std::make_unique<NativeVkImageRes>(
75         nativeWindowBuffer,
76         backendTexture,
77         new NativeBufferUtils::VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
78             backendTexture.GetTextureInfo().GetVKTextureInfo()->vkImage,
79             backendTexture.GetTextureInfo().GetVKTextureInfo()->vkAlloc.memory));
80 }
81 
MapVkImageFromSurfaceBuffer(const sptr<OHOS::SurfaceBuffer> & buffer,const sptr<SyncFence> & acquireFence,pid_t threadIndex,ScreenId screenId)82 std::shared_ptr<NativeVkImageRes> RSVkImageManager::MapVkImageFromSurfaceBuffer(
83     const sptr<OHOS::SurfaceBuffer>& buffer,
84     const sptr<SyncFence>& acquireFence,
85     pid_t threadIndex, ScreenId screenId)
86 {
87     if (buffer == nullptr) {
88         ROSEN_LOGE("RSVkImageManager::MapVkImageFromSurfaceBuffer buffer is nullptr");
89         return nullptr;
90     }
91     WaitAcquireFence(acquireFence);
92     std::lock_guard<std::mutex> lock(opMutex_);
93     bool isProtectedCondition = (buffer->GetUsage() & BUFFER_USAGE_PROTECTED) ||
94         RsVulkanContext::GetSingleton().GetIsProtected();
95     auto bufferId = buffer->GetSeqNum();
96     if (isVirtualScreen(screenId) && !isProtectedCondition && threadIndex == RSUniRenderThread::Instance().GetTid()) {
97         if (imageCacheVirtualScreenSeqs_.find(bufferId) == imageCacheVirtualScreenSeqs_.end()) {
98             return NewImageCacheFromBuffer(buffer, threadIndex, isProtectedCondition, true);
99         }
100         RS_TRACE_NAME_FMT("find cache vkImage for VirScreen, bufferId=%u", bufferId);
101         return imageCacheVirtualScreenSeqs_[bufferId];
102     }
103 
104     if (isProtectedCondition || imageCacheSeqs_.find(bufferId) == imageCacheSeqs_.end()) {
105         return NewImageCacheFromBuffer(buffer, threadIndex, isProtectedCondition);
106     } else {
107         return imageCacheSeqs_[bufferId];
108     }
109 }
110 
CreateImageCacheFromBuffer(sptr<OHOS::SurfaceBuffer> buffer,const sptr<SyncFence> & acquireFence)111 std::shared_ptr<NativeVkImageRes> RSVkImageManager::CreateImageCacheFromBuffer(sptr<OHOS::SurfaceBuffer> buffer,
112     const sptr<SyncFence>& acquireFence)
113 {
114     WaitAcquireFence(acquireFence);
115     auto bufferId = buffer->GetSeqNum();
116     auto imageCache = NativeVkImageRes::Create(buffer);
117     if (imageCache == nullptr) {
118         ROSEN_LOGE(
119             "RSVkImageManager::CreateImageCacheFromBuffer: failed to create ImageCache for buffer id %{public}d.",
120             bufferId);
121         return nullptr;
122     }
123     return imageCache;
124 }
125 
isVirtualScreen(ScreenId screenId)126 bool RSVkImageManager::isVirtualScreen(ScreenId screenId)
127 {
128     if (screenId == INVALID_SCREEN_ID) {
129         return false;
130     }
131 
132     auto screenManager = CreateOrGetScreenManager();
133     if (!screenManager) {
134         return false;
135     }
136     RSScreenType type = UNKNOWN_TYPE_SCREEN;
137     if (screenManager->GetScreenType(screenId, type) != StatusCode::SUCCESS) {
138         return false;
139     }
140     return type == VIRTUAL_TYPE_SCREEN ? true : false;
141 }
142 
NewImageCacheFromBuffer(const sptr<OHOS::SurfaceBuffer> & buffer,pid_t threadIndex,bool isProtectedCondition,bool isMatchVirtualScreen)143 std::shared_ptr<NativeVkImageRes> RSVkImageManager::NewImageCacheFromBuffer(
144     const sptr<OHOS::SurfaceBuffer>& buffer, pid_t threadIndex, bool isProtectedCondition, bool isMatchVirtualScreen)
145 {
146     auto bufferId = buffer->GetSeqNum();
147     auto deleteFlag = buffer->GetBufferDeleteFromCacheFlag();
148     auto imageCache = NativeVkImageRes::Create(buffer);
149     if (imageCache == nullptr) {
150         ROSEN_LOGE("RSVkImageManager::NewImageCacheFromBuffer: failed to create ImageCache for buffer id %{public}d.",
151             bufferId);
152         return {};
153     }
154 
155     size_t imageCacheVirtualScreenSeqSize = imageCacheVirtualScreenSeqs_.size();
156     size_t imageCacheSeqSize = imageCacheSeqs_.size();
157     DFX_LOGD(ENABLE_VKIMAGE_DFX, "RSVkImageManagerDfx: create image, bufferId=%{public}u, threadIndex=%{public}d, "
158         "deleteFlag=%{public}d, isProtected=%{public}d, isVirtualScreen=%{public}d,cacheSeq=[%{public}lu, %{public}lu]",
159         bufferId, threadIndex, deleteFlag, isProtectedCondition, isMatchVirtualScreen,
160         imageCacheVirtualScreenSeqSize, imageCacheSeqSize);
161     RS_TRACE_NAME_FMT("RSVkImageManagerDfx: create image, bufferId=%u, "
162         "deleteFlag=%d, isProtected=%d, isVirtualScreen=%d,cacheSeq=[%lu, %lu]",
163         bufferId, deleteFlag, isProtectedCondition, isMatchVirtualScreen,
164         imageCacheVirtualScreenSeqSize, imageCacheSeqSize);
165     imageCache->SetThreadIndex(threadIndex);
166     imageCache->SetBufferDeleteFromCacheFlag(deleteFlag);
167     if (isProtectedCondition) {
168         return imageCache;
169     }
170 
171     if (isMatchVirtualScreen) {
172         if (imageCacheVirtualScreenSeqSize <= MAX_CACHE_SIZE_FOR_VIRTUAL_SCREEN) {
173             imageCacheVirtualScreenSeqs_.emplace(bufferId, imageCache);
174         }
175     } else {
176         imageCacheSeqs_.emplace(bufferId, imageCache);
177         cacheQueue_.push(bufferId);
178     }
179     return imageCache;
180 }
181 
ShrinkCachesIfNeeded()182 void RSVkImageManager::ShrinkCachesIfNeeded()
183 {
184     while (cacheQueue_.size() > MAX_CACHE_SIZE) {
185         const uint32_t id = cacheQueue_.front();
186         UnMapVkImageFromSurfaceBuffer(id);
187         cacheQueue_.pop();
188     }
189 }
190 
UnMapVkImageFromSurfaceBuffer(uint32_t seqNum,bool isMatchVirtualScreen)191 void RSVkImageManager::UnMapVkImageFromSurfaceBuffer(uint32_t seqNum, bool isMatchVirtualScreen)
192 {
193     DFX_LOG(ENABLE_VKIMAGE_DFX,
194         "RSVkImageManagerDfx: tryUnmapImage, bufferId=%{public}u, isMatchVirtualScreen=%{public}d",
195         seqNum, isMatchVirtualScreen);
196     pid_t threadIndex = UNI_RENDER_THREAD_INDEX;
197     {
198         std::lock_guard<std::mutex> lock(opMutex_);
199         if (isMatchVirtualScreen) {
200             threadIndex = RSUniRenderThread::Instance().GetTid();
201         } else {
202             if (imageCacheSeqs_.count(seqNum) == 0) {
203                 return;
204             }
205             threadIndex = imageCacheSeqs_[seqNum]->GetThreadIndex();
206         }
207     }
208     auto func = [this, seqNum, isMatchVirtualScreen]() {
209         {
210             std::lock_guard<std::mutex> lock(opMutex_);
211             if (isMatchVirtualScreen) {
212                 auto iter = imageCacheVirtualScreenSeqs_.find(seqNum);
213                 if (iter == imageCacheVirtualScreenSeqs_.end()) {
214                     return;
215                 }
216                 imageCacheVirtualScreenSeqs_.erase(iter);
217             } else {
218                 auto iter = imageCacheSeqs_.find(seqNum);
219                 if (iter == imageCacheSeqs_.end()) {
220                     return;
221                 }
222                 imageCacheSeqs_.erase(iter);
223             }
224             DFX_LOGD(ENABLE_VKIMAGE_DFX, "RSVkImageManagerDfx: UnmapImage, bufferId=%{public}u, "
225                 "isMatchVirtualScreen=%{public}d, cacheSeq=[%{public}lu, %{public}lu]",
226                 seqNum, isMatchVirtualScreen, imageCacheVirtualScreenSeqs_.size(), imageCacheSeqs_.size());
227         }
228     };
229     DFX_LOGD(ENABLE_VKIMAGE_DFX, "RSVkImageManagerDfx: findImageToUnmap, bufferId=%{public}u", seqNum);
230     RSTaskDispatcher::GetInstance().PostTask(threadIndex, func);
231 }
232 
UnMapAllVkImageVirtualScreenCache()233 void RSVkImageManager::UnMapAllVkImageVirtualScreenCache()
234 {
235     auto func = [this]() {
236         std::lock_guard<std::mutex> lock(opMutex_);
237         (void)imageCacheVirtualScreenSeqs_.clear();
238     };
239     RSTaskDispatcher::GetInstance().PostTask(RSUniRenderThread::Instance().GetTid(), func);
240 }
241 
DumpVkImageInfo(std::string & dumpString)242 void RSVkImageManager::DumpVkImageInfo(std::string &dumpString)
243 {
244     std::lock_guard<std::mutex> lock(opMutex_);
245     dumpString.append("\n---------RSVkImageManager-DumpVkImageInfo-Begin----------\n");
246     dumpString.append("imageCacheSeqs size: " + std::to_string(imageCacheSeqs_.size()) + "\n");
247     for (auto iter = imageCacheSeqs_.begin(); iter != imageCacheSeqs_.end(); ++iter) {
248         dumpString.append("vkimageinfo: bufferId=" + std::to_string(iter->first) +
249             ", threadIndex=" + std::to_string(iter->second->GetThreadIndex()) +
250             ", deleteFlag=" + std::to_string(iter->second->GetBufferDeleteFromCacheFlag()) + "\n");
251     }
252     dumpString.append("imageCacheVirtualScreenSeqs size: " +
253         std::to_string(imageCacheVirtualScreenSeqs_.size()) + "\n");
254     for (auto iter = imageCacheVirtualScreenSeqs_.begin(); iter != imageCacheVirtualScreenSeqs_.end(); ++iter) {
255         dumpString.append("vkimageinfo: bufferId=" + std::to_string(iter->first) +
256             ", threadIndex=" + std::to_string(iter->second->GetThreadIndex()) +
257             ", deleteFlag=" + std::to_string(iter->second->GetBufferDeleteFromCacheFlag()) + "\n");
258     }
259     dumpString.append("\n---------RSVkImageManager-DumpVkImageInfo-End----------\n");
260 }
261 
262 } // namespace Rosen
263 } // namespace OHOS