1 /*
2 * Copyright (c) 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
17 #include "pipeline/rs_uifirst_manager.h"
18
19 #include "luminance/rs_luminance_control.h"
20 #include "rs_trace.h"
21
22 #include "common/rs_optional_trace.h"
23 #include "drawable/rs_surface_render_node_drawable.h"
24 #include "params/rs_display_render_params.h"
25 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
26 #include "pipeline/rs_canvas_render_node.h"
27 #include "pipeline/rs_uni_render_util.h"
28 #include "pipeline/rs_main_thread.h"
29 #include "platform/common/rs_log.h"
30
31 // use in mainthread, post subthread, not affect renderthread
32 namespace OHOS {
33 namespace Rosen {
34 namespace {
35 constexpr int EVENT_START_TIMEOUT = 500;
36 constexpr int EVENT_STOP_TIMEOUT = 150;
37 constexpr int EVENT_DISABLE_UIFIRST_GAP = 100;
38 constexpr int CLEAR_CACHE_DELAY = 400;
39 const std::string CLEAR_CACHE_TASK_PREFIX = "uifirst_clear_cache_";
40 constexpr std::string_view ARKTSCARDNODE_NAME = "ArkTSCardNode";
41 constexpr std::string_view EVENT_DISABLE_UIFIRST = "APP_LIST_FLING";
GetCurSysTime()42 inline int64_t GetCurSysTime()
43 {
44 auto curTime = std::chrono::system_clock::now().time_since_epoch();
45 return std::chrono::duration_cast<std::chrono::milliseconds>(curTime).count();
46 }
47 };
48
Instance()49 RSUifirstManager& RSUifirstManager::Instance()
50 {
51 static RSUifirstManager instance; // store in mainthread instance ?
52 return instance;
53 }
54
RSUifirstManager()55 RSUifirstManager::RSUifirstManager() :
56 #if defined(RS_ENABLE_VK)
57 useDmaBuffer_(RSSystemParameters::GetUIFirstDmaBufferEnabled() &&
58 RSSystemProperties::IsPhoneType() && RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN)
59 #else
60 useDmaBuffer_(false)
61 #endif
62 {}
63
GetSurfaceDrawableByID(NodeId id)64 std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> RSUifirstManager::GetSurfaceDrawableByID(NodeId id)
65 {
66 if (const auto cacheIt = subthreadProcessingNode_.find(id); cacheIt != subthreadProcessingNode_.end()) {
67 if (const auto ptr = cacheIt->second) {
68 return std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(ptr);
69 }
70 }
71 // unlikely
72 auto ptr = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
73 if (ptr) {
74 return std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(ptr);
75 }
76 return nullptr;
77 }
78
SetUifirstNodeEnableParam(RSSurfaceRenderNode & node,MultiThreadCacheType type)79 void RSUifirstManager::SetUifirstNodeEnableParam(RSSurfaceRenderNode& node, MultiThreadCacheType type)
80 {
81 node.SetUifirstNodeEnableParam(type); // update drawable param
82 if (node.IsLeashWindow() && type != MultiThreadCacheType::ARKTS_CARD) {
83 for (auto& child : *(node.GetChildren())) {
84 if (!child) {
85 continue;
86 }
87 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
88 if (!surfaceChild) {
89 continue;
90 }
91 if (surfaceChild->IsMainWindowType()) {
92 surfaceChild->SetIsParentUifirstNodeEnableParam(type == MultiThreadCacheType::LEASH_WINDOW ||
93 type == MultiThreadCacheType::NONFOCUS_WINDOW);
94 continue;
95 }
96 }
97 }
98 }
99
100 // unref in sub when cache done
AddProcessDoneNode(NodeId id)101 void RSUifirstManager::AddProcessDoneNode(NodeId id)
102 {
103 // mutex
104 if (id == INVALID_NODEID) {
105 return;
106 }
107 RS_OPTIONAL_TRACE_NAME_FMT("sub done %" PRIu64"", id);
108 std::lock_guard<std::mutex> lock(childernDrawableMutex_);
109 subthreadProcessDoneNode_.push_back(id);
110 }
111
ResetUifirstNode(std::shared_ptr<RSSurfaceRenderNode> & nodePtr)112 void RSUifirstManager::ResetUifirstNode(std::shared_ptr<RSSurfaceRenderNode>& nodePtr)
113 {
114 if (!nodePtr) {
115 return;
116 }
117 nodePtr->SetUifirstUseStarting(false);
118 SetUifirstNodeEnableParam(*nodePtr, MultiThreadCacheType::NONE);
119 RSMainThread::Instance()->GetContext().AddPendingSyncNode(nodePtr);
120 auto drawable = GetSurfaceDrawableByID(nodePtr->GetId());
121 if (!drawable) {
122 return;
123 }
124 if (!nodePtr->IsOnTheTree() && nodePtr->IsNodeToBeCaptured()) {
125 drawable->ResetUifirst(true);
126 auto taskName = CLEAR_CACHE_TASK_PREFIX + std::to_string(nodePtr->GetId());
127 auto releaseTask = [drawable] {
128 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
129 if (surfaceParams && surfaceParams->GetUifirstNodeEnableParam() == MultiThreadCacheType::NONE) {
130 RS_TRACE_NAME_FMT("ResetUifirstNode clearCache id:%llu", surfaceParams->GetId());
131 drawable->ResetUifirst(false);
132 }
133 };
134 RSUniRenderThread::Instance().PostTask(releaseTask, taskName, CLEAR_CACHE_DELAY);
135 } else {
136 nodePtr->SetIsNodeToBeCaptured(false);
137 drawable->ResetUifirst(false);
138 }
139 }
140
MergeOldDirty(RSSurfaceRenderNode & node)141 void RSUifirstManager::MergeOldDirty(RSSurfaceRenderNode& node)
142 {
143 auto params = static_cast<RSSurfaceRenderParams*>(node.GetStagingRenderParams().get());
144 if (!params || !params->GetPreSurfaceCacheContentStatic()) {
145 return;
146 }
147 if (node.IsAppWindow() && !RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.GetParent().lock())) {
148 node.GetDirtyManager()->MergeDirtyRect(node.GetOldDirty());
149 return;
150 }
151 for (auto& child : *node.GetSortedChildren()) {
152 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
153 if (surfaceNode && surfaceNode->IsAppWindow()) {
154 surfaceNode->GetDirtyManager()->MergeDirtyRect(surfaceNode->GetOldDirty());
155 break;
156 }
157 }
158 }
159
RenderGroupUpdate(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable)160 void RSUifirstManager::RenderGroupUpdate(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable)
161 {
162 if (mainThread_ == nullptr) {
163 return;
164 }
165 auto nodeSp = mainThread_->GetContext().GetNodeMap().GetRenderNode(drawable->GetId());
166 if (nodeSp == nullptr) {
167 return;
168 }
169 auto surfaceNode = std::static_pointer_cast<const RSSurfaceRenderNode>(nodeSp);
170 if (surfaceNode == nullptr) {
171 return;
172 }
173 // mark all parent rendergroup need update; planning: mark autoCache need update
174 auto node = surfaceNode->GetParent().lock();
175 if (node == nullptr) {
176 return;
177 }
178
179 do {
180 if (node->GetType() == RSRenderNodeType::DISPLAY_NODE) {
181 break;
182 }
183 if (node->IsSuggestedDrawInGroup()) {
184 RS_OPTIONAL_TRACE_NAME_FMT("cache_changed by uifirst card %" PRIu64"", node->GetId());
185 node->SetDrawingCacheChanged(true);
186 node->AddToPendingSyncList();
187 }
188 node = node->GetParent().lock();
189 } while (node);
190 }
191
ProcessForceUpdateNode()192 void RSUifirstManager::ProcessForceUpdateNode()
193 {
194 if (!mainThread_) {
195 return;
196 }
197 std::vector<std::shared_ptr<RSRenderNode>> toDirtyNodes;
198 for (auto id : pendingForceUpdateNode_) {
199 auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(id);
200 if (!node) {
201 continue;
202 }
203 toDirtyNodes.push_back(node);
204 if (!node->IsDirty() && !node->IsSubTreeDirty()) {
205 markForceUpdateByUifirst_.push_back(node);
206 node->SetForceUpdateByUifirst(true);
207 }
208 if (node->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD) {
209 continue;
210 }
211 for (auto& child : *node->GetChildren()) {
212 if (!child) {
213 continue;
214 }
215 auto surfaceNode = child->ReinterpretCastTo<RSSurfaceRenderNode>();
216 if (!surfaceNode || !surfaceNode->IsMainWindowType()) {
217 continue;
218 }
219 toDirtyNodes.push_back(child);
220 if (!child->IsDirty() && !child->IsSubTreeDirty()) {
221 markForceUpdateByUifirst_.push_back(child);
222 child->SetForceUpdateByUifirst(true);
223 }
224 }
225 }
226 for (auto& node : toDirtyNodes) {
227 node->SetDirty(true);
228 }
229 pendingForceUpdateNode_.clear();
230 }
231
NotifyUIStartingWindow(NodeId id,bool wait)232 void RSUifirstManager::NotifyUIStartingWindow(NodeId id, bool wait)
233 {
234 if (mainThread_ == nullptr) {
235 return;
236 }
237 auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
238 mainThread_->GetContext().GetNodeMap().GetRenderNode(id));
239 if (node == nullptr || !node->IsLeashWindow()) {
240 return;
241 }
242 for (auto& child : *node->GetChildren()) {
243 if (!child) {
244 continue;
245 }
246 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
247 if (surfaceChild && surfaceChild->IsMainWindowType()) {
248 surfaceChild->SetWaitUifirstFirstFrame(wait);
249 RS_TRACE_NAME_FMT("uifirst NotifyUIStartingWindow id:%llu, wait:%d", surfaceChild->GetId(), wait);
250 RS_LOGI("uifirst NotifyUIStartingWindow id:%{public}" PRIu64 ", wait:%{public}d",
251 surfaceChild->GetId(), wait);
252 }
253 }
254 }
255
ProcessDoneNodeInner()256 void RSUifirstManager::ProcessDoneNodeInner()
257 {
258 std::vector<NodeId> tmp;
259 {
260 std::lock_guard<std::mutex> lock(childernDrawableMutex_);
261 if (subthreadProcessDoneNode_.size() == 0) {
262 return;
263 }
264 std::swap(tmp, subthreadProcessDoneNode_);
265 subthreadProcessDoneNode_.clear();
266 }
267 RS_TRACE_NAME_FMT("ProcessDoneNode num%d", tmp.size());
268 for (auto& id : tmp) {
269 RS_OPTIONAL_TRACE_NAME_FMT("Done %" PRIu64"", id);
270 auto drawable = GetSurfaceDrawableByID(id);
271 if (drawable && drawable->GetCacheSurfaceNeedUpdated() &&
272 drawable->GetCacheSurface(UNI_MAIN_THREAD_INDEX, false)) {
273 drawable->UpdateCompletedCacheSurface();
274 RenderGroupUpdate(drawable);
275 SetHasDoneNodeFlag(true);
276 pendingForceUpdateNode_.push_back(id);
277 }
278 NotifyUIStartingWindow(id, false);
279 subthreadProcessingNode_.erase(id);
280 }
281 }
282
ProcessDoneNode()283 void RSUifirstManager::ProcessDoneNode()
284 {
285 SetHasDoneNodeFlag(false);
286 ProcessDoneNodeInner();
287
288 // reset node when node is not doing
289 for (auto it = capturedNodes_.begin(); it != capturedNodes_.end();) {
290 if (mainThread_ && subthreadProcessingNode_.find(*it) == subthreadProcessingNode_.end()) {
291 // reset uifirst
292 auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
293 mainThread_->GetContext().GetNodeMap().GetRenderNode(*it));
294 if (node == nullptr) {
295 it = capturedNodes_.erase(it);
296 continue;
297 }
298 node->SetIsNodeToBeCaptured(false);
299 if (node->GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE) {
300 ResetUifirstNode(node);
301 }
302 it = capturedNodes_.erase(it);
303 } else {
304 it++;
305 }
306 }
307 for (auto it = pendingResetNodes_.begin(); it != pendingResetNodes_.end();) {
308 if (subthreadProcessingNode_.find(it->first) == subthreadProcessingNode_.end()) {
309 ResetUifirstNode(it->second);
310 it = pendingResetNodes_.erase(it);
311 } else {
312 it++;
313 }
314 }
315
316 for (auto it = subthreadProcessingNode_.begin(); it != subthreadProcessingNode_.end();) {
317 auto id = it->first;
318 auto drawable = GetSurfaceDrawableByID(id);
319 if (!drawable) {
320 ++it;
321 continue;
322 }
323 auto cacheStatus = drawable->GetCacheSurfaceProcessedStatus();
324 if ((drawable->HasCachedTexture() && cacheStatus == CacheProcessStatus::WAITING) ||
325 cacheStatus == CacheProcessStatus::SKIPPED) {
326 it = subthreadProcessingNode_.erase(it);
327 continue;
328 }
329 pendingPostNodes_.erase(it->first); // dele doing node in pendingpostlist
330 pendingPostCardNodes_.erase(it->first);
331 ++it;
332 }
333 }
334
SyncHDRDisplayParam(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable)335 void RSUifirstManager::SyncHDRDisplayParam(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable)
336 {
337 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
338 if (!surfaceParams || !surfaceParams->GetAncestorDisplayNode().lock()) {
339 return;
340 }
341 auto ancestor = surfaceParams->GetAncestorDisplayNode().lock()->ReinterpretCastTo<RSDisplayRenderNode>();
342 if (!ancestor) {
343 return;
344 }
345 auto displayParams = static_cast<RSDisplayRenderParams*>(ancestor->GetRenderParams().get());
346 if (!displayParams) {
347 return;
348 }
349 bool isHdrOn = displayParams->GetHDRPresent();
350 ScreenId id = displayParams->GetScreenId();
351 drawable->SetHDRPresent(isHdrOn);
352 if (isHdrOn) {
353 drawable->SetScreenId(id);
354 drawable->SetTargetColorGamut(displayParams->GetNewColorSpace());
355 }
356 RS_LOGD("UIFirstHDR SyncDisplayParam:%{public}d, ratio:%{public}f", drawable->GetHDRPresent(),
357 surfaceParams->GetBrightnessRatio());
358 }
359
CheckVisibleDirtyRegionIsEmpty(const std::shared_ptr<RSSurfaceRenderNode> & node)360 bool RSUifirstManager::CheckVisibleDirtyRegionIsEmpty(const std::shared_ptr<RSSurfaceRenderNode>& node)
361 {
362 if (RSMainThread::Instance()->GetDeviceType() != DeviceType::PC) {
363 return false;
364 }
365 for (auto& child : *node->GetSortedChildren()) {
366 if (std::shared_ptr<RSSurfaceRenderNode> surfaceNode =
367 RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child)) {
368 auto visibleRegion = surfaceNode->GetVisibleRegion();
369 if (visibleRegion.IsEmpty()) {
370 surfaceNode->SetUIFirstIsPurge(false);
371 return true;
372 }
373 auto drawable = surfaceNode->GetRenderDrawable();
374 if (!drawable) {
375 continue;
376 }
377 auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
378 auto surfaceDirtyRect = surfaceDrawable->GetSyncDirtyManager()->GetCurrentFrameDirtyRegion();
379 Occlusion::Rect dirtyRect { surfaceDirtyRect.left_, surfaceDirtyRect.top_,
380 surfaceDirtyRect.GetRight(), surfaceDirtyRect.GetBottom() };
381 Occlusion::Region surfaceDirtyRegion { dirtyRect };
382 Occlusion::Region surfaceVisibleDirtyRegion = surfaceDirtyRegion.And(visibleRegion);
383 if (surfaceVisibleDirtyRegion.IsEmpty()) {
384 surfaceNode->SetUIFirstIsPurge(false);
385 return true;
386 }
387 if (!surfaceNode->GetUIFirstIsPurge()) {
388 surfaceNode->SetUIFirstIsPurge(true);
389 return false;
390 }
391 }
392 }
393 return false;
394 }
395
DoPurgePendingPostNodes(std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>> & pendingNode)396 void RSUifirstManager::DoPurgePendingPostNodes(std::unordered_map<NodeId,
397 std::shared_ptr<RSSurfaceRenderNode>>& pendingNode)
398 {
399 auto deviceType = RSMainThread::Instance()->GetDeviceType();
400 for (auto it = pendingNode.begin(); it != pendingNode.end();) {
401 auto id = it->first;
402 auto drawable = GetSurfaceDrawableByID(id);
403 if (!drawable) {
404 ++it;
405 continue;
406 }
407 SyncHDRDisplayParam(drawable);
408 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
409 auto node = it->second;
410 if (!surfaceParams || !node) {
411 ++it;
412 continue;
413 }
414
415 if (!node->IsOnTheTree() && subthreadProcessingNode_.find(id) == subthreadProcessingNode_.end()) {
416 it = pendingNode.erase(it);
417 continue;
418 }
419
420 bool staticContent = drawable->IsCurFrameStatic(deviceType);
421 if (drawable->HasCachedTexture() && (staticContent || CheckVisibleDirtyRegionIsEmpty(node)) &&
422 (subthreadProcessingNode_.find(id) == subthreadProcessingNode_.end()) &&
423 !drawable->IsSubThreadSkip()) {
424 RS_OPTIONAL_TRACE_NAME_FMT("Purge node name %s", surfaceParams->GetName().c_str());
425 it = pendingNode.erase(it);
426 } else {
427 ++it;
428 }
429 }
430 }
431
PurgePendingPostNodes()432 void RSUifirstManager::PurgePendingPostNodes()
433 {
434 RS_OPTIONAL_TRACE_NAME_FMT("PurgePendingPostNodes");
435 DoPurgePendingPostNodes(pendingPostNodes_);
436 DoPurgePendingPostNodes(pendingPostCardNodes_);
437 for (auto& node : markForceUpdateByUifirst_) {
438 node->SetForceUpdateByUifirst(false);
439 }
440 markForceUpdateByUifirst_.clear();
441 }
442
PostSubTask(NodeId id)443 void RSUifirstManager::PostSubTask(NodeId id)
444 {
445 RS_TRACE_NAME("post UpdateCacheSurface");
446
447 if (subthreadProcessingNode_.find(id) != subthreadProcessingNode_.end()) { // drawable is doing, do not send
448 RS_TRACE_NAME_FMT("node %" PRIu64" is doing", id);
449 RS_LOGE("RSUifirstManager ERROR: post task twice");
450 return;
451 }
452
453 // 1.find in cache list(done to dele) 2.find in global list
454 auto drawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
455 if (drawable) {
456 // ref drawable
457 subthreadProcessingNode_.emplace(id, drawable);
458 // post task
459 RS_OPTIONAL_TRACE_NAME_FMT("Post_SubTask_s %" PRIu64"", id);
460 RSSubThreadManager::Instance()->ScheduleRenderNodeDrawable(
461 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable));
462 }
463 }
464
TryReleaseTextureForIdleThread()465 void RSUifirstManager::TryReleaseTextureForIdleThread()
466 {
467 if (noUifirstNodeFrameCount_.load() <= CLEAR_RES_THRESHOLD) {
468 return;
469 }
470 RSSubThreadManager::Instance()->TryReleaseTextureForIdleThread();
471 }
472
PostReleaseCacheSurfaceSubTasks()473 void RSUifirstManager::PostReleaseCacheSurfaceSubTasks()
474 {
475 for (auto cardNode : collectedCardNodes_) {
476 PostReleaseCacheSurfaceSubTask(cardNode);
477 }
478 }
479
PostReleaseCacheSurfaceSubTask(NodeId id)480 void RSUifirstManager::PostReleaseCacheSurfaceSubTask(NodeId id)
481 {
482 RS_OPTIONAL_TRACE_NAME_FMT("post ReleaseCacheSurface %d", id);
483
484 if (subthreadProcessingNode_.find(id) != subthreadProcessingNode_.end()) { // drawable is doing, do not send
485 RS_TRACE_NAME_FMT("node %" PRIu64" is doing", id);
486 RS_LOGE("RSUifirstManager ERROR: try to clean running node");
487 return;
488 }
489
490 // 1.find in cache list(done to dele) 2.find in global list
491 auto drawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
492 if (drawable) {
493 // post task
494 RS_OPTIONAL_TRACE_NAME_FMT("Post_SubTask_s %" PRIu64"", id);
495 RSSubThreadManager::Instance()->ScheduleReleaseCacheSurfaceOnly(
496 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable));
497 }
498 }
499
UpdateSkipSyncNode()500 void RSUifirstManager::UpdateSkipSyncNode()
501 {
502 processingNodeSkipSync_.clear();
503 processingNodePartialSync_.clear();
504 processingCardNodeSkipSync_.clear();
505 RS_OPTIONAL_TRACE_NAME_FMT("UpdateSkipSyncNode doning%d", subthreadProcessingNode_.size());
506 if (subthreadProcessingNode_.size() == 0) {
507 return;
508 }
509 if (!mainThread_) {
510 return;
511 }
512 for (auto it = subthreadProcessingNode_.begin(); it != subthreadProcessingNode_.end(); it++) {
513 RS_OPTIONAL_TRACE_NAME_FMT("doning%" PRIu64"", it->first);
514 auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(it->first);
515 if (!node) {
516 continue;
517 }
518 auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>();
519 if (!surfaceNode) {
520 continue;
521 }
522 // ArkTSCard
523 if (NodeIsInCardWhiteList(*node)) {
524 if (surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD) {
525 processingCardNodeSkipSync_.insert(it->first);
526 continue;
527 }
528 }
529
530 // leash window
531 processingNodePartialSync_.insert(it->first); // partial sync
532 std::vector<std::pair<NodeId, std::weak_ptr<RSSurfaceRenderNode>>> allSubSurfaceNodes;
533 surfaceNode->GetAllSubSurfaceNodes(allSubSurfaceNodes);
534 for (auto& [id, subSurfaceNode] : allSubSurfaceNodes) {
535 processingNodeSkipSync_.insert(id); // skip sync
536 }
537 }
538 }
539
ProcessSubDoneNode()540 void RSUifirstManager::ProcessSubDoneNode()
541 {
542 RS_OPTIONAL_TRACE_NAME_FMT("ProcessSubDoneNode");
543 ConvertPendingNodeToDrawable();
544 ProcessDoneNode(); // release finish drawable
545 UpdateSkipSyncNode();
546 RestoreSkipSyncNode();
547 ResetCurrentFrameDeletedCardNodes();
548 }
549
ConvertPendingNodeToDrawable()550 void RSUifirstManager::ConvertPendingNodeToDrawable()
551 {
552 {
553 std::lock_guard<std::mutex> lock(useDmaBufferMutex_);
554 if (!useDmaBuffer_) {
555 return;
556 }
557 }
558 pendingPostDrawables_.clear();
559 for (const auto& iter : pendingPostNodes_) {
560 if (iter.second && GetUseDmaBuffer(iter.second->GetName())) {
561 if (auto drawableNode = DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(iter.second)) {
562 pendingPostDrawables_.emplace_back(
563 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawableNode));
564 }
565 }
566 }
567 }
568
SetUifirstSkipPartialSync(const std::shared_ptr<RSRenderNode> & node,bool needSync)569 static inline void SetUifirstSkipPartialSync(const std::shared_ptr<RSRenderNode> &node, bool needSync)
570 {
571 // node not null in caller
572 if (!needSync) {
573 return;
574 }
575 node->SetUifirstSkipPartialSync(true);
576 }
577
GetUifirstCachedState(NodeId id)578 CacheProcessStatus& RSUifirstManager::GetUifirstCachedState(NodeId id)
579 {
580 auto ret = uifirstCacheState_.insert({ id, CacheProcessStatus::UNKNOWN });
581 auto& curRootIdState = ret.first->second;
582 if (curRootIdState == CacheProcessStatus::UNKNOWN) {
583 /* first time to get the state of uifirstRoot, and cache the state for the remaining other times */
584 auto uifirstRootNodeDrawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
585 if (uifirstRootNodeDrawable && uifirstRootNodeDrawable->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
586 auto drawableNode =
587 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(uifirstRootNodeDrawable);
588 curRootIdState = drawableNode->GetCacheSurfaceProcessedStatus();
589 }
590 }
591 return curRootIdState;
592 }
593
CollectSkipSyncNodeWithDrawableState(const std::shared_ptr<RSRenderNode> & node)594 RSUifirstManager::SkipSyncState RSUifirstManager::CollectSkipSyncNodeWithDrawableState(
595 const std::shared_ptr<RSRenderNode>& node)
596 {
597 auto isPreDoing = IsPreFirstLevelNodeDoingAndTryClear(node);
598 auto drawable = node->GetRenderDrawable();
599 if (UNLIKELY(!drawable || !drawable->GetRenderParams())) {
600 RS_LOGE("RSUifirstManager::CollectSkipSyncNode drawable/params nullptr");
601 // must not be in the DOING state with the invalid drawable.
602 return SkipSyncState::STATE_NOT_SKIP;
603 }
604 auto& params = drawable->GetRenderParams();
605 // if node's UifirstRootNodeId is valid (e.g. ArkTsCard), use it first
606 auto uifirstRootId = params->GetUifirstRootNodeId() != INVALID_NODEID ?
607 params->GetUifirstRootNodeId() : params->GetFirstLevelNodeId();
608 auto& curRootIdState = GetUifirstCachedState(uifirstRootId);
609 RS_OPTIONAL_TRACE_NAME_FMT("node[%" PRIu64 " %" PRIu64 "] drawable[%"
610 PRIu64 " %" PRIu64 "] and curNodeId [%" PRIu64"] cacheState[%d]",
611 node->GetStagingRenderParams()->GetUifirstRootNodeId(), node->GetStagingRenderParams()->GetFirstLevelNodeId(),
612 params->GetUifirstRootNodeId(), params->GetFirstLevelNodeId(), node->GetId(), curRootIdState);
613
614 if (curRootIdState == CacheProcessStatus::DOING || curRootIdState == CacheProcessStatus::WAITING ||
615 /* unknow state to check prefirstLevelNode */
616 (uifirstRootId == INVALID_NODEID && isPreDoing)) {
617 pendingSyncForSkipBefore_[uifirstRootId].push_back(node);
618 auto isUifirstRootNode = (uifirstRootId == node->GetId());
619 RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
620 isUifirstRootNode ? "set partial_sync" : "CollectSkipSyncNode", node->GetId(), uifirstRootId);
621 SetUifirstSkipPartialSync(node, isUifirstRootNode);
622 return isUifirstRootNode ? SkipSyncState::STATE_NOT_SKIP : SkipSyncState::STATE_NEED_SKIP;
623 }
624 return SkipSyncState::STATE_NEED_CHECK;
625 }
626
CollectSkipSyncNode(const std::shared_ptr<RSRenderNode> & node)627 bool RSUifirstManager::CollectSkipSyncNode(const std::shared_ptr<RSRenderNode> &node)
628 {
629 if (!node) {
630 return false;
631 }
632 if (pendingPostNodes_.find(node->GetId()) != pendingPostNodes_.end() ||
633 pendingPostCardNodes_.find(node->GetId()) != pendingPostCardNodes_.end()) {
634 node->SetUifirstSyncFlag(true);
635 }
636
637 auto ret = CollectSkipSyncNodeWithDrawableState(node);
638 if (ret != SkipSyncState::STATE_NEED_CHECK) {
639 return ret == SkipSyncState::STATE_NEED_SKIP;
640 }
641
642 if (NodeIsInCardWhiteList(*node) && processingCardNodeSkipSync_.count(node->GetUifirstRootNodeId())) {
643 pendingSyncForSkipBefore_[node->GetUifirstRootNodeId()].push_back(node);
644 auto isUifirstRootNode = (node->GetUifirstRootNodeId() == node->GetId());
645 RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
646 isUifirstRootNode ? "set partial_sync card" : "CollectSkipSyncNode card",
647 node->GetId(), node->GetInstanceRootNodeId());
648 SetUifirstSkipPartialSync(node, isUifirstRootNode);
649 return !isUifirstRootNode;
650 }
651 if (processingNodePartialSync_.count(node->GetInstanceRootNodeId()) > 0) {
652 pendingSyncForSkipBefore_[node->GetInstanceRootNodeId()].push_back(node);
653 auto isInstanceRootNode = (node->GetInstanceRootNodeId() == node->GetId());
654 RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
655 isInstanceRootNode ? "set partial_sync" : "CollectSkipSyncNode",
656 node->GetId(), node->GetInstanceRootNodeId());
657 SetUifirstSkipPartialSync(node, isInstanceRootNode);
658 return !isInstanceRootNode;
659 } else if (processingNodeSkipSync_.count(node->GetInstanceRootNodeId()) > 0) {
660 RS_OPTIONAL_TRACE_NAME_FMT("CollectSkipSyncNode root %" PRIu64", node %" PRIu64,
661 node->GetInstanceRootNodeId(), node->GetId());
662 pendingSyncForSkipBefore_[node->GetInstanceRootNodeId()].push_back(node);
663 return true;
664 }
665 return false;
666 }
667
RestoreSkipSyncNode()668 void RSUifirstManager::RestoreSkipSyncNode()
669 {
670 std::vector<NodeId> todele;
671 for (auto& it : pendingSyncForSkipBefore_) {
672 if (processingNodeSkipSync_.count(it.first) == 0 && processingNodePartialSync_.count(it.first) == 0 &&
673 processingCardNodeSkipSync_.count(it.first) == 0) {
674 todele.push_back(it.first);
675 RS_OPTIONAL_TRACE_NAME_FMT("RestoreSkipSyncNode %" PRIu64" num%d", it.first, it.second.size());
676 for (auto& node : it.second) {
677 node->SetUifirstSkipPartialSync(false);
678 node->AddToPendingSyncList();
679 }
680 }
681 }
682 for (auto id : todele) {
683 pendingSyncForSkipBefore_.erase(id);
684 if (!mainThread_) {
685 continue;
686 }
687 auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(id);
688 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node);
689 if (!surfaceNode) {
690 continue;
691 }
692 if (surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD &&
693 surfaceNode->GetUifirstRootNodeId() == surfaceNode->GetId() &&
694 pendingPostCardNodes_.find(surfaceNode->GetId()) == pendingPostCardNodes_.end()) {
695 pendingPostCardNodes_[surfaceNode->GetId()] = surfaceNode;
696 RS_OPTIONAL_TRACE_NAME_FMT("RestoreSkipSyncNode AddPendingPostCard %llu", id);
697 }
698 }
699 }
700
ClearSubthreadRes()701 void RSUifirstManager::ClearSubthreadRes()
702 {
703 RS_OPTIONAL_TRACE_NAME_FMT("ClearSubthreadRes");
704 if (subthreadProcessingNode_.size() == 0 &&
705 pendingSyncForSkipBefore_.size() == 0) {
706 noUifirstNodeFrameCount_.fetch_add(1);
707 if (noUifirstNodeFrameCount_.load() == CLEAR_RES_THRESHOLD) {
708 RSSubThreadManager::Instance()->ResetSubThreadGrContext();
709 PostReleaseCacheSurfaceSubTasks();
710 }
711 } else {
712 noUifirstNodeFrameCount_.store(0);
713 }
714 reuseNodes_.clear();
715 }
716
ForceClearSubthreadRes()717 void RSUifirstManager::ForceClearSubthreadRes()
718 {
719 noUifirstNodeFrameCount_.store(0);
720 RSSubThreadManager::Instance()->ReleaseTexture();
721 }
722
IsPreFirstLevelNodeDoingAndTryClear(std::shared_ptr<RSRenderNode> node)723 bool RSUifirstManager::IsPreFirstLevelNodeDoingAndTryClear(std::shared_ptr<RSRenderNode> node)
724 {
725 if (!node) {
726 return true;
727 }
728 auto& preFirstLevelNodeIdSet = node->GetMutablePreFirstLevelNodeIdSet();
729 for (auto it = preFirstLevelNodeIdSet.begin(); it != preFirstLevelNodeIdSet.end();
730 it = preFirstLevelNodeIdSet.erase(it)) {
731 auto& curRootIdState = GetUifirstCachedState(*it);
732 if (curRootIdState == CacheProcessStatus::DOING || curRootIdState == CacheProcessStatus::WAITING) {
733 return true;
734 }
735 }
736 return false;
737 }
738
SetNodePriorty(std::list<NodeId> & result,std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>> & pendingNode)739 void RSUifirstManager::SetNodePriorty(std::list<NodeId>& result,
740 std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>& pendingNode)
741 {
742 bool isFocusNodeFound = false;
743 for (auto& item : pendingNode) {
744 auto const& [id, value] = item;
745 if (IsPreFirstLevelNodeDoingAndTryClear(value)) {
746 continue;
747 }
748 auto drawable = GetSurfaceDrawableByID(id);
749 if (!drawable) {
750 continue;
751 }
752 if (!isFocusNodeFound) {
753 bool isFocus = ((id == RSMainThread::Instance()->GetFocusNodeId()) ||
754 (id == RSMainThread::Instance()->GetFocusLeashWindowId()));
755 if (isFocus) {
756 // for resolving response latency
757 drawable->SetRenderCachePriority(NodePriorityType::SUB_FOCUSNODE_PRIORITY);
758 isFocusNodeFound = true;
759 }
760 }
761 if (drawable->HasCachedTexture()) {
762 drawable->SetRenderCachePriority(NodePriorityType::SUB_LOW_PRIORITY);
763 } else {
764 drawable->SetRenderCachePriority(NodePriorityType::SUB_HIGH_PRIORITY);
765 }
766 if (drawable->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::WAITING) {
767 drawable->SetRenderCachePriority(NodePriorityType::SUB_HIGH_PRIORITY);
768 }
769 sortedSubThreadNodeIds_.emplace_back(id);
770 }
771 }
772
SortSubThreadNodesPriority()773 void RSUifirstManager::SortSubThreadNodesPriority()
774 {
775 sortedSubThreadNodeIds_.clear();
776 SetNodePriorty(sortedSubThreadNodeIds_, pendingPostNodes_);
777 SetNodePriorty(sortedSubThreadNodeIds_, pendingPostCardNodes_);
778
779 sortedSubThreadNodeIds_.sort([this](const auto& first, const auto& second) -> bool {
780 auto drawable1 = GetSurfaceDrawableByID(first);
781 auto drawable2 = GetSurfaceDrawableByID(second);
782 if (drawable1 == nullptr || drawable2 == nullptr) {
783 ROSEN_LOGE("RSUifirstManager::SortSubThreadNodesPriority sort nullptr found in pendingPostNodes_, "
784 "this should not happen");
785 return false;
786 }
787 auto surfaceParams1 = static_cast<RSSurfaceRenderParams*>(drawable1->GetRenderParams().get());
788 if (!surfaceParams1) {
789 RS_LOGE("RSSurfaceRenderNodeDrawable::sortsubthread params1 is nullptr");
790 return false;
791 }
792 auto surfaceParams2 = static_cast<RSSurfaceRenderParams*>(drawable2->GetRenderParams().get());
793 if (!surfaceParams2) {
794 RS_LOGE("RSSurfaceRenderNodeDrawable::sortsubthread params2 is nullptr");
795 return false;
796 }
797 if (drawable1->GetRenderCachePriority() == drawable2->GetRenderCachePriority()) {
798 return surfaceParams2->GetPositionZ() < surfaceParams1->GetPositionZ();
799 } else {
800 return drawable1->GetRenderCachePriority() < drawable2->GetRenderCachePriority();
801 }
802 });
803 }
804
805 // post in drawframe sync time
PostUifistSubTasks()806 void RSUifirstManager::PostUifistSubTasks()
807 {
808 // if screen is power-off, uifirst sub thread can be suspended.
809 if (RSUniRenderUtil::CheckRenderSkipIfScreenOff()) {
810 return;
811 }
812 PurgePendingPostNodes();
813 SortSubThreadNodesPriority();
814 if (sortedSubThreadNodeIds_.size() > 0) {
815 for (auto& id : sortedSubThreadNodeIds_) {
816 PostSubTask(id);
817 }
818 pendingPostNodes_.clear();
819 pendingPostCardNodes_.clear();
820 sortedSubThreadNodeIds_.clear();
821 } else {
822 ClearSubthreadRes();
823 }
824 UifirstCurStateClear();
825 }
826
IsInLeashWindowTree(RSSurfaceRenderNode & node,NodeId instanceRootId)827 bool RSUifirstManager::IsInLeashWindowTree(RSSurfaceRenderNode& node, NodeId instanceRootId)
828 {
829 if (node.GetInstanceRootNodeId() == instanceRootId) {
830 return true;
831 }
832 if (!node.IsLeashWindow()) {
833 return false;
834 }
835 for (auto& child : *(node.GetChildren())) {
836 if (!child) {
837 continue;
838 }
839 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
840 if (!surfaceChild) {
841 continue;
842 }
843 if (surfaceChild->GetInstanceRootNodeId() == instanceRootId) {
844 return true;
845 }
846 }
847 return false;
848 }
849
LeashWindowContainMainWindow(RSSurfaceRenderNode & node)850 static inline bool LeashWindowContainMainWindow(RSSurfaceRenderNode& node)
851 {
852 if (node.IsLeashWindow() && node.HasSubSurfaceNodes()) {
853 return true;
854 }
855 return false;
856 }
857
AddPendingPostNode(NodeId id,std::shared_ptr<RSSurfaceRenderNode> & node,MultiThreadCacheType currentFrameCacheType)858 void RSUifirstManager::AddPendingPostNode(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node,
859 MultiThreadCacheType currentFrameCacheType)
860 {
861 if (id == INVALID_NODEID || !node) {
862 return;
863 }
864
865 // process for uifirst node
866 UpdateChildrenDirtyRect(*node);
867 node->SetHwcChildrenDisabledStateByUifirst();
868 node->AddToPendingSyncList();
869
870 if (currentFrameCacheType == MultiThreadCacheType::LEASH_WINDOW ||
871 currentFrameCacheType == MultiThreadCacheType::NONFOCUS_WINDOW) {
872 if (isRecentTaskScene_.load() && !node->IsNodeToBeCaptured() &&
873 currentFrameCacheType == MultiThreadCacheType::LEASH_WINDOW) {
874 node->SetIsNodeToBeCaptured(true);
875 } else if (!isRecentTaskScene_.load()) {
876 node->SetIsNodeToBeCaptured(false);
877 }
878 // delete card node in leashwindow tree
879 for (auto it = pendingPostCardNodes_.begin(); it != pendingPostCardNodes_.end();) {
880 auto surfaceNode = it->second;
881 if (surfaceNode && IsInLeashWindowTree(*node, surfaceNode->GetInstanceRootNodeId())) {
882 DisableUifirstNode(*surfaceNode);
883 it = pendingPostCardNodes_.erase(it);
884 } else {
885 it++;
886 }
887 }
888 pendingPostNodes_[id] = node;
889 } else if (currentFrameCacheType == MultiThreadCacheType::ARKTS_CARD) {
890 pendingPostCardNodes_[id] = node;
891 }
892
893 pendingResetNodes_.erase(id); // enable uifirst when waiting for reset
894 }
895
LeashWindowContainMainWindowAndStarting(RSSurfaceRenderNode & node)896 NodeId RSUifirstManager::LeashWindowContainMainWindowAndStarting(RSSurfaceRenderNode& node)
897 {
898 if (!node.IsLeashWindow()) {
899 return INVALID_NODEID;
900 }
901 int mainwindowNum = 0;
902 int canvasNodeNum = 0;
903 bool support = true;
904 std::shared_ptr<RSRenderNode> startingWindow = nullptr;
905 for (auto& child : *(node.GetSortedChildren())) {
906 if (!child) {
907 continue;
908 }
909 RS_TRACE_NAME_FMT("nID:%" PRIu64" , nType:%d, support:%d, canvasNodeNum:%d, mainwindowNum:%d",
910 child->GetId(), static_cast<int>(child->GetType()), support, canvasNodeNum, mainwindowNum);
911 auto canvasChild = child->ReinterpretCastTo<RSCanvasRenderNode>();
912 if (canvasChild && canvasChild->GetChildrenCount() == 0 && mainwindowNum > 0) {
913 canvasNodeNum++;
914 startingWindow = canvasChild;
915 continue;
916 }
917 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
918 if (surfaceChild && surfaceChild->IsMainWindowType() && canvasNodeNum == 0) {
919 mainwindowNum++;
920 continue;
921 }
922 support = false;
923 }
924 RS_TRACE_NAME_FMT("uifirst_node support:%d, canvasNodeNum:%d, mainwindowNum:%d, startingWindow:%d",
925 support, canvasNodeNum, mainwindowNum, startingWindow != nullptr);
926 if (support && canvasNodeNum == 1 && mainwindowNum > 0 && startingWindow) { // starting window & appwindow
927 startingWindow->SetStartingWindowFlag(true);
928 return startingWindow->GetId();
929 } else {
930 return INVALID_NODEID;
931 }
932 }
933
AddPendingResetNode(NodeId id,std::shared_ptr<RSSurfaceRenderNode> & node)934 void RSUifirstManager::AddPendingResetNode(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node)
935 {
936 if (id == INVALID_NODEID) {
937 return;
938 }
939 pendingResetNodes_[id] = node;
940 }
941
GetNodeStatus(NodeId id)942 CacheProcessStatus RSUifirstManager::GetNodeStatus(NodeId id)
943 {
944 auto drawable = GetSurfaceDrawableByID(id);
945 if (drawable) {
946 return drawable->GetCacheSurfaceProcessedStatus();
947 }
948 return CacheProcessStatus::UNKNOWN;
949 }
950
UpdateCompletedSurface(NodeId id)951 void RSUifirstManager::UpdateCompletedSurface(NodeId id)
952 {
953 auto drawable = GetSurfaceDrawableByID(id);
954 if (drawable) {
955 drawable->UpdateCompletedCacheSurface();
956 }
957 }
958
959 // add&clear in render
AddReuseNode(NodeId id)960 void RSUifirstManager::AddReuseNode(NodeId id)
961 {
962 if (id == INVALID_NODEID) {
963 return;
964 }
965 reuseNodes_.insert(id);
966 }
967
OnProcessEventResponse(DataBaseRs & info)968 void RSUifirstManager::OnProcessEventResponse(DataBaseRs& info)
969 {
970 RS_OPTIONAL_TRACE_NAME_FMT("uifirst uniqueId:%" PRId64", appPid:%" PRId32", sceneId:%s",
971 info.uniqueId, info.appPid, info.sceneId.c_str());
972 EventInfo eventInfo = {GetCurSysTime(), 0, info.uniqueId, info.appPid, info.sceneId, {}};
973 std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
974 for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
975 it->disableNodes.clear();
976 }
977 globalFrameEvent_.push_back(std::move(eventInfo));
978 currentFrameCanSkipFirstWait_ = EventsCanSkipFirstWait(globalFrameEvent_);
979 }
980
OnProcessEventComplete(DataBaseRs & info)981 void RSUifirstManager::OnProcessEventComplete(DataBaseRs& info)
982 {
983 int64_t curSysTime = GetCurSysTime();
984 std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
985 for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
986 if (it->uniqueId == info.uniqueId && it->sceneId == info.sceneId) {
987 // delay delete for animation continue
988 it->stopTime = curSysTime;
989 break;
990 }
991 }
992 }
993
EventDisableLeashWindowCache(NodeId id,EventInfo & info)994 void RSUifirstManager::EventDisableLeashWindowCache(NodeId id, EventInfo& info)
995 {
996 std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
997 for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
998 if (it->uniqueId == info.uniqueId && it->sceneId == info.sceneId) {
999 it->disableNodes.insert(id);
1000 break;
1001 }
1002 }
1003 }
1004
PrepareCurrentFrameEvent()1005 void RSUifirstManager::PrepareCurrentFrameEvent()
1006 {
1007 int64_t curSysTime = GetCurSysTime();
1008 currentFrameEvent_.clear();
1009 if (!mainThread_ || entryViewNodeId_ == INVALID_NODEID || negativeScreenNodeId_ == INVALID_NODEID) {
1010 mainThread_ = RSMainThread::Instance();
1011 if (mainThread_) {
1012 entryViewNodeId_ = mainThread_->GetContext().GetNodeMap().GetEntryViewNodeId();
1013 negativeScreenNodeId_ = mainThread_->GetContext().GetNodeMap().GetNegativeScreenNodeId();
1014 scbPid_ = ExtractPid(entryViewNodeId_);
1015 }
1016 }
1017 {
1018 std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1019 for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end();) {
1020 if (it->stopTime != 0 &&
1021 ((curSysTime > it->stopTime) && (curSysTime - it->stopTime) > EVENT_STOP_TIMEOUT)) {
1022 it = globalFrameEvent_.erase(it);
1023 continue;
1024 }
1025
1026 if ((curSysTime > it->startTime) && (curSysTime - it->startTime) > EVENT_START_TIMEOUT) {
1027 it = globalFrameEvent_.erase(it);
1028 continue;
1029 }
1030 it++;
1031 }
1032 if (globalFrameEvent_.empty()) {
1033 currentFrameCanSkipFirstWait_ = false;
1034 return;
1035 }
1036 // copy global to current, judge leashwindow stop
1037 currentFrameEvent_.assign(globalFrameEvent_.begin(), globalFrameEvent_.end());
1038 }
1039 currentFrameCanSkipFirstWait_ = EventsCanSkipFirstWait(currentFrameEvent_);
1040 }
1041
OnProcessAnimateScene(SystemAnimatedScenes systemAnimatedScene)1042 void RSUifirstManager::OnProcessAnimateScene(SystemAnimatedScenes systemAnimatedScene)
1043 {
1044 RS_TRACE_NAME_FMT("RSUifirstManager::OnProcessAnimateScene systemAnimatedScene:%d", systemAnimatedScene);
1045 if ((systemAnimatedScene == SystemAnimatedScenes::ENTER_RECENTS) && !isRecentTaskScene_.load()) {
1046 isRecentTaskScene_ = true;
1047 } else if ((systemAnimatedScene == SystemAnimatedScenes::EXIT_RECENTS) && isRecentTaskScene_.load()) {
1048 isRecentTaskScene_ = false;
1049 }
1050 }
1051
NodeIsInCardWhiteList(RSRenderNode & node)1052 bool RSUifirstManager::NodeIsInCardWhiteList(RSRenderNode& node)
1053 {
1054 if ((entryViewNodeId_ != INVALID_NODEID) && (negativeScreenNodeId_ != INVALID_NODEID)) {
1055 auto instanceRootId = node.GetInstanceRootNodeId();
1056 if (instanceRootId == entryViewNodeId_ || instanceRootId == negativeScreenNodeId_) {
1057 return true;
1058 }
1059 }
1060 return false;
1061 }
1062
IsCardSkipFirstWaitScene(std::string & scene,int32_t appPid)1063 bool RSUifirstManager::IsCardSkipFirstWaitScene(std::string& scene, int32_t appPid)
1064 {
1065 if (appPid != scbPid_) {
1066 return false;
1067 }
1068 for (auto& item : cardCanSkipFirstWaitScene_) {
1069 if ((scene.find(item) != std::string::npos)) {
1070 return true;
1071 }
1072 }
1073 return false;
1074 }
1075
EventsCanSkipFirstWait(std::vector<EventInfo> & events)1076 bool RSUifirstManager::EventsCanSkipFirstWait(std::vector<EventInfo>& events)
1077 {
1078 if (events.empty()) {
1079 return false;
1080 }
1081 if (isCurrentFrameHasCardNodeReCreate_) {
1082 RS_OPTIONAL_TRACE_NAME("uifirst current frame can't skip wait");
1083 return false;
1084 }
1085 for (auto& item : events) {
1086 if (IsCardSkipFirstWaitScene(item.sceneId, item.appPid)) {
1087 return true;
1088 }
1089 }
1090 return false;
1091 }
1092
IsScreenshotAnimation()1093 bool RSUifirstManager::IsScreenshotAnimation()
1094 {
1095 for (auto& it : currentFrameEvent_) {
1096 if (std::find(screenshotAnimation_.begin(), screenshotAnimation_.end(), it.sceneId) !=
1097 screenshotAnimation_.end()) {
1098 return true;
1099 }
1100 }
1101 return false;
1102 }
1103
CheckIfAppWindowHasAnimation(RSSurfaceRenderNode & node)1104 bool RSUifirstManager::CheckIfAppWindowHasAnimation(RSSurfaceRenderNode& node)
1105 {
1106 if (currentFrameEvent_.empty()) {
1107 return false;
1108 }
1109
1110 std::set<int32_t> appPids;
1111 if (node.IsAppWindow()) {
1112 appPids.insert(ExtractPid(node.GetId()));
1113 } else if (node.IsLeashWindow()) {
1114 for (auto& child : *(node.GetChildren())) {
1115 if (!child) {
1116 continue;
1117 }
1118 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1119 if (!surfaceChild) {
1120 continue;
1121 }
1122 if (surfaceChild->IsAppWindow()) {
1123 appPids.insert(ExtractPid(surfaceChild->GetId()));
1124 }
1125 }
1126 }
1127
1128 if (appPids.empty()) {
1129 return false;
1130 }
1131 for (auto& item : currentFrameEvent_) {
1132 if (item.disableNodes.count(node.GetId())) {
1133 return true;
1134 }
1135 if (appPids.count(item.appPid) && (node.GetUifirstStartTime() > 0) &&
1136 (node.GetUifirstStartTime() < (item.startTime - EVENT_DISABLE_UIFIRST_GAP)) &&
1137 (item.sceneId.find(EVENT_DISABLE_UIFIRST) != std::string::npos)) {
1138 EventDisableLeashWindowCache(node.GetId(), item);
1139 return true; // app has animation, stop leashwindow uifirst
1140 }
1141 }
1142 return false;
1143 }
1144
IsArkTsCardCache(RSSurfaceRenderNode & node,bool animation)1145 bool RSUifirstManager::IsArkTsCardCache(RSSurfaceRenderNode& node, bool animation) // maybe canvas node ?
1146 {
1147 auto baseNode = node.GetAncestorDisplayNode().lock();
1148 if (!baseNode) {
1149 RS_LOGE("surfaceNode GetAncestorDisplayNode().lock() return nullptr");
1150 return false;
1151 }
1152 auto curDisplayNode = baseNode->ReinterpretCastTo<RSDisplayRenderNode>();
1153 if (curDisplayNode == nullptr) {
1154 RS_LOGE("surfaceNode GetAncestorDisplayNode().lock() return nullptr");
1155 return false;
1156 }
1157 if (RSLuminanceControl::Get().IsHdrOn(curDisplayNode->GetScreenId())) {
1158 return false;
1159 }
1160 bool flag = ((RSMainThread::Instance()->GetDeviceType() == DeviceType::PHONE) &&
1161 (node.GetSurfaceNodeType() == RSSurfaceNodeType::ABILITY_COMPONENT_NODE) &&
1162 RSUifirstManager::Instance().NodeIsInCardWhiteList(node) &&
1163 (node.ShouldPaint()) && (node.GetName().find(ARKTSCARDNODE_NAME) != std::string::npos));
1164 if (flag) { // Planning: mark by arkui or app
1165 return true;
1166 }
1167 return false;
1168 }
1169
1170 // animation first, may reuse last image cache
IsLeashWindowCache(RSSurfaceRenderNode & node,bool animation)1171 bool RSUifirstManager::IsLeashWindowCache(RSSurfaceRenderNode& node, bool animation)
1172 {
1173 if (RSUifirstManager::Instance().GetUseDmaBuffer(node.GetName())) {
1174 return true;
1175 }
1176 bool isNeedAssignToSubThread = false;
1177 if ((RSMainThread::Instance()->GetDeviceType() == DeviceType::PC) ||
1178 (node.GetFirstLevelNodeId() != node.GetId()) ||
1179 (RSUifirstManager::Instance().NodeIsInCardWhiteList(node)) ||
1180 (RSUifirstManager::Instance().CheckIfAppWindowHasAnimation(node))) {
1181 return false;
1182 }
1183 if (node.IsLeashWindow()) {
1184 if (RSUifirstManager::Instance().IsRecentTaskScene()) {
1185 isNeedAssignToSubThread = node.IsScale() && LeashWindowContainMainWindow(node);
1186 } else {
1187 isNeedAssignToSubThread = animation;
1188 }
1189 // 1: Planning: support multi appwindows
1190 isNeedAssignToSubThread = (isNeedAssignToSubThread || ROSEN_EQ(node.GetGlobalAlpha(), 0.0f) ||
1191 node.GetForceUIFirst()) && !node.HasFilter() && !RSUifirstManager::Instance().rotationChanged_;
1192 }
1193
1194 std::string surfaceName = node.GetName();
1195 bool needFilterSCB = node.GetSurfaceWindowType() == SurfaceWindowType::SYSTEM_SCB_WINDOW;
1196 if (needFilterSCB || node.IsSelfDrawingType()) {
1197 RS_TRACE_NAME_FMT("IsLeashWindowCache: needFilterSCB [%d]", needFilterSCB);
1198 return false;
1199 }
1200 RS_TRACE_NAME_FMT("IsLeashWindowCache: toSubThread[%d] IsScale[%d]"
1201 " filter:[%d] rotate[%d] captured[%d] snapshot[%d]",
1202 isNeedAssignToSubThread, node.IsScale(),
1203 node.HasFilter(), RSUifirstManager::Instance().rotationChanged_, node.IsNodeToBeCaptured(),
1204 RSUniRenderThread::GetCaptureParam().isSnapshot_);
1205 return isNeedAssignToSubThread;
1206 }
1207
1208 // NonFocusWindow, may reuse last image cache
IsNonFocusWindowCache(RSSurfaceRenderNode & node,bool animation)1209 bool RSUifirstManager::IsNonFocusWindowCache(RSSurfaceRenderNode& node, bool animation)
1210 {
1211 bool isDisplayRotation = RSUifirstManager::Instance().rotationChanged_;
1212 if ((RSMainThread::Instance()->GetDeviceType() != DeviceType::PC) ||
1213 (node.GetFirstLevelNodeId() != node.GetId()) ||
1214 (RSUifirstManager::Instance().NodeIsInCardWhiteList(node))) {
1215 return false;
1216 }
1217
1218 std::string surfaceName = node.GetName();
1219 bool needFilterSCB = node.GetSurfaceWindowType() == SurfaceWindowType::SYSTEM_SCB_WINDOW;
1220 if (!node.GetForceUIFirst() && (needFilterSCB || node.IsSelfDrawingType())) {
1221 return false;
1222 }
1223 if ((node.IsFocusedNode(RSMainThread::Instance()->GetFocusNodeId()) ||
1224 node.IsFocusedNode(RSMainThread::Instance()->GetFocusLeashWindowId())) &&
1225 node.GetHasSharedTransitionNode()) {
1226 return false;
1227 }
1228 return node.QuerySubAssignable(isDisplayRotation);
1229 }
1230
UpdateUifirstNodes(RSSurfaceRenderNode & node,bool ancestorNodeHasAnimation)1231 void RSUifirstManager::UpdateUifirstNodes(RSSurfaceRenderNode& node, bool ancestorNodeHasAnimation)
1232 {
1233 RS_TRACE_NAME_FMT("UpdateUifirstNodes: Id[%llu] name[%s] FLId[%llu] Ani[%d] Support[%d] isUiFirstOn[%d]",
1234 node.GetId(), node.GetName().c_str(), node.GetFirstLevelNodeId(),
1235 ancestorNodeHasAnimation, node.GetUifirstSupportFlag(), isUiFirstOn_);
1236 if (!isUiFirstOn_ || !node.GetUifirstSupportFlag()) {
1237 UifirstStateChange(node, MultiThreadCacheType::NONE);
1238 if (!node.isUifirstNode_) {
1239 node.isUifirstDelay_++;
1240 if (node.isUifirstDelay_ > EVENT_STOP_TIMEOUT) {
1241 node.isUifirstNode_ = true;
1242 }
1243 }
1244 return;
1245 }
1246 if (RSUifirstManager::IsLeashWindowCache(node, ancestorNodeHasAnimation)) {
1247 UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1248 return;
1249 }
1250 if (RSUifirstManager::IsNonFocusWindowCache(node, ancestorNodeHasAnimation)) {
1251 UifirstStateChange(node, MultiThreadCacheType::NONFOCUS_WINDOW);
1252 return;
1253 }
1254 if (RSUifirstManager::IsArkTsCardCache(node, ancestorNodeHasAnimation)) {
1255 UifirstStateChange(node, MultiThreadCacheType::ARKTS_CARD);
1256 return;
1257 }
1258 UifirstStateChange(node, MultiThreadCacheType::NONE);
1259 }
1260
UpdateUIFirstNodeUseDma(RSSurfaceRenderNode & node,const std::vector<RectI> & rects)1261 void RSUifirstManager::UpdateUIFirstNodeUseDma(RSSurfaceRenderNode& node, const std::vector<RectI>& rects)
1262 {
1263 if (!GetUseDmaBuffer(node.GetName())) {
1264 return;
1265 }
1266 bool intersect = false;
1267 for (auto& rect : rects) {
1268 if (rect.Intersect(node.GetAbsDrawRect())) {
1269 intersect = true;
1270 break;
1271 }
1272 }
1273 node.SetHardwareForcedDisabledState(intersect);
1274
1275 Drawing::Matrix totalMatrix;
1276 float alpha = 1.f;
1277 auto surfaceNode = node.ReinterpretCastTo<RSSurfaceRenderNode>();
1278 RSUniRenderUtil::AccumulateMatrixAndAlpha(surfaceNode, totalMatrix, alpha);
1279 node.SetTotalMatrix(totalMatrix);
1280 }
1281
UifirstStateChange(RSSurfaceRenderNode & node,MultiThreadCacheType currentFrameCacheType)1282 void RSUifirstManager::UifirstStateChange(RSSurfaceRenderNode& node, MultiThreadCacheType currentFrameCacheType)
1283 {
1284 auto lastFrameCacheType = node.GetLastFrameUifirstFlag();
1285 if ((lastFrameCacheType != MultiThreadCacheType::NONE) && (lastFrameCacheType != currentFrameCacheType)) {
1286 // not support cache type switch, just disable multithread cache
1287 currentFrameCacheType = MultiThreadCacheType::NONE;
1288 }
1289 if (lastFrameCacheType == MultiThreadCacheType::NONE) { // likely branch: last is disable
1290 if (currentFrameCacheType != MultiThreadCacheType::NONE) { // switch: disable -> enable
1291 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.shared_from_this());
1292 RS_OPTIONAL_TRACE_NAME_FMT("UIFirst_switch disable -> enable %" PRIu64"", node.GetId());
1293 SetUifirstNodeEnableParam(node, currentFrameCacheType);
1294 if (currentFrameCacheType == MultiThreadCacheType::ARKTS_CARD) { // now only update ArkTSCardNode
1295 node.UpdateTreeUifirstRootNodeId(node.GetId());
1296 }
1297 if (currentFrameCacheType == MultiThreadCacheType::LEASH_WINDOW) {
1298 node.SetUifirstUseStarting(LeashWindowContainMainWindowAndStarting(*surfaceNode));
1299 NotifyUIStartingWindow(node.GetId(), true);
1300 }
1301 auto func = &RSUifirstManager::ProcessTreeStateChange;
1302 node.RegisterTreeStateChangeCallback(func);
1303 node.SetUifirstStartTime(GetCurSysTime());
1304 AddPendingPostNode(node.GetId(), surfaceNode, currentFrameCacheType); // clear pending reset status
1305 AddCardNodes(node.GetId(), currentFrameCacheType);
1306 } else { // keep disable
1307 RS_OPTIONAL_TRACE_NAME_FMT("UIFirst_keep disable %" PRIu64"", node.GetId());
1308 }
1309 } else { // last is enable
1310 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.shared_from_this());
1311 if (currentFrameCacheType != MultiThreadCacheType::NONE) { // keep enable
1312 RS_OPTIONAL_TRACE_NAME_FMT("UIFirst_keep enable %" PRIu64"", node.GetId());
1313 MergeOldDirty(node);
1314 AddPendingPostNode(node.GetId(), surfaceNode, currentFrameCacheType);
1315 } else { // switch: enable -> disable
1316 RS_OPTIONAL_TRACE_NAME_FMT("UIFirst_switch enable -> disable %" PRIu64"", node.GetId());
1317 node.SetUifirstStartTime(-1); // -1: default start time
1318 NotifyUIStartingWindow(node.GetId(), false);
1319 AddPendingResetNode(node.GetId(), surfaceNode); // set false onsync when task done
1320 RemoveCardNodes(node.GetId());
1321 }
1322 }
1323 node.SetLastFrameUifirstFlag(currentFrameCacheType);
1324 }
1325
1326 // appwindow will not be traversed in process when cache leashwindow
UpdateChildrenDirtyRect(RSSurfaceRenderNode & node)1327 void RSUifirstManager::UpdateChildrenDirtyRect(RSSurfaceRenderNode& node)
1328 {
1329 RectI rect(0, 0, 0, 0);
1330 if (node.IsLeashWindow()) {
1331 for (auto& child : *(node.GetChildren())) {
1332 if (!child) {
1333 continue;
1334 }
1335 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1336 if (!surfaceChild) {
1337 continue;
1338 }
1339 if (surfaceChild->IsMainWindowType()) {
1340 rect = rect.JoinRect(surfaceChild->GetOldDirtyInSurface());
1341 continue;
1342 }
1343 }
1344 }
1345 node.SetUifirstChildrenDirtyRectParam(rect);
1346 }
1347
CreateUIFirstLayer(std::shared_ptr<RSProcessor> & processor)1348 void RSUifirstManager::CreateUIFirstLayer(std::shared_ptr<RSProcessor>& processor)
1349 {
1350 if (!processor) {
1351 return;
1352 }
1353 {
1354 std::lock_guard<std::mutex> lock(useDmaBufferMutex_);
1355 if (!useDmaBuffer_) {
1356 return;
1357 }
1358 }
1359 for (auto& drawable : pendingPostDrawables_) {
1360 if (!drawable) {
1361 continue;
1362 }
1363 auto& param = drawable->GetRenderParams();
1364 if (!param) {
1365 continue;
1366 }
1367 auto params = static_cast<RSSurfaceRenderParams*>(param.get());
1368 if (params && params->GetHardwareEnabled()) {
1369 processor->CreateUIFirstLayer(*drawable, *params);
1370 }
1371 }
1372 }
1373
UpdateUIFirstLayerInfo(const ScreenInfo & screenInfo,float zOrder)1374 void RSUifirstManager::UpdateUIFirstLayerInfo(const ScreenInfo& screenInfo, float zOrder)
1375 {
1376 {
1377 std::lock_guard<std::mutex> lock(useDmaBufferMutex_);
1378 if (!useDmaBuffer_) {
1379 return;
1380 }
1381 }
1382 for (const auto& iter : pendingPostNodes_) {
1383 auto& node = iter.second;
1384 if (node && GetUseDmaBuffer(node->GetName())) {
1385 node->GetRSSurfaceHandler()->SetGlobalZOrder(node->IsHardwareForcedDisabled() ? -1.f : zOrder++);
1386 auto transform = RSUniRenderUtil::GetLayerTransform(*node, screenInfo);
1387 node->UpdateHwcNodeLayerInfo(transform);
1388 node->SetIsLastFrameHwcEnabled(!node->IsHardwareForcedDisabled());
1389 }
1390 }
1391 }
1392
ProcessTreeStateChange(RSSurfaceRenderNode & node)1393 void RSUifirstManager::ProcessTreeStateChange(RSSurfaceRenderNode& node)
1394 {
1395 RSUifirstManager::Instance().CheckCurrentFrameHasCardNodeReCreate(node);
1396 // Planning: do not clear complete image for card
1397 if (node.IsOnTheTree()) {
1398 return;
1399 }
1400 RSUifirstManager::Instance().DisableUifirstNode(node);
1401 RSUifirstManager::Instance().ForceClearSubthreadRes();
1402 RSUifirstManager::Instance().RemoveCardNodes(node.GetId());
1403 }
1404
DisableUifirstNode(RSSurfaceRenderNode & node)1405 void RSUifirstManager::DisableUifirstNode(RSSurfaceRenderNode& node)
1406 {
1407 RS_TRACE_NAME_FMT("DisableUifirstNode");
1408 UifirstStateChange(node, MultiThreadCacheType::NONE);
1409 }
1410
AddCapturedNodes(NodeId id)1411 void RSUifirstManager::AddCapturedNodes(NodeId id)
1412 {
1413 capturedNodes_.push_back(id);
1414 }
1415
SetUseDmaBuffer(bool val)1416 void RSUifirstManager::SetUseDmaBuffer(bool val)
1417 {
1418 std::lock_guard<std::mutex> lock(useDmaBufferMutex_);
1419 #if defined(RS_ENABLE_VK)
1420 useDmaBuffer_ = val && RSSystemParameters::GetUIFirstDmaBufferEnabled() &&
1421 RSSystemProperties::IsPhoneType() && RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN;
1422 #else
1423 useDmaBuffer_ = false;
1424 #endif
1425 }
1426
GetUseDmaBuffer(const std::string & name)1427 bool RSUifirstManager::GetUseDmaBuffer(const std::string& name)
1428 {
1429 std::lock_guard<std::mutex> lock(useDmaBufferMutex_);
1430 return useDmaBuffer_ && name.find("ScreenShotWindow") != std::string::npos;
1431 }
1432
ResetCurrentFrameDeletedCardNodes()1433 void RSUifirstManager::ResetCurrentFrameDeletedCardNodes()
1434 {
1435 currentFrameDeletedCardNodes_.clear();
1436 isCurrentFrameHasCardNodeReCreate_ = false;
1437 }
1438
CheckCurrentFrameHasCardNodeReCreate(const RSSurfaceRenderNode & node)1439 void RSUifirstManager::CheckCurrentFrameHasCardNodeReCreate(const RSSurfaceRenderNode& node)
1440 {
1441 if (node.GetSurfaceNodeType() != RSSurfaceNodeType::ABILITY_COMPONENT_NODE ||
1442 node.GetName().find(ARKTSCARDNODE_NAME) == std::string::npos) {
1443 return;
1444 }
1445 if (!node.IsOnTheTree()) {
1446 currentFrameDeletedCardNodes_.emplace_back(node.GetId());
1447 } else if (std::find(currentFrameDeletedCardNodes_.begin(), currentFrameDeletedCardNodes_.end(),
1448 node.GetId()) != currentFrameDeletedCardNodes_.end()) {
1449 isCurrentFrameHasCardNodeReCreate_ = true;
1450 }
1451 }
1452
CheckMatchAndWaitNotify(const RSRenderParams & params,bool checkMatch)1453 bool RSUiFirstProcessStateCheckerHelper::CheckMatchAndWaitNotify(const RSRenderParams& params, bool checkMatch)
1454 {
1455 if (checkMatch && IsCurFirstLevelMatch(params)) {
1456 return true;
1457 }
1458 return CheckAndWaitPreFirstLevelDrawableNotify(params);
1459 }
1460
CheckAndWaitPreFirstLevelDrawableNotify(const RSRenderParams & params)1461 bool RSUiFirstProcessStateCheckerHelper::CheckAndWaitPreFirstLevelDrawableNotify(const RSRenderParams& params)
1462 {
1463 auto firstLevelNodeId = params.GetFirstLevelNodeId();
1464 auto uifirstRootNodeId = params.GetUifirstRootNodeId();
1465 auto rootId = uifirstRootNodeId != INVALID_NODEID ? uifirstRootNodeId : firstLevelNodeId;
1466 if (rootId == INVALID_NODEID) {
1467 /* uifirst will not draw with no firstlevel node, and there's no need to check and wait for uifirst onDraw */
1468 RS_LOGW("uifirst node %{public}" PRIu64 " uifirstrootNodeId is INVALID_NODEID", params.GetId());
1469 return true;
1470 }
1471
1472 auto uifirstRootNodeDrawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(rootId);
1473 if (!uifirstRootNodeDrawable) {
1474 // drawable may release when node off tree
1475 // uifirst will not draw with null uifirstRootNodeDrawable
1476 RS_LOGW("uifirstnode %{public}" PRIu64 " uifirstroot %{public}" PRIu64 " nullptr", params.GetId(), rootId);
1477 return true;
1478 }
1479
1480 if (UNLIKELY(uifirstRootNodeDrawable->GetNodeType() != RSRenderNodeType::SURFACE_NODE)) {
1481 RS_LOGE("uifirst invalid uifirstrootNodeId %{public}" PRIu64, rootId);
1482 return false;
1483 }
1484 auto uifirstRootSurfaceNodeDrawable =
1485 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(uifirstRootNodeDrawable);
1486
1487 RS_TRACE_NAME_FMT("CheckAndWaitPreFirstLevelDrawableNotify %" PRIu64 " wait for %" PRIu64 "",
1488 params.GetId(), uifirstRootSurfaceNodeDrawable->GetId());
1489
1490 static constexpr auto TIME_OUT = std::chrono::milliseconds(32); // 32ms
1491 auto pred = [uifirstRootSurfaceNodeDrawable] {
1492 auto curState = uifirstRootSurfaceNodeDrawable->GetCacheSurfaceProcessedStatus();
1493 return curState == CacheProcessStatus::DONE || curState == CacheProcessStatus::UNKNOWN ||
1494 curState == CacheProcessStatus::SKIPPED;
1495 };
1496 std::unique_lock<std::mutex> lock(notifyMutex_);
1497 notifyCv_.wait_for(lock, TIME_OUT, pred);
1498 return pred();
1499 }
1500
IsCurFirstLevelMatch(const RSRenderParams & params)1501 bool RSUiFirstProcessStateCheckerHelper::IsCurFirstLevelMatch(const RSRenderParams& params)
1502 {
1503 auto uifirstRootNodeId = params.GetUifirstRootNodeId();
1504 auto firstLevelNodeId = params.GetFirstLevelNodeId();
1505
1506 RS_OPTIONAL_TRACE_NAME_FMT("RSUiFirstProcessStateCheckerHelper IsCurFirstLevelMatch In node[%"
1507 PRIu64 " %" PRIu64"] cur[%" PRIu64 " %" PRIu64 "] in nodeId[%" PRIu64 "]",
1508 uifirstRootNodeId, firstLevelNodeId, curUifirstRootNodeId_, curFirstLevelNodeId_, params.GetId());
1509
1510 if (curUifirstRootNodeId_ == INVALID_NODEID && curFirstLevelNodeId_ == INVALID_NODEID) {
1511 // should draw because uifirst may not inited
1512 return true;
1513 }
1514 auto uiFirstCheckRet = uifirstRootNodeId == curUifirstRootNodeId_ && curUifirstRootNodeId_ != INVALID_NODEID;
1515 auto firstLevelCheckRet = firstLevelNodeId == curFirstLevelNodeId_ && curFirstLevelNodeId_ != INVALID_NODEID;
1516 if (uiFirstCheckRet || firstLevelCheckRet) {
1517 return true;
1518 }
1519 return false;
1520 }
1521 } // namespace Rosen
1522 } // namespace OHOS
1523