• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "ipc_callbacks/rs_surface_buffer_callback.h"
17 #include "pipeline/rs_draw_cmd.h"
18 #include "pipeline/rs_surface_buffer_callback_manager.h"
19 #include "platform/common/rs_log.h"
20 #include "platform/common/rs_system_properties.h"
21 #include "rs_trace.h"
22 
23 namespace OHOS {
24 namespace Rosen {
Instance()25 RSSurfaceBufferCallbackManager& RSSurfaceBufferCallbackManager::Instance()
26 {
27     static RSSurfaceBufferCallbackManager surfaceBufferCallbackMgr;
28     return surfaceBufferCallbackMgr;
29 }
30 
SetRunPolicy(std::function<void (std::function<void ()>)> runPolicy)31 void RSSurfaceBufferCallbackManager::SetRunPolicy(
32     std::function<void(std::function<void()>)> runPolicy)
33 {
34     runPolicy_ = runPolicy;
35 }
36 
SetVSyncFuncs(VSyncFuncs vSyncFuncs)37 void RSSurfaceBufferCallbackManager::SetVSyncFuncs(VSyncFuncs vSyncFuncs)
38 {
39     vSyncFuncs_ = vSyncFuncs;
40 }
41 
SetIsUniRender(bool isUniRender)42 void RSSurfaceBufferCallbackManager::SetIsUniRender(bool isUniRender)
43 {
44     isUniRender_ = isUniRender;
45 }
46 
47 #ifdef RS_ENABLE_VK
SetReleaseFenceForVulkan(int releaseFenceFd,NodeId rootNodeId)48 void RSSurfaceBufferCallbackManager::SetReleaseFenceForVulkan(
49     int releaseFenceFd, NodeId rootNodeId)
50 {
51     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
52         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
53         return;
54     }
55     std::lock_guard<std::mutex> lock { surfaceBufferOpItemMutex_ };
56     for (auto& [_, data] : stagingSurfaceBufferIds_) {
57         auto& fences = data.releaseFences;
58         size_t idx = 0;
59         for (auto& fence : fences) {
60             if (data.isRenderedFlags[idx] && data.rootNodeIds[idx] == rootNodeId) {
61                 fence = new (std::nothrow) SyncFence(::dup(releaseFenceFd));
62                 if (!fence) {
63                     RS_LOGE("RSSurfaceBufferCallbackManager::SetReleaseFenceForVulkan"
64                         " Err on creating SyncFence");
65                 }
66             }
67             ++idx;
68         }
69     }
70 }
71 #endif
72 
RegisterSurfaceBufferCallback(pid_t pid,uint64_t uid,sptr<RSISurfaceBufferCallback> callback)73 void RSSurfaceBufferCallbackManager::RegisterSurfaceBufferCallback(pid_t pid, uint64_t uid,
74     sptr<RSISurfaceBufferCallback> callback)
75 {
76     std::unique_lock<std::shared_mutex> lock { registerSurfaceBufferCallbackMutex_ };
77     auto iter = surfaceBufferCallbacks_.find({pid, uid});
78     if (iter == std::end(surfaceBufferCallbacks_)) {
79         surfaceBufferCallbacks_.insert({{pid, uid}, callback});
80     } else {
81         RS_LOGE("RSSurfaceBufferCallbackManager::RegisterSurfaceBufferCallback Pair:"
82             "[Pid: %{public}s, Uid: %{public}s] exists.",
83             std::to_string(pid).c_str(), std::to_string(uid).c_str());
84     }
85 }
86 
UnregisterSurfaceBufferCallback(pid_t pid)87 void RSSurfaceBufferCallbackManager::UnregisterSurfaceBufferCallback(pid_t pid)
88 {
89     std::unique_lock<std::shared_mutex> lock { registerSurfaceBufferCallbackMutex_ };
90     EraseIf(surfaceBufferCallbacks_, [pid](const auto& pair) {
91         return pair.first.first == pid;
92     });
93 }
94 
UnregisterSurfaceBufferCallback(pid_t pid,uint64_t uid)95 void RSSurfaceBufferCallbackManager::UnregisterSurfaceBufferCallback(pid_t pid, uint64_t uid)
96 {
97     std::unique_lock<std::shared_mutex> lock { registerSurfaceBufferCallbackMutex_ };
98     auto iter = surfaceBufferCallbacks_.find({pid, uid});
99     if (iter == std::end(surfaceBufferCallbacks_)) {
100         RS_LOGE("RSSurfaceBufferCallbackManager::UnregisterSurfaceBufferCallback Pair:"
101             "[Pid: %{public}s, Uid: %{public}s] not exists.",
102             std::to_string(pid).c_str(), std::to_string(uid).c_str());
103     } else {
104         surfaceBufferCallbacks_.erase(iter);
105     }
106 }
107 
108 #ifdef ROSEN_OHOS
GetOnFinishCb() const109 RSSurfaceBufferCallbackManager::OnFinishCb RSSurfaceBufferCallbackManager::GetOnFinishCb(
110     ) const
111 {
112     auto mutablePtr = const_cast<RSSurfaceBufferCallbackManager*>(this);
113     return [mutablePtr](const Drawing::DrawSurfaceBufferFinishCbData& data) {
114         mutablePtr->OnFinish(data);
115     };
116 }
117 
GetOnAfterAcquireBufferCb() const118 RSSurfaceBufferCallbackManager::OnAfterAcquireBufferCb RSSurfaceBufferCallbackManager::GetOnAfterAcquireBufferCb(
119     ) const
120 {
121     auto mutablePtr = const_cast<RSSurfaceBufferCallbackManager*>(this);
122     return [mutablePtr](const Drawing::DrawSurfaceBufferAfterAcquireCbData& data) {
123         mutablePtr->OnAfterAcquireBuffer(data);
124     };
125 }
126 #endif
127 
GetSurfaceBufferCallback(pid_t pid,uint64_t uid) const128 sptr<RSISurfaceBufferCallback> RSSurfaceBufferCallbackManager::GetSurfaceBufferCallback(
129     pid_t pid, uint64_t uid) const
130 {
131     std::shared_lock<std::shared_mutex> lock { registerSurfaceBufferCallbackMutex_ };
132     auto iter = surfaceBufferCallbacks_.find({pid, uid});
133     if (iter == std::cend(surfaceBufferCallbacks_)) {
134         RS_LOGE("RSSurfaceBufferCallbackManager::GetSurfaceBufferCallback Pair:"
135             "[Pid: %{public}s, Uid: %{public}s] not exists.",
136             std::to_string(pid).c_str(), std::to_string(uid).c_str());
137         return nullptr;
138     }
139     return iter->second;
140 }
141 
GetSurfaceBufferCallbackSize() const142 size_t RSSurfaceBufferCallbackManager::GetSurfaceBufferCallbackSize() const
143 {
144     std::shared_lock<std::shared_mutex> lock { registerSurfaceBufferCallbackMutex_ };
145     return surfaceBufferCallbacks_.size();
146 }
147 
148 #ifdef ROSEN_OHOS
EnqueueSurfaceBufferId(const Drawing::DrawSurfaceBufferFinishCbData & data)149 void RSSurfaceBufferCallbackManager::EnqueueSurfaceBufferId(
150     const Drawing::DrawSurfaceBufferFinishCbData& data)
151 {
152     auto iter = stagingSurfaceBufferIds_.find({data.pid, data.uid});
153     if (iter == std::end(stagingSurfaceBufferIds_)) {
154         std::tie(iter, std::ignore) = stagingSurfaceBufferIds_.insert({{data.pid, data.uid}, {}});
155     }
156     auto& [surfaceBufferIds, isRenderedFlags, fences, rootNodeIds] = iter->second;
157     surfaceBufferIds.push_back(data.surfaceBufferId);
158     isRenderedFlags.push_back(static_cast<uint8_t>(data.isRendered));
159     fences.push_back(data.releaseFence);
160     rootNodeIds.push_back(data.rootNodeId);
161 }
162 #endif
163 
RequestNextVSync()164 void RSSurfaceBufferCallbackManager::RequestNextVSync()
165 {
166     if (vSyncFuncs_.isRequestedNextVSync && !std::invoke(vSyncFuncs_.isRequestedNextVSync)) {
167         if (vSyncFuncs_.requestNextVsync) {
168             std::invoke(vSyncFuncs_.requestNextVsync);
169         }
170     }
171 }
172 
173 #ifdef ROSEN_OHOS
OnFinish(const Drawing::DrawSurfaceBufferFinishCbData & data)174 void RSSurfaceBufferCallbackManager::OnFinish(
175     const Drawing::DrawSurfaceBufferFinishCbData& data)
176 {
177     if (auto callback = GetSurfaceBufferCallback(data.pid, data.uid)) {
178         if (data.isNeedTriggerCbDirectly) {
179             callback->OnFinish({
180                 .uid = data.uid,
181                 .surfaceBufferIds = { data.surfaceBufferId },
182                 .isRenderedFlags = { static_cast<uint8_t>(data.isRendered) },
183                 .releaseFences = { data.releaseFence },
184                 .isUniRender = isUniRender_,
185             });
186         } else {
187             {
188                 std::lock_guard<std::mutex> lock { surfaceBufferOpItemMutex_ };
189                 EnqueueSurfaceBufferId(data);
190             }
191             RequestNextVSync();
192         }
193     } else {
194         RS_LOGE("RSSurfaceBufferCallbackManager::OnFinish Pair:"
195             "[Pid: %{public}s, Uid: %{public}s] Callback not exists.",
196             std::to_string(data.pid).c_str(), std::to_string(data.uid).c_str());
197     }
198 }
199 
OnAfterAcquireBuffer(const Drawing::DrawSurfaceBufferAfterAcquireCbData & data)200 void RSSurfaceBufferCallbackManager::OnAfterAcquireBuffer(
201     const Drawing::DrawSurfaceBufferAfterAcquireCbData& data)
202 {
203     if (auto callback = GetSurfaceBufferCallback(data.pid, data.uid)) {
204         callback->OnAfterAcquireBuffer({
205             .uid = data.uid,
206             .isUniRender = isUniRender_,
207         });
208     } else {
209         RS_LOGE("RSSurfaceBufferCallbackManager::OnAfterAcquireBuffer Pair:"
210             "[Pid: %{public}s, Uid: %{public}s] Callback not exists.",
211             std::to_string(data.pid).c_str(), std::to_string(data.uid).c_str());
212     }
213 }
214 #endif
215 
SerializeBufferIdVec(const std::vector<uint32_t> & bufferIdVec)216 std::string RSSurfaceBufferCallbackManager::SerializeBufferIdVec(
217     const std::vector<uint32_t>& bufferIdVec)
218 {
219     std::string ret;
220     for (const auto& id : bufferIdVec) {
221         ret += std::to_string(id) + ",";
222     }
223     if (!ret.empty()) {
224         ret.pop_back();
225     }
226     return ret;
227 }
228 
RunSurfaceBufferCallback()229 void RSSurfaceBufferCallbackManager::RunSurfaceBufferCallback()
230 {
231     if (GetSurfaceBufferCallbackSize() == 0) {
232         return;
233     }
234     runPolicy_([this]() {
235         std::map<std::pair<pid_t, uint64_t>, BufferQueueData> surfaceBufferIds;
236         {
237             std::lock_guard<std::mutex> lock { surfaceBufferOpItemMutex_ };
238             surfaceBufferIds.swap(stagingSurfaceBufferIds_);
239         }
240         bool isNeedRequestNextVSync = false;
241         for (auto& [code, data] : surfaceBufferIds) {
242             auto [pid, uid] = code;
243             auto callback = GetSurfaceBufferCallback(pid, uid);
244             if (callback) {
245                 if (!data.bufferIds.empty()) {
246                     isNeedRequestNextVSync = true;
247                 } else {
248                     continue;
249                 }
250                 RS_TRACE_NAME_FMT("RSSurfaceBufferCallbackManager::RunSurfaceBufferCallback"
251                     "Release Buffer %s", SerializeBufferIdVec(data.bufferIds).c_str());
252                 callback->OnFinish({
253                     .uid = uid,
254                     .surfaceBufferIds = std::move(data.bufferIds),
255                     .isRenderedFlags = std::move(data.isRenderedFlags),
256 #ifdef ROSEN_OHOS
257                     .releaseFences = std::move(data.releaseFences),
258 #endif
259                     .isUniRender = isUniRender_,
260                 });
261             }
262         }
263         if (isNeedRequestNextVSync) {
264             RequestNextVSync();
265         }
266     });
267 }
268 
269 #ifdef RS_ENABLE_VK
RunSurfaceBufferSubCallbackForVulkan(NodeId rootNodeId)270 void RSSurfaceBufferCallbackManager::RunSurfaceBufferSubCallbackForVulkan(NodeId rootNodeId)
271 {
272     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
273         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
274         return;
275     }
276 
277     if (GetSurfaceBufferCallbackSize() == 0) {
278         return;
279     }
280 
281     // Step 1: Extract BufferQueueData by RootNodeId
282     std::map<std::pair<pid_t, uint64_t>, BufferQueueData> surfaceBufferIds;
283     {
284         std::lock_guard<std::mutex> lock { surfaceBufferOpItemMutex_ };
285         for (auto &[code, data] : stagingSurfaceBufferIds_) {
286             auto [pid, uid] = code;
287             auto& dstBufferQueueData = surfaceBufferIds[{pid, uid}];
288             auto bufferQueueDataBegin = std::tuple {
289                 data.bufferIds.begin(), data.isRenderedFlags.begin(),
290                 data.releaseFences.begin(), data.rootNodeIds.begin() };
291             auto bufferQueueDataEnd = std::tuple {
292                 data.bufferIds.end(), data.isRenderedFlags.end(),
293                 data.releaseFences.end(), data.rootNodeIds.end() };
294             static auto runCondition = [rootNodeId](auto iterTuple) {
295                 return rootNodeId == *std::get<ROOTNODEIDS_POS>(iterTuple);
296             };
297             (void) RSSurfaceBufferCallbackMgrUtil::CopyIf(
298                 bufferQueueDataBegin, bufferQueueDataEnd,
299                 std::tuple {
300                     std::back_inserter(dstBufferQueueData.bufferIds),
301                     std::back_inserter(dstBufferQueueData.isRenderedFlags),
302                     std::back_inserter(dstBufferQueueData.releaseFences),
303                     std::back_inserter(dstBufferQueueData.rootNodeIds),
304                 }, runCondition);
305             auto partitionPoint = RSSurfaceBufferCallbackMgrUtil::RemoveIf(
306                 bufferQueueDataBegin, bufferQueueDataEnd, runCondition);
307             auto resizeSize = std::distance(
308                 data.bufferIds.begin(), std::get<0>(partitionPoint));
309             data.bufferIds.resize(resizeSize);
310             data.isRenderedFlags.resize(resizeSize);
311             data.releaseFences.resize(resizeSize);
312             data.rootNodeIds.resize(resizeSize);
313         }
314     }
315 
316     // step 2: Send BufferQueueData to Arkui
317     bool isNeedRequestNextVSync = false;
318     for (auto& [code, data] : surfaceBufferIds) {
319         auto [pid, uid] = code;
320         auto callback = GetSurfaceBufferCallback(pid, uid);
321         if (callback) {
322             if (!data.bufferIds.empty()) {
323                 isNeedRequestNextVSync = true;
324             } else {
325                 continue;
326             }
327             RS_TRACE_NAME_FMT("RSSurfaceBufferCallbackManager::RunSurfaceBufferSubCallbackForVulkan"
328                 "Release Buffer %s", SerializeBufferIdVec(data.bufferIds).c_str());
329             callback->OnFinish({
330                 .uid = uid,
331                 .surfaceBufferIds = std::move(data.bufferIds),
332                 .isRenderedFlags = std::move(data.isRenderedFlags),
333                 .releaseFences = std::move(data.releaseFences),
334                 .isUniRender = isUniRender_,
335             });
336         }
337     }
338     if (isNeedRequestNextVSync) {
339         RequestNextVSync();
340     }
341 }
342 #endif
343 } // namespace Rosen
344 } // namespace OHOS