1 /*
2 * Copyright (c) 2021-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 "ui/rs_ui_director.h"
17
18 #include "rs_trace.h"
19 #include "sandbox_utils.h"
20
21 #include "command/rs_message_processor.h"
22 #include "modifier/rs_modifier_manager.h"
23 #include "modifier/rs_modifier_manager_map.h"
24 #include "pipeline/rs_frame_report.h"
25 #include "pipeline/rs_node_map.h"
26 #include "pipeline/rs_render_thread.h"
27 #include "platform/common/rs_log.h"
28 #include "transaction/rs_application_agent_impl.h"
29 #include "transaction/rs_interfaces.h"
30 #include "transaction/rs_transaction_proxy.h"
31 #include "ui/rs_root_node.h"
32 #include "ui/rs_surface_extractor.h"
33 #include "ui/rs_surface_node.h"
34 #ifdef NEW_RENDER_CONTEXT
35 #include "render_context/memory_handler.h"
36 #endif
37
38 #ifdef _WIN32
39 #include <windows.h>
40 #define gettid GetCurrentThreadId
41 #endif
42
43 #ifdef __APPLE__
44 #define gettid getpid
45 #endif
46
47 #ifdef __gnu_linux__
48 #include <sys/types.h>
49 #include <sys/syscall.h>
50 #define gettid []() -> int32_t { return static_cast<int32_t>(syscall(SYS_gettid)); }
51 #endif
52
53 namespace OHOS {
54 namespace Rosen {
55 static std::unordered_map<RSUIDirector*, TaskRunner> g_uiTaskRunners;
56 static std::mutex g_uiTaskRunnersVisitorMutex;
57
Create()58 std::shared_ptr<RSUIDirector> RSUIDirector::Create()
59 {
60 return std::shared_ptr<RSUIDirector>(new RSUIDirector());
61 }
62
~RSUIDirector()63 RSUIDirector::~RSUIDirector()
64 {
65 Destroy();
66 }
67
Init(bool shouldCreateRenderThread)68 void RSUIDirector::Init(bool shouldCreateRenderThread)
69 {
70 AnimationCommandHelper::SetAnimationCallbackProcessor(AnimationCallbackProcessor);
71
72 isUniRenderEnabled_ = RSSystemProperties::GetUniRenderEnabled();
73 if (shouldCreateRenderThread && !isUniRenderEnabled_) {
74 auto renderThreadClient = RSIRenderClient::CreateRenderThreadClient();
75 auto transactionProxy = RSTransactionProxy::GetInstance();
76 if (transactionProxy != nullptr) {
77 transactionProxy->SetRenderThreadClient(renderThreadClient);
78 }
79
80 RsFrameReport::GetInstance().Init();
81 if (!cacheDir_.empty()) {
82 RSRenderThread::Instance().SetCacheDir(cacheDir_);
83 }
84 RSRenderThread::Instance().Start();
85 } else {
86 // force fallback animaiions send to RS if no render thread
87 RSNodeMap::Instance().GetAnimationFallbackNode()->isRenderServiceNode_ = true;
88 }
89 RSApplicationAgentImpl::Instance().RegisterRSApplicationAgent();
90
91 GoForeground();
92 }
93
GoForeground()94 void RSUIDirector::GoForeground()
95 {
96 ROSEN_LOGD("RSUIDirector::GoForeground");
97 if (!isActive_) {
98 if (!isUniRenderEnabled_) {
99 RSRenderThread::Instance().UpdateWindowStatus(true);
100 }
101 isActive_ = true;
102 if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
103 node->SetEnableRender(true);
104 }
105 auto surfaceNode = surfaceNode_.lock();
106 if (surfaceNode) {
107 surfaceNode->MarkUIHidden(false);
108 }
109 }
110 }
111
GoBackground()112 void RSUIDirector::GoBackground()
113 {
114 ROSEN_LOGD("RSUIDirector::GoBackground");
115 if (isActive_) {
116 if (!isUniRenderEnabled_) {
117 RSRenderThread::Instance().UpdateWindowStatus(false);
118 }
119 isActive_ = false;
120 if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
121 node->SetEnableRender(false);
122 }
123 auto surfaceNode = surfaceNode_.lock();
124 if (surfaceNode) {
125 surfaceNode->MarkUIHidden(true);
126 }
127 // clean bufferQueue cache
128 RSRenderThread::Instance().PostTask([surfaceNode]() {
129 if (surfaceNode != nullptr) {
130 #ifdef NEW_RENDER_CONTEXT
131 std::shared_ptr<RSRenderSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
132 #else
133 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
134 #endif
135 rsSurface->ClearBuffer();
136 }
137 });
138 #ifdef ACE_ENABLE_GL
139 RSRenderThread::Instance().PostTask([this]() {
140 auto renderContext = RSRenderThread::Instance().GetRenderContext();
141 if (renderContext != nullptr) {
142 #ifndef ROSEN_CROSS_PLATFORM
143 #if defined(NEW_RENDER_CONTEXT)
144 auto drawingContext = RSRenderThread::Instance().GetDrawingContext();
145 MemoryHandler::ClearRedundantResources(drawingContext->GetDrawingContext());
146 #else
147 renderContext->ClearRedundantResources();
148 #endif
149 #endif
150 }
151 });
152 #endif
153 }
154 }
155
Destroy()156 void RSUIDirector::Destroy()
157 {
158 if (root_ != 0) {
159 if (!isUniRenderEnabled_) {
160 if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
161 node->RemoveFromTree();
162 }
163 }
164 root_ = 0;
165 }
166 GoBackground();
167 std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
168 g_uiTaskRunners.erase(this);
169 }
170
SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)171 void RSUIDirector::SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)
172 {
173 surfaceNode_ = surfaceNode;
174 AttachSurface();
175 }
176
SetAbilityBGAlpha(uint8_t alpha)177 void RSUIDirector::SetAbilityBGAlpha(uint8_t alpha)
178 {
179 auto node = surfaceNode_.lock();
180 if (!node) {
181 ROSEN_LOGI("RSUIDirector::SetAbilityBGAlpha, surfaceNode_ is nullptr");
182 return;
183 }
184 node->SetAbilityBGAlpha(alpha);
185 }
186
SetRTRenderForced(bool isRenderForced)187 void RSUIDirector::SetRTRenderForced(bool isRenderForced)
188 {
189 RSRenderThread::Instance().SetRTRenderForced(isRenderForced);
190 }
191
SetContainerWindow(bool hasContainerWindow,float density)192 void RSUIDirector::SetContainerWindow(bool hasContainerWindow, float density)
193 {
194 auto node = surfaceNode_.lock();
195 if (!node) {
196 ROSEN_LOGI("RSUIDirector::SetContainerWindow, surfaceNode_ is nullptr");
197 return;
198 }
199 node->SetContainerWindow(hasContainerWindow, density);
200 }
201
SetRoot(NodeId root)202 void RSUIDirector::SetRoot(NodeId root)
203 {
204 if (root_ == root) {
205 ROSEN_LOGW("RSUIDirector::SetRoot, root_ is not change");
206 return;
207 }
208 root_ = root;
209 AttachSurface();
210 }
211
AttachSurface()212 void RSUIDirector::AttachSurface()
213 {
214 auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_);
215 auto surfaceNode = surfaceNode_.lock();
216 if (node != nullptr && surfaceNode != nullptr) {
217 node->AttachRSSurfaceNode(surfaceNode);
218 ROSEN_LOGD("RSUIDirector::AttachSurface [%" PRIu64 "]", surfaceNode->GetId());
219 } else {
220 ROSEN_LOGD("RSUIDirector::AttachSurface not ready");
221 }
222 }
223
SetAppFreeze(bool isAppFreeze)224 void RSUIDirector::SetAppFreeze(bool isAppFreeze)
225 {
226 auto surfaceNode = surfaceNode_.lock();
227 if (surfaceNode != nullptr) {
228 surfaceNode->SetFreeze(isAppFreeze);
229 }
230 }
231
SetTimeStamp(uint64_t timeStamp,const std::string & abilityName)232 void RSUIDirector::SetTimeStamp(uint64_t timeStamp, const std::string& abilityName)
233 {
234 timeStamp_ = timeStamp;
235 abilityName_ = abilityName;
236 }
237
SetCacheDir(const std::string & cacheFilePath)238 void RSUIDirector::SetCacheDir(const std::string& cacheFilePath)
239 {
240 cacheDir_ = cacheFilePath;
241 }
242
RunningCustomAnimation(uint64_t timeStamp)243 bool RSUIDirector::RunningCustomAnimation(uint64_t timeStamp)
244 {
245 bool hasRunningAnimation = false;
246 auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
247 if (modifierManager == nullptr) {
248 return hasRunningAnimation;
249 }
250
251 hasRunningAnimation = modifierManager->Animate(timeStamp);
252 modifierManager->Draw();
253
254 // post animation finish callback(s) to task queue
255 RSUIDirector::RecvMessages();
256 return hasRunningAnimation;
257 }
258
SetUITaskRunner(const TaskRunner & uiTaskRunner)259 void RSUIDirector::SetUITaskRunner(const TaskRunner& uiTaskRunner)
260 {
261 std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
262 g_uiTaskRunners[this] = uiTaskRunner;
263 }
264
SendMessages()265 void RSUIDirector::SendMessages()
266 {
267 ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "SendCommands");
268 auto transactionProxy = RSTransactionProxy::GetInstance();
269 if (transactionProxy != nullptr) {
270 transactionProxy->FlushImplicitTransaction(timeStamp_, abilityName_);
271 }
272 ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
273 }
274
RecvMessages()275 void RSUIDirector::RecvMessages()
276 {
277 if (GetRealPid() == -1) {
278 return;
279 }
280 static const uint32_t pid = static_cast<uint32_t>(GetRealPid());
281 static std::mutex recvMessagesMutex;
282 std::unique_lock<std::mutex> lock(recvMessagesMutex);
283 if (RSMessageProcessor::Instance().HasTransaction(pid)) {
284 auto transactionDataPtr = RSMessageProcessor::Instance().GetTransaction(pid);
285 RecvMessages(transactionDataPtr);
286 }
287 }
288
RecvMessages(std::shared_ptr<RSTransactionData> cmds)289 void RSUIDirector::RecvMessages(std::shared_ptr<RSTransactionData> cmds)
290 {
291 if (cmds == nullptr || cmds->IsEmpty()) {
292 return;
293 }
294 ROSEN_LOGD("RSUIDirector::RecvMessages success");
295 PostTask([cmds]() {
296 ROSEN_LOGD("RSUIDirector::ProcessMessages success");
297 RSUIDirector::ProcessMessages(cmds);
298 });
299 }
300
ProcessMessages(std::shared_ptr<RSTransactionData> cmds)301 void RSUIDirector::ProcessMessages(std::shared_ptr<RSTransactionData> cmds)
302 {
303 static RSContext context; // RSCommand->process() needs it
304 cmds->Process(context);
305 }
306
AnimationCallbackProcessor(NodeId nodeId,AnimationId animId,AnimationCallbackEvent event)307 void RSUIDirector::AnimationCallbackProcessor(NodeId nodeId, AnimationId animId, AnimationCallbackEvent event)
308 {
309 // try find the node by nodeId
310 if (auto nodePtr = RSNodeMap::Instance().GetNode<RSNode>(nodeId)) {
311 if (!nodePtr->AnimationCallback(animId, event)) {
312 ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %" PRIu64 " on node %" PRIu64
313 ".", animId, nodeId);
314 }
315 return;
316 }
317
318 // if node not found, try fallback node
319 auto& fallbackNode = RSNodeMap::Instance().GetAnimationFallbackNode();
320 if (fallbackNode && fallbackNode->AnimationCallback(animId, event)) {
321 ROSEN_LOGD("RSUIDirector::AnimationCallbackProcessor, found animation %" PRIu64 " on fallback node.", animId);
322 } else {
323 ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %" PRIu64 " on fallback node.",
324 animId);
325 }
326 }
327
PostTask(const std::function<void ()> & task)328 void RSUIDirector::PostTask(const std::function<void()>& task)
329 {
330 std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
331 for (auto [_, taskRunner] : g_uiTaskRunners) {
332 if (taskRunner == nullptr) {
333 ROSEN_LOGE("RSUIDirector::PostTask, uiTaskRunner is null");
334 continue;
335 }
336 ROSEN_LOGD("RSUIDirector::PostTask success");
337 taskRunner(task);
338 return;
339 }
340 }
341 } // namespace Rosen
342 } // namespace OHOS
343