• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "pipeline/rs_render_thread.h"
17 
18 #include <cstdint>
19 
20 #include "rs_trace.h"
21 #include "sandbox_utils.h"
22 
23 #include "animation/rs_animation_fraction.h"
24 #include "command/rs_surface_node_command.h"
25 #include "common/rs_background_thread.h"
26 #include "delegate/rs_functional_delegate.h"
27 #include "pipeline/rs_draw_cmd_list.h"
28 #include "pipeline/rs_node_map.h"
29 #include "pipeline/rs_render_node_map.h"
30 #include "pipeline/rs_render_node_gc.h"
31 #include "pipeline/rs_root_render_node.h"
32 #include "pipeline/rs_surface_buffer_callback_manager.h"
33 #include "pipeline/rs_surface_render_node.h"
34 #include "platform/common/rs_log.h"
35 #include "platform/common/rs_system_properties.h"
36 #include "property/rs_property_trace.h"
37 #include "render/rs_image_cache.h"
38 #include "render/rs_typeface_cache.h"
39 #include "render_context/shader_cache.h"
40 #include "rs_frame_report.h"
41 #include "transaction/rs_render_service_client.h"
42 #include "ui/rs_surface_extractor.h"
43 #include "ui/rs_surface_node.h"
44 #include "ui/rs_ui_director.h"
45 #ifdef RS_ENABLE_VK
46 #include "platform/ohos/backend/rs_vulkan_context.h"
47 #endif
48 #ifdef OHOS_RSS_CLIENT
49 #include "res_sched_client.h"
50 #include "res_type.h"
51 #endif
52 
53 #ifdef RES_CLINET_SCHED_ENABLE
54 #include "qos.h"
55 #endif
56 
57 #ifdef ROSEN_PREVIEW
58 #include "glfw_render_context.h"
59 #endif
60 
61 #ifdef ROSEN_OHOS
62 #include <unistd.h>
63 #include "frame_collector.h"
64 #include "render_frame_trace.h"
65 #include "platform/ohos/overdraw/rs_overdraw_controller.h"
66 #ifdef ACCESSIBILITY_ENABLE
67 #include "accessibility_config.h"
68 #include "platform/common/rs_accessibility.h"
69 #endif
70 
71 static const std::string RT_INTERVAL_NAME = "renderthread";
72 #endif
73 #if !defined(ROSEN_PREVIEW) && !defined(ROSEN_IOS)
74 #include <sys/prctl.h>
75 #endif
SystemCallSetThreadName(const std::string & name)76 static void SystemCallSetThreadName(const std::string& name)
77 {
78 #if !defined(ROSEN_PREVIEW) && !defined(ROSEN_IOS)
79 
80     if (prctl(PR_SET_NAME, name.c_str()) < 0) {
81         return;
82     }
83 #endif
84 }
85 
86 namespace OHOS {
87 namespace Rosen {
88 namespace {
89     static constexpr uint64_t REFRESH_PERIOD = 16666667;
90 }
91 
SendFrameEvent(bool start)92 void SendFrameEvent(bool start)
93 {
94 #ifdef ROSEN_OHOS
95     FrameCollector::GetInstance().MarkFrameEvent(start ? FrameEventType::WaitVsyncStart : FrameEventType::WaitVsyncEnd);
96 #endif
97 }
98 
Instance()99 RSRenderThread& RSRenderThread::Instance()
100 {
101     static RSRenderThread renderThread;
102     RSAnimationFraction::Init();
103     return renderThread;
104 }
105 
RSRenderThread()106 RSRenderThread::RSRenderThread()
107 {
108     static std::function<std::shared_ptr<Drawing::Typeface> (uint64_t)> customTypefaceQueryfunc =
109     [] (uint64_t globalUniqueId) -> std::shared_ptr<Drawing::Typeface> {
110         return RSTypefaceCache::Instance().GetDrawingTypefaceCache(globalUniqueId);
111     };
112     Drawing::DrawOpItem::SetTypefaceQueryCallBack(customTypefaceQueryfunc);
113     mainFunc_ = [&]() {
114         uint64_t renderStartTimeStamp = jankDetector_->GetSysTimeNs();
115         RS_TRACE_BEGIN("RSRenderThread DrawFrame: " + std::to_string(timestamp_));
116 #ifdef ROSEN_OHOS
117         FRAME_TRACE::RenderFrameTrace::GetInstance().RenderStartFrameTrace(RT_INTERVAL_NAME);
118 #endif
119         prevTimestamp_ = timestamp_;
120         ProcessCommands();
121         ROSEN_LOGD("RSRenderThread DrawFrame(%{public}" PRIu64 ") in %{public}s",
122             prevTimestamp_, renderContext_ ? "GPU" : "CPU");
123         Animate(prevTimestamp_);
124         Render();
125         SendCommands();
126         {
127             std::lock_guard<std::mutex> lock(context_->activeNodesInRootMutex_);
128             context_->activeNodesInRoot_.clear();
129         }
130         RSRenderNodeGC::Instance().ReleaseNodeMemory();
131         ReleasePixelMapInBackgroundThread();
132         context_->pendingSyncNodes_.clear();
133 #ifdef ROSEN_OHOS
134         FRAME_TRACE::RenderFrameTrace::GetInstance().RenderEndFrameTrace(RT_INTERVAL_NAME);
135 #endif
136         jankDetector_->CalculateSkippedFrame(renderStartTimeStamp, jankDetector_->GetSysTimeNs());
137         RSTypefaceCache::Instance().HandleDelayDestroyQueue();
138         RS_TRACE_END();
139     };
140     context_ = std::make_shared<RSContext>();
141     context_->Initialize();
142     jankDetector_ = std::make_shared<RSJankDetector>();
143 #ifdef ACCESSIBILITY_ENABLE
144     RSAccessibility::GetInstance().ListenHighContrastChange([](bool newHighContrast) {
145         std::thread thread(
146             [](bool newHighContrast) {
147                 auto& renderThread = RSRenderThread::Instance();
148                 renderThread.SetHighContrast(newHighContrast);
149             },
150             newHighContrast);
151         thread.detach();
152     });
153 #endif
154 #ifdef ROSEN_OHOS
155     Drawing::DrawSurfaceBufferOpItem::RegisterSurfaceBufferCallback({
156         .OnFinish = RSSurfaceBufferCallbackManager::Instance().GetOnFinishCb(),
157         .OnAfterAcquireBuffer = RSSurfaceBufferCallbackManager::Instance().GetOnAfterAcquireBufferCb(),
158     });
159     Drawing::DrawSurfaceBufferOpItem::SetIsUniRender(false);
160     Drawing::DrawSurfaceBufferOpItem::RegisterGetRootNodeIdFuncForRT(
161         [this]() {
162             if (visitor_) {
163                 return visitor_->GetActiveSubtreeRootId();
164             }
165             return INVALID_NODEID;
166         }
167     );
168 #endif
169     RSSurfaceBufferCallbackManager::Instance().SetIsUniRender(false);
170     RSSurfaceBufferCallbackManager::Instance().SetVSyncFuncs({
171         .requestNextVSync = []() {
172             RSRenderThread::Instance().RequestNextVSync();
173         },
174         .isRequestedNextVSync = [this]() {
175 #ifdef __OHOS__
176             if (receiver_ != nullptr) {
177                 return receiver_->IsRequestedNextVSync();
178             }
179 #endif
180             return false;
181         },
182     });
183 }
184 
~RSRenderThread()185 RSRenderThread::~RSRenderThread()
186 {
187     Stop();
188 #ifndef NEW_RENDER_CONTEXT
189     if (renderContext_ != nullptr) {
190         ROSEN_LOGD("Destroy renderContext!!");
191         delete renderContext_;
192         renderContext_ = nullptr;
193     }
194 #endif
195 }
196 
Start()197 void RSRenderThread::Start()
198 {
199     ROSEN_LOGD("RSRenderThread start.");
200     running_.store(true);
201     std::unique_lock<std::mutex> cmdLock(rtMutex_);
202     if (thread_ == nullptr) {
203         thread_ = std::make_unique<std::thread>([this] { this->RSRenderThread::RenderLoop(); });
204     }
205 }
206 
ReleasePixelMapInBackgroundThread()207 void RSRenderThread::ReleasePixelMapInBackgroundThread()
208 {
209     if (!RSImageCache::Instance().CheckUniqueIdIsEmpty()) {
210         static std::function<void()> task = []() -> void { RSImageCache::Instance().ReleaseUniqueIdList(); };
211         RSBackgroundThread::Instance().PostTask(task);
212     }
213 }
214 
Stop()215 void RSRenderThread::Stop()
216 {
217     running_.store(false);
218 
219     if (handler_) {
220         handler_->RemoveAllEvents();
221         handler_ = nullptr;
222     }
223     receiver_ = nullptr;
224     if (runner_) {
225         runner_->Stop();
226     }
227 
228     if (thread_ != nullptr && thread_->joinable()) {
229         thread_->join();
230     }
231 
232     thread_ = nullptr;
233     ROSEN_LOGD("RSRenderThread stopped.");
234 }
235 
RecvTransactionData(std::unique_ptr<RSTransactionData> & transactionData)236 void RSRenderThread::RecvTransactionData(std::unique_ptr<RSTransactionData>& transactionData)
237 {
238     {
239         std::unique_lock<std::mutex> cmdLock(cmdMutex_);
240         std::string str = "RecvCommands ptr:" + std::to_string(reinterpret_cast<uintptr_t>(transactionData.get()));
241         commandTimestamp_ = transactionData->GetTimestamp();
242         ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, str.c_str());
243         cmds_.emplace_back(std::move(transactionData));
244         ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
245     }
246     // [PLANNING]: process in next vsync (temporarily)
247     RSRenderThread::Instance().RequestNextVSync();
248 }
249 
RequestNextVSync()250 void RSRenderThread::RequestNextVSync()
251 {
252     if (handler_) {
253         RS_TRACE_FUNC();
254         SendFrameEvent(true);
255         VSyncReceiver::FrameCallback fcb = {
256             .userData_ = this,
257             .callbackWithId_ = [this](uint64_t timestamp, int64_t frameCount,
258                                    void* arg) { this->OnVsync(timestamp, frameCount); },
259         };
260         if (receiver_ != nullptr) {
261             receiver_->RequestNextVSync(fcb);
262         } else {
263             hasSkipVsync_ = true;
264         }
265     } else {
266         hasSkipVsync_ = true;
267     }
268 }
269 
GetTid()270 int32_t RSRenderThread::GetTid()
271 {
272     return tid_;
273 }
274 
CreateAndInitRenderContextIfNeed()275 void RSRenderThread::CreateAndInitRenderContextIfNeed()
276 {
277 #if defined(NEW_RENDER_CONTEXT)
278 #if !defined(ROSEN_PREVIEW)
279     if (renderContext_ == nullptr) {
280         renderContext_ = RenderContextBaseFactory::CreateRenderContext();
281         drawingContext_ = std::make_shared<Rosen::DrawingContext>(renderContext_->GetRenderType());
282         RS_TRACE_NAME("Init Context");
283         renderContext_->Init(); // init egl context on RT
284         if (!cacheDir_.empty()) {
285             ShaderCache::Instance().SetFilePath(cacheDir_);
286         }
287         ROSEN_LOGD("Create and Init RenderContext");
288     }
289 #endif
290 #else
291 #if (defined(RS_ENABLE_GL) || defined (RS_ENABLE_VK)) && !defined(ROSEN_PREVIEW)
292     if (renderContext_ == nullptr) {
293         renderContext_ = new RenderContext();
294         ROSEN_LOGD("Create RenderContext");
295 #ifdef ROSEN_OHOS
296 #ifdef RS_ENABLE_GL
297         if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
298             RS_TRACE_NAME("InitializeEglContext");
299             renderContext_->InitializeEglContext(); // init egl context on RT
300             if (!cacheDir_.empty()) {
301                 renderContext_->SetCacheDir(cacheDir_);
302             }
303         }
304 #endif
305 #ifdef RS_ENABLE_VK
306     if (RSSystemProperties::IsUseVulkan()) {
307         renderContext_->SetUpGpuContext(nullptr);
308     }
309 #endif
310 #endif
311     }
312 #endif
313 #endif
314 }
315 
RenderLoop()316 void RSRenderThread::RenderLoop()
317 {
318     SystemCallSetThreadName("RSRenderThread");
319 
320 #ifdef OHOS_RSS_CLIENT
321     std::unordered_map<std::string, std::string> payload;
322     payload["uid"] = std::to_string(getuid());
323     payload["pid"] = std::to_string(GetRealPid());
324     ResourceSchedule::ResSchedClient::GetInstance().ReportData(
325         ResourceSchedule::ResType::RES_TYPE_REPORT_RENDER_THREAD, getproctid(), payload);
326 #endif
327 #ifdef ROSEN_OHOS
328     tid_ = gettid();
329 #endif
330     CreateAndInitRenderContextIfNeed();
331     std::string name = "RSRenderThread_" + std::to_string(GetRealPid());
332     runner_ = AppExecFwk::EventRunner::Create(false);
333     handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
334     auto rsClient = std::static_pointer_cast<RSRenderServiceClient>(RSIRenderClient::CreateRenderServiceClient());
335     receiver_ = rsClient->CreateVSyncReceiver(name, handler_);
336     if (receiver_ == nullptr) {
337         ROSEN_LOGE("RSRenderThread CreateVSyncReceiver Error");
338         return;
339     }
340     receiver_->Init();
341     if (hasSkipVsync_) {
342         hasSkipVsync_ = false;
343         RSRenderThread::Instance().RequestNextVSync();
344     }
345 #ifdef ROSEN_PREVIEW
346     static auto onSizeChange = [&](int width, int height) {
347         if (isRunning_) {
348             RSRenderThread::Instance().RequestNextVSync();
349         }
350     };
351     GlfwRenderContext::GetGlobal()->OnSizeChanged(onSizeChange);
352 #endif
353 
354 #ifdef ROSEN_OHOS
355     FrameCollector::GetInstance().SetRepaintCallback([this]() { this->RequestNextVSync(); });
356     auto delegate = RSFunctionalDelegate::Create();
357     delegate->SetRepaintCallback([this]() {
358         bool isOverDrawEnabled = RSOverdrawController::GetInstance().IsEnabled();
359         PostTask([this, isOverDrawEnabled]() {
360             isOverDrawEnabledOfCurFrame_ = isOverDrawEnabled;
361             RequestNextVSync();
362         });
363     });
364     RSOverdrawController::GetInstance().SetDelegate(delegate);
365 #endif
366 
367 #ifdef RES_CLINET_SCHED_ENABLE
368     auto ret = OHOS::QOS::SetThreadQos(OHOS::QOS::QosLevel::QOS_USER_INTERACTIVE);
369     RS_LOGI("RSRenderThread: SetThreadQos retcode = %{public}d", ret);
370 #endif
371 
372     if (runner_) {
373         runner_->Run();
374     }
375 }
376 
OnVsync(uint64_t timestamp,int64_t frameCount)377 void RSRenderThread::OnVsync(uint64_t timestamp, int64_t frameCount)
378 {
379     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "RSRenderThread::OnVsync");
380 #ifdef ROSEN_PREVIEW
381     isRunning_ = true;
382 #endif
383     SendFrameEvent(false);
384     mValue = (mValue + 1) % 2; // 1 and 2 is Calculated parameters
385     RS_TRACE_INT("Vsync-client", mValue);
386     timestamp_ = timestamp;
387     if (activeWindowCnt_.load() > 0) {
388         mainFunc_(); // start render-loop now
389     }
390 #ifdef ROSEN_PREVIEW
391     isRunning_ = false;
392 #endif
393     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
394 }
395 
UpdateWindowStatus(bool active)396 void RSRenderThread::UpdateWindowStatus(bool active)
397 {
398     if (active) {
399         activeWindowCnt_++;
400     } else {
401         activeWindowCnt_--;
402     }
403     ROSEN_LOGD("RSRenderThread UpdateWindowStatus %{public}d, cur activeWindowCnt_ %{public}d",
404         active, activeWindowCnt_.load());
405 }
406 
ProcessCommands()407 void RSRenderThread::ProcessCommands()
408 {
409     // Attention: there are two situations
410     // 1. when commandTimestamp_ != 0, it means that UIDirector has called
411     // "RSRenderThread::Instance().RequestNextVSync()", which equals there are some commands form UIThread need to be
412     // executed. To make commands from UIThread sync with buffer flushed by RenderThread, we choose commandTimestamp_ as
413     // uiTimestamp_ which would be used in RenderThreadVisitor when we call flushFrame.
414     // 2. when cmds_.empty() is true or commandTimestamp_ = 0,
415     // it means that some thread except UIThread like RSRenderThread::Animate
416     // has called "RSRenderThread::Instance().RequestNextVSync()", which equals that some commands form RenderThread
417     // need to be executed. To make commands from RenderThread sync with buffer flushed by RenderThread, we choose
418     // (prevTimestamp_ - 1) as uiTimestamp_ which would be used in RenderThreadVisitor when we call flushFrame.
419 
420     // The reason why prevTimestamp_ need to be minus 1 is that timestamp used in UIThread is always less than (for now)
421     // timestamp used in RenderThread. If we do not do this, when RenderThread::Animate execute flushFrame and use
422     // prevTimestamp_ as buffer timestamp which equals T0, UIDirector send messages in the same vsync period, and the
423     // commandTimestamp_ would also be T0, RenderService would execute commands from UIDirector and composite buffer
424     // which rendering is executed by RSRenderThread::Animate for they have the same timestamp. To avoid this situation,
425     // we should always use "prevTimestamp_ - 1".
426 
427     std::unique_lock<std::mutex> cmdLock(cmdMutex_);
428     if (cmds_.empty()) {
429         uiTimestamp_ = prevTimestamp_ - 1;
430         return;
431     }
432     if (RsFrameReport::GetInstance().GetEnable()) {
433         RsFrameReport::GetInstance().ProcessCommandsStart();
434     }
435 
436     if (commandTimestamp_ != 0) {
437         uiTimestamp_ = commandTimestamp_;
438         commandTimestamp_ = 0;
439     } else {
440         uiTimestamp_ = prevTimestamp_ - 1;
441     }
442 
443     ROSEN_LOGD("RSRenderThread ProcessCommands size: %{public}lu\n", (unsigned long)cmds_.size());
444     std::vector<std::unique_ptr<RSTransactionData>> cmds;
445 #ifdef CROSS_PLATFORM
446     PrepareCommandForCrossPlatform(cmds);
447 #else
448     std::swap(cmds, cmds_);
449 #endif
450     cmdLock.unlock();
451 
452     // To improve overall responsiveness, we make animations start on LAST frame instead of THIS frame.
453     // If last frame is too far away (earlier than 2 vsync from now), we use currentTimestamp_ - REFRESH_PERIOD as
454     // 'virtual' last frame timestamp.
455     if (timestamp_ - lastAnimateTimestamp_ > 2 * REFRESH_PERIOD) { // 2: if last frame is earlier than 2 vsync from now
456         context_->currentTimestamp_ = timestamp_ - REFRESH_PERIOD;
457     } else {
458         context_->currentTimestamp_ = lastAnimateTimestamp_;
459     }
460     uint64_t uiEndTimeStamp = jankDetector_->GetSysTimeNs();
461     for (auto& cmdData : cmds) {
462         std::string str = "ProcessCommands ptr:" + std::to_string(reinterpret_cast<uintptr_t>(cmdData.get()));
463         ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, str.c_str());
464         // only set transactionTimestamp_ in UniRender mode
465         context_->transactionTimestamp_ = RSSystemProperties::GetUniRenderEnabled() ? cmdData->GetTimestamp() : 0;
466         cmdData->Process(*context_);
467         jankDetector_->UpdateUiDrawFrameMsg(cmdData->GetTimestamp(), uiEndTimeStamp, cmdData->GetAbilityName());
468         ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
469     }
470 }
471 
472 #ifdef CROSS_PLATFORM
PrepareCommandForCrossPlatform(std::vector<std::unique_ptr<RSTransactionData>> & cmds)473 void RSRenderThread::PrepareCommandForCrossPlatform(std::vector<std::unique_ptr<RSTransactionData>>& cmds)
474 {
475     if (cmds_.empty()) {
476         return;
477     }
478     int index = 0;
479     uint64_t firstCmdTimestamp = cmds_[0]->GetTimestamp();
480     uint64_t lastCmdTimestamp = cmds_.back()->GetTimestamp();
481     while (index < cmds_.size()) {
482         if (cmds_[index]->GetTimestamp() <
483             std::max({timestamp_, firstCmdTimestamp + 1, lastCmdTimestamp})) {
484             index++;
485         } else {
486             break;
487         }
488     }
489     for (int i = 0; i < index; i++) {
490         cmds.emplace_back(std::move(cmds_[i]));
491     }
492 
493     cmds_.erase(cmds_.begin(), cmds_.begin() + index);
494     if (!cmds_.empty()) {
495         RequestNextVSync();
496     }
497 }
498 #endif
499 
Animate(uint64_t timestamp)500 void RSRenderThread::Animate(uint64_t timestamp)
501 {
502     RS_TRACE_FUNC();
503 
504     if (RsFrameReport::GetInstance().GetEnable()) {
505         RsFrameReport::GetInstance().AnimateStart();
506     }
507 
508     lastAnimateTimestamp_ = timestamp;
509 
510     if (context_->animatingNodeList_.empty()) {
511         return;
512     }
513 
514     bool needRequestNextVsync = false;
515     // isCalculateAnimationValue is embedded modify for stat animate frame drop
516     bool isCalculateAnimationValue = false;
517     // iterate and animate all animating nodes, remove if animation finished
518     EraseIf(context_->animatingNodeList_,
519         [timestamp, &needRequestNextVsync, &isCalculateAnimationValue](const auto& iter) -> bool {
520         auto node = iter.second.lock();
521         if (node == nullptr) {
522             ROSEN_LOGD("RSRenderThread::Animate removing expired animating node");
523             return true;
524         }
525         auto [hasRunningAnimation, nodeNeedRequestNextVsync, nodeCalculateAnimationValue] = node->Animate(timestamp);
526         if (!hasRunningAnimation) {
527             ROSEN_LOGD("RSRenderThread::Animate removing finished animating node %{public}" PRIu64, node->GetId());
528         }
529         needRequestNextVsync = needRequestNextVsync || nodeNeedRequestNextVsync;
530         isCalculateAnimationValue = isCalculateAnimationValue || nodeCalculateAnimationValue;
531         return !hasRunningAnimation;
532     });
533     if (!isCalculateAnimationValue && needRequestNextVsync) {
534         RS_TRACE_NAME("Animation running empty");
535     }
536 
537     if (needRequestNextVsync) {
538         RSRenderThread::Instance().RequestNextVSync();
539     }
540 }
541 
Render()542 void RSRenderThread::Render()
543 {
544     if (RSSystemProperties::GetRenderNodeTraceEnabled()) {
545         RSPropertyTrace::GetInstance().RefreshNodeTraceInfo();
546     }
547     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "RSRenderThread::Render");
548     if (RsFrameReport::GetInstance().GetEnable()) {
549         RsFrameReport::GetInstance().RenderStart(timestamp_);
550     }
551     std::unique_lock<std::mutex> lock(mutex_);
552     const auto& rootNode = context_->GetGlobalRootRenderNode();
553 
554     if (rootNode == nullptr) {
555         ROSEN_LOGE("RSRenderThread::Render, rootNode is nullptr");
556         return;
557     }
558     if (visitor_ == nullptr) {
559         visitor_ = std::make_shared<RSRenderThreadVisitor>();
560     }
561     // get latest partial render status from system properties and set it to RTvisitor_
562     visitor_->SetPartialRenderStatus(RSSystemProperties::GetPartialRenderEnabled(),
563         isRTRenderForced_ || (isOverDrawEnabledOfLastFrame_ != isOverDrawEnabledOfCurFrame_) ||
564         IsHighContrastChanged());
565     ResetHighContrastChanged();
566     rootNode->Prepare(visitor_);
567     rootNode->Process(visitor_);
568     isOverDrawEnabledOfLastFrame_ = isOverDrawEnabledOfCurFrame_;
569     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
570 }
571 
SendCommands()572 void RSRenderThread::SendCommands()
573 {
574     ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "RSRenderThread::SendCommands");
575     if (RsFrameReport::GetInstance().GetEnable()) {
576         RsFrameReport::GetInstance().SendCommandsStart();
577     }
578 
579     RSUIDirector::RecvMessages();
580     ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
581 }
582 
Detach(NodeId id)583 void RSRenderThread::Detach(NodeId id)
584 {
585     if (auto node = context_->GetNodeMap().GetRenderNode<RSRootRenderNode>(id)) {
586         std::unique_lock<std::mutex> lock(mutex_);
587         context_->GetGlobalRootRenderNode()->RemoveChild(node);
588     }
589 }
590 
PostTask(RSTaskMessage::RSTask task)591 void RSRenderThread::PostTask(RSTaskMessage::RSTask task)
592 {
593     if (handler_) {
594         handler_->PostTask(task);
595     }
596 }
597 
PostSyncTask(RSTaskMessage::RSTask task)598 void RSRenderThread::PostSyncTask(RSTaskMessage::RSTask task)
599 {
600     if (handler_) {
601         handler_->PostSyncTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
602     }
603 }
604 
PostPreTask()605 void RSRenderThread::PostPreTask()
606 {
607     if (handler_ && preTask_) {
608         handler_->PostTask(preTask_);
609     }
610 }
611 } // namespace Rosen
612 } // namespace OHOS
613