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