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