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