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