• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h"
31 #include "transaction/rs_transaction_proxy.h"
32 #include "ui/rs_frame_rate_policy.h"
33 #include "ui/rs_root_node.h"
34 #include "ui/rs_surface_extractor.h"
35 #include "ui/rs_surface_node.h"
36 #ifdef NEW_RENDER_CONTEXT
37 #include "render_context/memory_handler.h"
38 #endif
39 
40 #ifdef _WIN32
41 #include <windows.h>
42 #define gettid GetCurrentThreadId
43 #endif
44 
45 #ifdef __APPLE__
46 #define gettid getpid
47 #endif
48 
49 #ifdef __gnu_linux__
50 #include <sys/types.h>
51 #include <sys/syscall.h>
52 #define gettid []() -> int32_t { return static_cast<int32_t>(syscall(SYS_gettid)); }
53 #endif
54 
55 namespace OHOS {
56 namespace Rosen {
57 static std::unordered_map<RSUIDirector*, TaskRunner> g_uiTaskRunners;
58 static std::mutex g_uiTaskRunnersVisitorMutex;
59 std::function<void()> RSUIDirector::requestVsyncCallback_ = nullptr;
60 static std::mutex g_vsyncCallbackMutex;
61 
Create()62 std::shared_ptr<RSUIDirector> RSUIDirector::Create()
63 {
64     return std::shared_ptr<RSUIDirector>(new RSUIDirector());
65 }
66 
~RSUIDirector()67 RSUIDirector::~RSUIDirector()
68 {
69     Destroy();
70 }
71 
Init(bool shouldCreateRenderThread)72 void RSUIDirector::Init(bool shouldCreateRenderThread)
73 {
74     AnimationCommandHelper::SetAnimationCallbackProcessor(AnimationCallbackProcessor);
75 
76     isUniRenderEnabled_ = RSSystemProperties::GetUniRenderEnabled();
77     if (shouldCreateRenderThread && !isUniRenderEnabled_) {
78         auto renderThreadClient = RSIRenderClient::CreateRenderThreadClient();
79         auto transactionProxy = RSTransactionProxy::GetInstance();
80         if (transactionProxy != nullptr) {
81             transactionProxy->SetRenderThreadClient(renderThreadClient);
82         }
83 
84         RsFrameReport::GetInstance().Init();
85         if (!cacheDir_.empty()) {
86             RSRenderThread::Instance().SetCacheDir(cacheDir_);
87         }
88         RSRenderThread::Instance().Start();
89     } else {
90         // force fallback animaiions send to RS if no render thread
91         RSNodeMap::Instance().GetAnimationFallbackNode()->isRenderServiceNode_ = true;
92     }
93     if (auto rsApplicationAgent = RSApplicationAgentImpl::Instance()) {
94         rsApplicationAgent->RegisterRSApplicationAgent();
95     }
96 
97     GoForeground();
98 }
99 
StartTextureExport()100 void RSUIDirector::StartTextureExport()
101 {
102     isUniRenderEnabled_ = RSSystemProperties::GetUniRenderEnabled();
103     if (isUniRenderEnabled_) {
104         auto renderThreadClient = RSIRenderClient::CreateRenderThreadClient();
105         auto transactionProxy = RSTransactionProxy::GetInstance();
106         if (transactionProxy != nullptr) {
107             transactionProxy->SetRenderThreadClient(renderThreadClient);
108         }
109         RSRenderThread::Instance().Start();
110     }
111     RSRenderThread::Instance().UpdateWindowStatus(true);
112 }
113 
GoForeground(bool isTextureExport)114 void RSUIDirector::GoForeground(bool isTextureExport)
115 {
116     ROSEN_LOGD("RSUIDirector::GoForeground");
117     if (!isActive_) {
118         if (!isUniRenderEnabled_ || isTextureExport) {
119             RSRenderThread::Instance().UpdateWindowStatus(true);
120         }
121         isActive_ = true;
122         if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
123             node->SetEnableRender(true);
124         }
125         auto surfaceNode = surfaceNode_.lock();
126         if (surfaceNode) {
127             surfaceNode->MarkUIHidden(false);
128         }
129     }
130 }
131 
GoBackground(bool isTextureExport)132 void RSUIDirector::GoBackground(bool isTextureExport)
133 {
134     ROSEN_LOGD("RSUIDirector::GoBackground");
135     if (isActive_) {
136         if (!isUniRenderEnabled_ || isTextureExport) {
137             RSRenderThread::Instance().UpdateWindowStatus(false);
138         }
139         isActive_ = false;
140         if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
141             node->SetEnableRender(false);
142         }
143         auto surfaceNode = surfaceNode_.lock();
144         if (surfaceNode) {
145             surfaceNode->MarkUIHidden(true);
146         }
147         if (isTextureExport || isUniRenderEnabled_) {
148             return;
149         }
150         // clean bufferQueue cache
151         RSRenderThread::Instance().PostTask([surfaceNode]() {
152             if (surfaceNode != nullptr) {
153 #ifdef NEW_RENDER_CONTEXT
154                 std::shared_ptr<RSRenderSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
155 #else
156                 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
157 #endif
158                 rsSurface->ClearBuffer();
159             }
160         });
161 #if defined(ACE_ENABLE_GL) || defined(ACE_ENABLE_VK)
162         RSRenderThread::Instance().PostTask([this]() {
163             auto renderContext = RSRenderThread::Instance().GetRenderContext();
164             if (renderContext != nullptr) {
165 #ifndef ROSEN_CROSS_PLATFORM
166 #if defined(NEW_RENDER_CONTEXT)
167                 auto drawingContext = RSRenderThread::Instance().GetDrawingContext();
168                 MemoryHandler::ClearRedundantResources(drawingContext->GetDrawingContext());
169 #else
170                 renderContext->ClearRedundantResources();
171 #endif
172 #endif
173             }
174         });
175 #endif
176     }
177 }
178 
Destroy(bool isTextureExport)179 void RSUIDirector::Destroy(bool isTextureExport)
180 {
181     if (root_ != 0) {
182         if (!isUniRenderEnabled_ || isTextureExport) {
183             if (auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_)) {
184                 node->RemoveFromTree();
185             }
186         }
187         root_ = 0;
188     }
189     GoBackground(isTextureExport);
190     std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
191     g_uiTaskRunners.erase(this);
192 }
193 
SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)194 void RSUIDirector::SetRSSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode)
195 {
196     surfaceNode_ = surfaceNode;
197     AttachSurface();
198 }
199 
SetAbilityBGAlpha(uint8_t alpha)200 void RSUIDirector::SetAbilityBGAlpha(uint8_t alpha)
201 {
202     auto node = surfaceNode_.lock();
203     if (!node) {
204         ROSEN_LOGI("RSUIDirector::SetAbilityBGAlpha, surfaceNode_ is nullptr");
205         return;
206     }
207     node->SetAbilityBGAlpha(alpha);
208 }
209 
SetRTRenderForced(bool isRenderForced)210 void RSUIDirector::SetRTRenderForced(bool isRenderForced)
211 {
212     RSRenderThread::Instance().SetRTRenderForced(isRenderForced);
213 }
214 
SetContainerWindow(bool hasContainerWindow,float density)215 void RSUIDirector::SetContainerWindow(bool hasContainerWindow, float density)
216 {
217     auto node = surfaceNode_.lock();
218     if (!node) {
219         ROSEN_LOGI("RSUIDirector::SetContainerWindow, surfaceNode_ is nullptr");
220         return;
221     }
222     node->SetContainerWindow(hasContainerWindow, density);
223 }
224 
SetRoot(NodeId root)225 void RSUIDirector::SetRoot(NodeId root)
226 {
227     if (root_ == root) {
228         ROSEN_LOGW("RSUIDirector::SetRoot, root_ is not change");
229         return;
230     }
231     root_ = root;
232     AttachSurface();
233 }
234 
AttachSurface()235 void RSUIDirector::AttachSurface()
236 {
237     auto node = RSNodeMap::Instance().GetNode<RSRootNode>(root_);
238     auto surfaceNode = surfaceNode_.lock();
239     if (node != nullptr && surfaceNode != nullptr) {
240         node->AttachRSSurfaceNode(surfaceNode);
241         ROSEN_LOGD("RSUIDirector::AttachSurface [%{public}" PRIu64, surfaceNode->GetId());
242     } else {
243         ROSEN_LOGD("RSUIDirector::AttachSurface not ready");
244     }
245 }
246 
SetAppFreeze(bool isAppFreeze)247 void RSUIDirector::SetAppFreeze(bool isAppFreeze)
248 {
249     auto surfaceNode = surfaceNode_.lock();
250     if (surfaceNode != nullptr) {
251         surfaceNode->SetFreeze(isAppFreeze);
252     }
253 }
254 
SetRequestVsyncCallback(const std::function<void ()> & callback)255 void RSUIDirector::SetRequestVsyncCallback(const std::function<void()>& callback)
256 {
257     std::unique_lock<std::mutex> lock(g_vsyncCallbackMutex);
258     requestVsyncCallback_ = callback;
259 }
260 
SetTimeStamp(uint64_t timeStamp,const std::string & abilityName)261 void RSUIDirector::SetTimeStamp(uint64_t timeStamp, const std::string& abilityName)
262 {
263     timeStamp_ = timeStamp;
264     abilityName_ = abilityName;
265 }
266 
SetCacheDir(const std::string & cacheFilePath)267 void RSUIDirector::SetCacheDir(const std::string& cacheFilePath)
268 {
269     cacheDir_ = cacheFilePath;
270 }
271 
FlushAnimation(uint64_t timeStamp,int64_t vsyncPeriod)272 bool RSUIDirector::FlushAnimation(uint64_t timeStamp, int64_t vsyncPeriod)
273 {
274     bool hasRunningAnimation = false;
275     auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
276     if (modifierManager != nullptr) {
277         modifierManager->SetDisplaySyncEnable(GetCurrentRefreshRateMode() == -1);
278         modifierManager->SetFrameRateGetFunc([](const RSPropertyUnit unit, float velocity) -> int32_t {
279             return RSFrameRatePolicy::GetInstance()->GetExpectedFrameRate(unit, velocity);
280         });
281         hasRunningAnimation = modifierManager->Animate(timeStamp, vsyncPeriod);
282     }
283     return hasRunningAnimation;
284 }
285 
FlushAnimationStartTime(uint64_t timeStamp)286 void RSUIDirector::FlushAnimationStartTime(uint64_t timeStamp)
287 {
288     auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
289     if (modifierManager != nullptr) {
290         modifierManager->FlushStartAnimation(timeStamp);
291     }
292 }
293 
FlushModifier()294 void RSUIDirector::FlushModifier()
295 {
296     auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
297     if (modifierManager == nullptr) {
298         return;
299     }
300 
301     modifierManager->Draw();
302     // post animation finish callback(s) to task queue
303     RSUIDirector::RecvMessages();
304 }
305 
HasUIAnimation()306 bool RSUIDirector::HasUIAnimation()
307 {
308     auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
309     if (modifierManager != nullptr) {
310         return modifierManager->HasUIAnimation();
311     }
312     return false;
313 }
314 
SetUITaskRunner(const TaskRunner & uiTaskRunner)315 void RSUIDirector::SetUITaskRunner(const TaskRunner& uiTaskRunner)
316 {
317     std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
318     g_uiTaskRunners[this] = uiTaskRunner;
319     if (!isHgmConfigChangeCallbackReg_) {
320         RSFrameRatePolicy::GetInstance()->RegisterHgmConfigChangeCallback();
321         isHgmConfigChangeCallbackReg_ = true;
322     }
323 }
324 
SendMessages()325 void RSUIDirector::SendMessages()
326 {
327     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "SendCommands");
328     auto transactionProxy = RSTransactionProxy::GetInstance();
329     if (transactionProxy != nullptr) {
330         transactionProxy->FlushImplicitTransaction(timeStamp_, abilityName_);
331     }
332     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
333 }
334 
RecvMessages()335 void RSUIDirector::RecvMessages()
336 {
337     if (GetRealPid() == -1) {
338         return;
339     }
340     static const uint32_t pid = static_cast<uint32_t>(GetRealPid());
341     static std::mutex recvMessagesMutex;
342     std::unique_lock<std::mutex> lock(recvMessagesMutex);
343     if (RSMessageProcessor::Instance().HasTransaction(pid)) {
344         auto transactionDataPtr = RSMessageProcessor::Instance().GetTransaction(pid);
345         RecvMessages(transactionDataPtr);
346     }
347 }
348 
RecvMessages(std::shared_ptr<RSTransactionData> cmds)349 void RSUIDirector::RecvMessages(std::shared_ptr<RSTransactionData> cmds)
350 {
351     if (cmds == nullptr || cmds->IsEmpty()) {
352         return;
353     }
354     ROSEN_LOGD("RSUIDirector::RecvMessages success");
355     PostTask([cmds]() {
356         ROSEN_LOGD("RSUIDirector::ProcessMessages success");
357         RSUIDirector::ProcessMessages(cmds);
358         std::unique_lock<std::mutex> lock(g_vsyncCallbackMutex);
359         if (requestVsyncCallback_ != nullptr) {
360             requestVsyncCallback_();
361         } else {
362             RSTransaction::FlushImplicitTransaction();
363         }
364     });
365 }
366 
ProcessMessages(std::shared_ptr<RSTransactionData> cmds)367 void RSUIDirector::ProcessMessages(std::shared_ptr<RSTransactionData> cmds)
368 {
369     static RSContext context; // RSCommand->process() needs it
370     cmds->Process(context);
371 }
372 
AnimationCallbackProcessor(NodeId nodeId,AnimationId animId,AnimationCallbackEvent event)373 void RSUIDirector::AnimationCallbackProcessor(NodeId nodeId, AnimationId animId, AnimationCallbackEvent event)
374 {
375     // try find the node by nodeId
376     if (auto nodePtr = RSNodeMap::Instance().GetNode<RSNode>(nodeId)) {
377         if (!nodePtr->AnimationCallback(animId, event)) {
378             ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %{public}" PRIu64 ""
379                 "on node %{public}" PRIu64, animId, nodeId);
380         }
381         return;
382     }
383 
384     // if node not found, try fallback node
385     auto& fallbackNode = RSNodeMap::Instance().GetAnimationFallbackNode();
386     if (fallbackNode && fallbackNode->AnimationCallback(animId, event)) {
387         ROSEN_LOGD("RSUIDirector::AnimationCallbackProcessor, found animation %{public}" PRIu64 " on fallback node.",
388             animId);
389     } else {
390         ROSEN_LOGE("RSUIDirector::AnimationCallbackProcessor, could not find animation %{public}" PRIu64 " on"
391             " fallback node.", animId);
392     }
393 }
394 
PostFrameRateTask(const std::function<void ()> & task)395 void RSUIDirector::PostFrameRateTask(const std::function<void()>& task)
396 {
397     PostTask(task);
398 }
399 
PostTask(const std::function<void ()> & task)400 void RSUIDirector::PostTask(const std::function<void()>& task)
401 {
402     std::unique_lock<std::mutex> lock(g_uiTaskRunnersVisitorMutex);
403     for (auto [_, taskRunner] : g_uiTaskRunners) {
404         if (taskRunner == nullptr) {
405             ROSEN_LOGE("RSUIDirector::PostTask, uiTaskRunner is null");
406             continue;
407         }
408         ROSEN_LOGD("RSUIDirector::PostTask success");
409         taskRunner(task);
410         return;
411     }
412 }
413 
GetCurrentRefreshRateMode()414 int32_t RSUIDirector::GetCurrentRefreshRateMode()
415 {
416     return RSFrameRatePolicy::GetInstance()->GetRefreshRateMode();
417 }
418 
GetAnimateExpectedRate() const419 int32_t RSUIDirector::GetAnimateExpectedRate() const
420 {
421     int32_t animateRate = 0;
422     auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
423     if (modifierManager != nullptr) {
424         auto& range = modifierManager->GetFrameRateRange();
425         if (range.IsValid()) {
426             animateRate = range.preferred_;
427         }
428     }
429     return animateRate;
430 }
431 } // namespace Rosen
432 } // namespace OHOS
433