• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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