1 /*
2 * Copyright (c) 2021-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 "ui/rs_ui_director.h"
17
18 #include "rs_trace.h"
19 #include "sandbox_utils.h"
20
21 #include "animation/rs_animation_trace_utils.h"
22 #include "command/rs_message_processor.h"
23 #include "command/rs_node_command.h"
24 #include "hyper_graphic_manager/core/utils/hgm_command.h"
25 #include "modifier/rs_modifier_manager.h"
26 #include "modifier/rs_modifier_manager_map.h"
27 #include "pipeline/rs_node_map.h"
28 #include "pipeline/rs_render_thread.h"
29 #include "platform/common/rs_log.h"
30 #include "rs_frame_report.h"
31 #include "transaction/rs_application_agent_impl.h"
32 #include "transaction/rs_interfaces.h"
33 #include "transaction/rs_transaction.h"
34 #include "transaction/rs_transaction_proxy.h"
35 #include "ui/rs_frame_rate_policy.h"
36 #include "ui/rs_root_node.h"
37 #include "ui/rs_surface_extractor.h"
38 #include "ui/rs_surface_node.h"
39 #ifdef NEW_RENDER_CONTEXT
40 #include "render_context/memory_handler.h"
41 #endif
42
43 #ifdef _WIN32
44 #include <windows.h>
45 #define gettid GetCurrentThreadId
46 #endif
47
48 #ifdef __APPLE__
49 #define gettid getpid
50 #endif
51
52 #ifdef __gnu_linux__
53 #include <sys/types.h>
54 #include <sys/syscall.h>
55 #define gettid []() -> int32_t { return static_cast<int32_t>(syscall(SYS_gettid)); }
56 #endif
57
58 namespace OHOS {
59 namespace Rosen {
60 static std::unordered_map<RSUIDirector*, TaskRunner> g_uiTaskRunners;
61 static std::mutex g_uiTaskRunnersVisitorMutex;
62 std::function<void()> RSUIDirector::requestVsyncCallback_ = nullptr;
63 static std::mutex g_vsyncCallbackMutex;
64 static std::once_flag g_initDumpNodeTreeProcessorFlag;
65
Create()66 std::shared_ptr<RSUIDirector> RSUIDirector::Create()
67 {
68 return std::shared_ptr<RSUIDirector>(new RSUIDirector());
69 }
70
~RSUIDirector()71 RSUIDirector::~RSUIDirector()
72 {
73 Destroy();
74 }
75
Init(bool shouldCreateRenderThread)76 void RSUIDirector::Init(bool shouldCreateRenderThread)
77 {
78 AnimationCommandHelper::SetAnimationCallbackProcessor(AnimationCallbackProcessor);
79 std::call_once(g_initDumpNodeTreeProcessorFlag, [] () {
80 RSNodeCommandHelper::SetDumpNodeTreeProcessor(RSUIDirector::DumpNodeTreeProcessor);
81 });
82
83 isUniRenderEnabled_ = RSSystemProperties::GetUniRenderEnabled();
84 if (shouldCreateRenderThread && !isUniRenderEnabled_) {
85 auto renderThreadClient = RSIRenderClient::CreateRenderThreadClient();
86 auto transactionProxy = RSTransactionProxy::GetInstance();
87 if (transactionProxy != nullptr) {
88 transactionProxy->SetRenderThreadClient(renderThreadClient);
89 }
90
91 RsFrameReport::GetInstance().Init();
92 if (!cacheDir_.empty()) {
93 RSRenderThread::Instance().SetCacheDir(cacheDir_);
94 }
95 RSRenderThread::Instance().Start();
96 } else {
97 // force fallback animaiions send to RS if no render thread
98 RSNodeMap::Instance().GetAnimationFallbackNode()->isRenderServiceNode_ = true;
99 }
100 if (auto rsApplicationAgent = RSApplicationAgentImpl::Instance()) {
101 rsApplicationAgent->RegisterRSApplicationAgent();
102 }
103
104 GoForeground();
105 RSInterpolator::Init();
106 }
107
SetFlushEmptyCallback(FlushEmptyCallback flushEmptyCallback)108 void RSUIDirector::SetFlushEmptyCallback(FlushEmptyCallback flushEmptyCallback)
109 {
110 auto transactionProxy = RSTransactionProxy::GetInstance();
111 if (transactionProxy != nullptr) {
112 transactionProxy->SetFlushEmptyCallback(flushEmptyCallback);
113 }
114 }
115
StartTextureExport()116 void RSUIDirector::StartTextureExport()
117 {
118 isUniRenderEnabled_ = RSSystemProperties::GetUniRenderEnabled();
119 if (isUniRenderEnabled_) {
120 auto renderThreadClient = RSIRenderClient::CreateRenderThreadClient();
121 auto transactionProxy = RSTransactionProxy::GetInstance();
122 if (transactionProxy != nullptr) {
123 transactionProxy->SetRenderThreadClient(renderThreadClient);
124 }
125 RSRenderThread::Instance().Start();
126 }
127 RSRenderThread::Instance().UpdateWindowStatus(true);
128 }
129
GoForeground(bool isTextureExport)130 void RSUIDirector::GoForeground(bool isTextureExport)
131 {
132 ROSEN_LOGD("RSUIDirector::GoForeground");
133 if (!isActive_) {
134 if (!isUniRenderEnabled_ || isTextureExport) {
135 RSRenderThread::Instance().UpdateWindowStatus(true);
136 }
137 isActive_ = true;
138 if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
139 node->SetEnableRender(true);
140 }
141 auto surfaceNode = surfaceNode_.lock();
142 if (surfaceNode) {
143 surfaceNode->MarkUIHidden(false);
144 surfaceNode->SetAbilityState(RSSurfaceNodeAbilityState::FOREGROUND);
145 }
146 }
147 }
148
GoBackground(bool isTextureExport)149 void RSUIDirector::GoBackground(bool isTextureExport)
150 {
151 ROSEN_LOGD("RSUIDirector::GoBackground");
152 if (isActive_) {
153 if (!isUniRenderEnabled_ || isTextureExport) {
154 RSRenderThread::Instance().UpdateWindowStatus(false);
155 }
156 isActive_ = false;
157 if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
158 node->SetEnableRender(false);
159 }
160 auto surfaceNode = surfaceNode_.lock();
161 if (surfaceNode) {
162 surfaceNode->MarkUIHidden(true);
163 surfaceNode->SetAbilityState(RSSurfaceNodeAbilityState::BACKGROUND);
164 }
165 if (isTextureExport || isUniRenderEnabled_) {
166 return;
167 }
168 // clean bufferQueue cache
169 RSRenderThread::Instance().PostTask([surfaceNode]() {
170 if (surfaceNode != nullptr) {
171 #ifdef NEW_RENDER_CONTEXT
172 std::shared_ptr<RSRenderSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
173 #else
174 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
175 #endif
176 if (rsSurface == nullptr) {
177 ROSEN_LOGE("rsSurface is nullptr");
178 return;
179 }
180 rsSurface->ClearBuffer();
181 }
182 });
183 #if defined(ACE_ENABLE_GL) || defined(ACE_ENABLE_VK)
184 RSRenderThread::Instance().PostTask([this]() {
185 auto renderContext = RSRenderThread::Instance().GetRenderContext();
186 if (renderContext != nullptr) {
187 #ifndef ROSEN_CROSS_PLATFORM
188 #if defined(NEW_RENDER_CONTEXT)
189 auto drawingContext = RSRenderThread::Instance().GetDrawingContext();
190 MemoryHandler::ClearRedundantResources(drawingContext->GetDrawingContext());
191 #else
192 renderContext->ClearRedundantResources();
193 #endif
194 #endif
195 }
196 });
197 #endif
198 }
199 }
200
Destroy(bool isTextureExport)201 void RSUIDirector::Destroy(bool isTextureExport)
202 {
203 if (root_ != 0) {
204 if (!isUniRenderEnabled_ || isTextureExport) {
205 if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
206 node->RemoveFromTree();
207 }
208 }
209 root_ = 0;
210 }
211 GoBackground(isTextureExport);
212 std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
213 g_uiTaskRunners.erase(this);
214 }
215
SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)216 void RSUIDirector::SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)
217 {
218 surfaceNode_ = surfaceNode;
219 AttachSurface();
220 }
221
SetAbilityBGAlpha(uint8_t alpha)222 void RSUIDirector::SetAbilityBGAlpha(uint8_t alpha)
223 {
224 auto node = surfaceNode_.lock();
225 if (!node) {
226 ROSEN_LOGI("RSUIDirector::SetAbilityBGAlpha, surfaceNode_ is nullptr");
227 return;
228 }
229 node->SetAbilityBGAlpha(alpha);
230 }
231
SetRTRenderForced(bool isRenderForced)232 void RSUIDirector::SetRTRenderForced(bool isRenderForced)
233 {
234 RSRenderThread::Instance().SetRTRenderForced(isRenderForced);
235 }
236
SetContainerWindow(bool hasContainerWindow,float density)237 void RSUIDirector::SetContainerWindow(bool hasContainerWindow, float density)
238 {
239 auto node = surfaceNode_.lock();
240 if (!node) {
241 ROSEN_LOGI("RSUIDirector::SetContainerWindow, surfaceNode_ is nullptr");
242 return;
243 }
244 node->SetContainerWindow(hasContainerWindow, density);
245 }
246
SetRoot(NodeId root)247 void RSUIDirector::SetRoot(NodeId root)
248 {
249 if (root_ == root) {
250 ROSEN_LOGW("RSUIDirector::SetRoot, root_ is not change");
251 return;
252 }
253 root_ = root;
254 AttachSurface();
255 }
256
AttachSurface()257 void RSUIDirector::AttachSurface()
258 {
259 auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_);
260 auto surfaceNode = surfaceNode_.lock();
261 if (node != nullptr && surfaceNode != nullptr) {
262 node->AttachRSSurfaceNode(surfaceNode);
263 ROSEN_LOGD("RSUIDirector::AttachSurface [%{public}" PRIu64, surfaceNode->GetId());
264 } else {
265 ROSEN_LOGD("RSUIDirector::AttachSurface not ready");
266 }
267 }
268
SetAppFreeze(bool isAppFreeze)269 void RSUIDirector::SetAppFreeze(bool isAppFreeze)
270 {
271 auto surfaceNode = surfaceNode_.lock();
272 if (surfaceNode != nullptr) {
273 surfaceNode->SetFreeze(isAppFreeze);
274 }
275 }
276
SetRequestVsyncCallback(const std::function<void ()> & callback)277 void RSUIDirector::SetRequestVsyncCallback(const std::function<void()>& callback)
278 {
279 std::unique_lock<std::mutex> lock(g_vsyncCallbackMutex);
280 requestVsyncCallback_ = callback;
281 }
282
SetTimeStamp(uint64_t timeStamp,const std::string & abilityName)283 void RSUIDirector::SetTimeStamp(uint64_t timeStamp, const std::string& abilityName)
284 {
285 timeStamp_ = timeStamp;
286 abilityName_ = abilityName;
287 }
288
SetCacheDir(const std::string & cacheFilePath)289 void RSUIDirector::SetCacheDir(const std::string& cacheFilePath)
290 {
291 cacheDir_ = cacheFilePath;
292 }
293
FlushAnimation(uint64_t timeStamp,int64_t vsyncPeriod)294 bool RSUIDirector::FlushAnimation(uint64_t timeStamp, int64_t vsyncPeriod)
295 {
296 bool hasRunningAnimation = false;
297 auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
298 if (modifierManager != nullptr) {
299 modifierManager->SetDisplaySyncEnable(true);
300 modifierManager->SetFrameRateGetFunc([](const RSPropertyUnit unit, float velocity) -> int32_t {
301 return RSFrameRatePolicy::GetInstance()->GetExpectedFrameRate(unit, velocity);
302 });
303 hasRunningAnimation = modifierManager->Animate(timeStamp, vsyncPeriod);
304 }
305 return hasRunningAnimation;
306 }
307
FlushAnimationStartTime(uint64_t timeStamp)308 void RSUIDirector::FlushAnimationStartTime(uint64_t timeStamp)
309 {
310 auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
311 if (modifierManager != nullptr) {
312 modifierManager->FlushStartAnimation(timeStamp);
313 }
314 }
315
FlushModifier()316 void RSUIDirector::FlushModifier()
317 {
318 auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
319 if (modifierManager == nullptr) {
320 return;
321 }
322
323 modifierManager->Draw();
324 // post animation finish callback(s) to task queue
325 RSUIDirector::RecvMessages();
326 }
327
HasUIRunningAnimation()328 bool RSUIDirector::HasUIRunningAnimation()
329 {
330 auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
331 if (modifierManager != nullptr) {
332 return modifierManager->HasUIRunningAnimation();
333 }
334 return false;
335 }
336
SetUITaskRunner(const TaskRunner & uiTaskRunner,int32_t instanceId)337 void RSUIDirector::SetUITaskRunner(const TaskRunner& uiTaskRunner, int32_t instanceId)
338 {
339 std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
340 instanceId_ = instanceId;
341 g_uiTaskRunners[this] = uiTaskRunner;
342 if (!isHgmConfigChangeCallbackReg_) {
343 RSFrameRatePolicy::GetInstance()->RegisterHgmConfigChangeCallback();
344 isHgmConfigChangeCallbackReg_ = true;
345 }
346 }
347
SendMessages()348 void RSUIDirector::SendMessages()
349 {
350 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "SendCommands");
351 auto transactionProxy = RSTransactionProxy::GetInstance();
352 if (transactionProxy != nullptr) {
353 transactionProxy->FlushImplicitTransaction(timeStamp_, abilityName_);
354 index_ = transactionProxy->GetTransactionDataIndex();
355 } else {
356 RS_LOGE_LIMIT(__func__, __line__, "RSUIDirector::SendMessages failed, transactionProxy is nullptr");
357 }
358 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
359 }
360
GetIndex() const361 uint32_t RSUIDirector::GetIndex() const
362 {
363 return index_;
364 }
365
RecvMessages()366 void RSUIDirector::RecvMessages()
367 {
368 if (GetRealPid() == -1) {
369 return;
370 }
371 static const uint32_t pid = static_cast<uint32_t>(GetRealPid());
372 if (!RSMessageProcessor::Instance().HasTransaction(pid)) {
373 return;
374 }
375 auto transactionDataPtr = RSMessageProcessor::Instance().GetTransaction(pid);
376 RecvMessages(transactionDataPtr);
377 }
378
RecvMessages(std::shared_ptr<RSTransactionData> cmds)379 void RSUIDirector::RecvMessages(std::shared_ptr<RSTransactionData> cmds)
380 {
381 if (cmds == nullptr || cmds->IsEmpty()) {
382 return;
383 }
384 ROSEN_LOGD("ProcessMessages begin");
385 RSUIDirector::ProcessMessages(cmds);
386 }
387
ProcessMessages(std::shared_ptr<RSTransactionData> cmds)388 void RSUIDirector::ProcessMessages(std::shared_ptr<RSTransactionData> cmds)
389 {
390 // message ID for correspondence UI thread and IPC thread
391 static uint32_t messageId = 0;
392 std::map<int32_t, std::vector<std::unique_ptr<RSCommand>>> m;
393 for (auto &[id, _, cmd] : cmds->GetPayload()) {
394 NodeId realId = (id == 0 && cmd) ? cmd->GetNodeId() : id;
395 int32_t instanceId = RSNodeMap::Instance().GetNodeInstanceId(realId);
396 if (instanceId == INSTANCE_ID_UNDEFINED) {
397 instanceId = RSNodeMap::Instance().GetInstanceIdForReleasedNode(realId);
398 }
399 m[instanceId].push_back(std::move(cmd));
400 }
401 auto msgId = ++messageId;
402 RS_TRACE_NAME_FMT("RSUIDirector::ProcessMessages [messageId:%lu,cmdIndex:%llu,cmdCount:%lu]",
403 msgId, cmds->GetIndex(), cmds->GetCommandCount());
404 auto counter = std::make_shared<std::atomic_size_t>(m.size());
405 for (auto &[instanceId, commands] : m) {
406 ROSEN_LOGI("RSUIDirector::ProcessMessages messageId:%{public}d, cmdCount:%{public}lu, "
407 "instanceId:%{public}d", msgId, static_cast<unsigned long>(commands.size()), instanceId);
408 PostTask(
409 [cmds = std::make_shared<std::vector<std::unique_ptr<RSCommand>>>(std::move(commands)),
410 counter, msgId, tempInstanceId = instanceId] {
411 RS_TRACE_NAME_FMT("RSUIDirector::ProcessMessages PostTask messageId [%lu]", msgId);
412 ROSEN_LOGI("RSUIDirector::PostTask messageId:%{public}d, cmdCount:%{public}lu, instanceId:%{public}d",
413 msgId, static_cast<unsigned long>(cmds->size()), tempInstanceId);
414 for (auto &cmd : *cmds) {
415 RSContext context; // RSCommand->process() needs it
416 cmd->Process(context);
417 }
418 if (counter->fetch_sub(1) == 1) {
419 std::unique_lock<std::mutex> lock(g_vsyncCallbackMutex);
420 if (requestVsyncCallback_ != nullptr) {
421 requestVsyncCallback_();
422 } else {
423 RSTransaction::FlushImplicitTransaction();
424 }
425 ROSEN_LOGD("ProcessMessages end");
426 }
427 }, instanceId);
428 }
429 }
430
AnimationCallbackProcessor(NodeId nodeId,AnimationId animId,AnimationCallbackEvent event)431 void RSUIDirector::AnimationCallbackProcessor(NodeId nodeId, AnimationId animId, AnimationCallbackEvent event)
432 {
433 RSAnimationTraceUtils::GetInstance().addAnimationFinishTrace(
434 "Animation FinishCallback Processor", nodeId, animId, false);
435 // try find the node by nodeId
436 if (auto nodePtr = RSNodeMap::Instance().GetNode<RSNode>(nodeId)) {
437 if (!nodePtr->AnimationCallback(animId, event)) {
438 ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %{public}" PRIu64 ""
439 "on node %{public}" PRIu64, animId, nodeId);
440 }
441 return;
442 }
443
444 // if node not found, try fallback node
445 auto& fallbackNode = RSNodeMap::Instance().GetAnimationFallbackNode();
446 if (fallbackNode && fallbackNode->AnimationCallback(animId, event)) {
447 ROSEN_LOGD("RSUIDirector::AnimationCallbackProcessor, found animation %{public}" PRIu64 " on fallback node.",
448 animId);
449 } else {
450 ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %{public}" PRIu64 " on"
451 " fallback node.", animId);
452 }
453 }
454
DumpNodeTreeProcessor(NodeId nodeId,pid_t pid,uint32_t taskId)455 void RSUIDirector::DumpNodeTreeProcessor(NodeId nodeId, pid_t pid, uint32_t taskId)
456 {
457 RS_TRACE_NAME_FMT("DumpClientNodeTree dump task[%u] node[%" PRIu64 "]", taskId, nodeId);
458 ROSEN_LOGI("DumpNodeTreeProcessor task[%{public}u] node[%" PRIu64 "]", taskId, nodeId);
459
460 std::string out;
461 // use for dump transactionFlags [pid,index] in client tree dump
462 int32_t instanceId = RSNodeMap::Instance().GetNodeInstanceId(nodeId);
463 {
464 std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
465 for (const auto &[director, taskRunner] : g_uiTaskRunners) {
466 if (director->instanceId_ == instanceId) {
467 out.append("transactionFlags:[ ").append(std::to_string(pid).append(", ")
468 .append(std::to_string(director->index_)).append("]\r"));
469 break;
470 }
471 }
472 }
473
474 if (auto node = RSNodeMap::Instance().GetNode(nodeId)) {
475 constexpr int TOP_LEVEL_DEPTH = 1;
476 node->DumpTree(TOP_LEVEL_DEPTH, out);
477 }
478
479 auto transactionProxy = RSTransactionProxy::GetInstance();
480 if (transactionProxy != nullptr) {
481 std::unique_ptr<RSCommand> command = std::make_unique<RSCommitDumpClientNodeTree>(
482 nodeId, getpid(), taskId, out);
483 transactionProxy->AddCommand(command, true);
484 RSTransaction::FlushImplicitTransaction();
485 }
486 }
487
PostFrameRateTask(const std::function<void ()> & task)488 void RSUIDirector::PostFrameRateTask(const std::function<void()>& task)
489 {
490 PostTask(task);
491 }
492
PostTask(const std::function<void ()> & task,int32_t instanceId)493 void RSUIDirector::PostTask(const std::function<void()>& task, int32_t instanceId)
494 {
495 PostDelayTask(task, 0, instanceId);
496 }
497
PostDelayTask(const std::function<void ()> & task,uint32_t delay,int32_t instanceId)498 void RSUIDirector::PostDelayTask(const std::function<void()>& task, uint32_t delay, int32_t instanceId)
499 {
500 std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
501 for (const auto &[director, taskRunner] : g_uiTaskRunners) {
502 if (director->instanceId_ != instanceId) {
503 continue;
504 }
505 ROSEN_LOGD("RSUIDirector::PostTask instanceId=%{public}d success", instanceId);
506 taskRunner(task, delay);
507 return;
508 }
509 if (instanceId != INSTANCE_ID_UNDEFINED) {
510 ROSEN_LOGW("RSUIDirector::PostTask instanceId=%{public}d not found", instanceId);
511 }
512 for (const auto &[_, taskRunner] : g_uiTaskRunners) {
513 ROSEN_LOGD("RSUIDirector::PostTask success");
514 taskRunner(task, delay);
515 return;
516 }
517 }
518
GetCurrentRefreshRateMode()519 int32_t RSUIDirector::GetCurrentRefreshRateMode()
520 {
521 return RSFrameRatePolicy::GetInstance()->GetRefreshRateModeName();
522 }
523
GetAnimateExpectedRate() const524 int32_t RSUIDirector::GetAnimateExpectedRate() const
525 {
526 int32_t animateRate = 0;
527 auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
528 if (modifierManager != nullptr) {
529 auto& range = modifierManager->GetFrameRateRange();
530 if (range.IsValid()) {
531 animateRate = range.preferred_;
532 }
533 }
534 return animateRate;
535 }
536 } // namespace Rosen
537 } // namespace OHOS
538