• 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 #include "rs_trace.h"
17 
18 #include "common/rs_optional_trace.h"
19 #include "display_engine/rs_luminance_control.h"
20 #include "drawable/rs_surface_render_node_drawable.h"
21 #include "feature/uifirst/rs_sub_thread_manager.h"
22 #include "feature/uifirst/rs_uifirst_manager.h"
23 #include "feature_cfg/graphic_feature_param_manager.h"
24 #include "memory/rs_memory_manager.h"
25 #include "params/rs_display_render_params.h"
26 #include "pipeline/render_thread/rs_uni_render_util.h"
27 #include "pipeline/rs_canvas_render_node.h"
28 #include "pipeline/main_thread/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 
GetSurfaceDrawableByID(NodeId id)55 std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> RSUifirstManager::GetSurfaceDrawableByID(NodeId id)
56 {
57     if (const auto cacheIt = subthreadProcessingNode_.find(id); cacheIt != subthreadProcessingNode_.end()) {
58         const auto ptr = cacheIt->second;
59         if (ptr && ptr->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
60             return std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(ptr);
61         }
62     }
63     // unlikely
64     auto ptr = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
65     if (ptr && ptr->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
66         return std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(ptr);
67     }
68     return nullptr;
69 }
70 
SetUifirstNodeEnableParam(RSSurfaceRenderNode & node,MultiThreadCacheType type)71 bool RSUifirstManager::SetUifirstNodeEnableParam(RSSurfaceRenderNode& node, MultiThreadCacheType type)
72 {
73     auto ret = node.SetUifirstNodeEnableParam(type); // update drawable param
74     auto isType = type == MultiThreadCacheType::LEASH_WINDOW || type == MultiThreadCacheType::NONFOCUS_WINDOW;
75     if (node.IsLeashWindow() && type != MultiThreadCacheType::ARKTS_CARD) {
76         for (auto& child : *(node.GetChildren())) {
77             if (!child) {
78                 continue;
79             }
80             auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
81             if (!surfaceChild) {
82                 continue;
83             }
84             if (surfaceChild->IsMainWindowType()) {
85                 surfaceChild->SetIsParentUifirstNodeEnableParam(isType);
86                 continue;
87             }
88         }
89     }
90     return ret;
91 }
92 
93 // unref in sub when cache done
AddProcessDoneNode(NodeId id)94 void RSUifirstManager::AddProcessDoneNode(NodeId id)
95 {
96     // mutex
97     if (id == INVALID_NODEID) {
98         return;
99     }
100     RS_OPTIONAL_TRACE_NAME_FMT("sub done %" PRIu64"", id);
101     std::lock_guard<std::mutex> lock(childernDrawableMutex_);
102     subthreadProcessDoneNode_.push_back(id);
103 }
104 
AddProcessSkippedNode(NodeId id)105 void RSUifirstManager::AddProcessSkippedNode(NodeId id)
106 {
107     if (id == INVALID_NODEID) {
108         return;
109     }
110     RS_OPTIONAL_TRACE_NAME_FMT("sub skipped %" PRIu64, id);
111     std::lock_guard<std::mutex> lock(skippedNodeMutex_);
112     subthreadProcessSkippedNode_.insert(id);
113 }
114 
NeedNextDrawForSkippedNode()115 bool RSUifirstManager::NeedNextDrawForSkippedNode()
116 {
117     std::lock_guard<std::mutex> lock(skippedNodeMutex_);
118     return !subthreadProcessSkippedNode_.empty();
119 }
120 
ResetUifirstNode(std::shared_ptr<RSSurfaceRenderNode> & nodePtr)121 void RSUifirstManager::ResetUifirstNode(std::shared_ptr<RSSurfaceRenderNode>& nodePtr)
122 {
123     if (!nodePtr) {
124         return;
125     }
126     RS_LOGD("uifirst ResetUifirstNode name:%{public}s,id:%{public}" PRIu64 ",isOnTheTree:%{public}d,"
127         "toBeCaptured:%{public}d", nodePtr->GetName().c_str(), nodePtr->GetId(), nodePtr->IsOnTheTree(),
128         nodePtr->IsNodeToBeCaptured());
129     nodePtr->SetUifirstUseStarting(false);
130     if (SetUifirstNodeEnableParam(*nodePtr, MultiThreadCacheType::NONE)) {
131         // enable ->disable
132         SetNodeNeedForceUpdateFlag(true);
133         pendingForceUpdateNode_.push_back(nodePtr->GetId());
134     }
135     RSMainThread::Instance()->GetContext().AddPendingSyncNode(nodePtr);
136     auto drawable = GetSurfaceDrawableByID(nodePtr->GetId());
137     if (!drawable) {
138         return;
139     }
140     if (!nodePtr->IsOnTheTree() && nodePtr->IsNodeToBeCaptured()) {
141         drawable->ResetUifirst(true);
142         auto taskName = CLEAR_CACHE_TASK_PREFIX + std::to_string(nodePtr->GetId());
143         auto releaseTask = [drawable] {
144             auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
145             if (surfaceParams && surfaceParams->GetUifirstNodeEnableParam() == MultiThreadCacheType::NONE) {
146                 RS_TRACE_NAME_FMT("ResetUifirstNode clearCache id:%llu", surfaceParams->GetId());
147                 drawable->ResetUifirst(false);
148             }
149         };
150         RSUniRenderThread::Instance().PostTask(releaseTask, taskName, CLEAR_CACHE_DELAY);
151     } else {
152         nodePtr->SetIsNodeToBeCaptured(false);
153         drawable->ResetUifirst(false);
154     }
155 }
156 
MergeOldDirty(NodeId id)157 void RSUifirstManager::MergeOldDirty(NodeId id)
158 {
159     if (!mainThread_) {
160         return;
161     }
162     auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
163         mainThread_->GetContext().GetNodeMap().GetRenderNode(id));
164     if (!node) {
165         return;
166     }
167     if (node->IsAppWindow() &&
168         !RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node->GetParent().lock())) {
169         auto& curDirtyManager = node->GetDirtyManagerForUifirst();
170         if (curDirtyManager) {
171             curDirtyManager->SetUifirstFrameDirtyRect(node->GetOldDirty());
172         }
173         return;
174     }
175     bool hasAppWindow = false;
176     for (auto& child : * node-> GetSortedChildren()) {
177         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
178         auto& curDirtyManager = node->GetDirtyManagerForUifirst();
179         if (surfaceNode && surfaceNode->IsAppWindow()) {
180             hasAppWindow = true;
181             if (curDirtyManager) {
182                 curDirtyManager->SetUifirstFrameDirtyRect(surfaceNode->GetOldDirty());
183             }
184             break;
185         }
186     }
187     if (!hasAppWindow) {
188         auto& curDirtyManager = node->GetDirtyManagerForUifirst();
189         if (curDirtyManager) {
190             curDirtyManager->SetUifirstFrameDirtyRect(node->GetOldDirty());
191         }
192     }
193 }
194 
MergeOldDirtyToDirtyManager(std::shared_ptr<RSSurfaceRenderNode> & node)195 void RSUifirstManager::MergeOldDirtyToDirtyManager(std::shared_ptr<RSSurfaceRenderNode>& node)
196 {
197     auto& curDirtyManager = node->GetDirtyManagerForUifirst();
198     if (!curDirtyManager) {
199         RS_LOGE("MergeOldDirtyToDirtyManager curDirtyManager is nullptr");
200         return;
201     }
202     auto curDirtyRegion = curDirtyManager->GetCurrentFrameDirtyRegion();
203     auto uifirstDirtyRegion = curDirtyManager->GetUifirstFrameDirtyRegion();
204     curDirtyManager->MergeDirtyRect(uifirstDirtyRegion);
205     curDirtyManager->SetUifirstFrameDirtyRect(curDirtyRegion);
206     RS_OPTIONAL_TRACE_NAME_FMT("MergeOldDirtyToDirtyManager %" PRIu64","
207         " curDirtyRegion[%d %d %d %d], uifirstDirtyRegion[%d %d %d %d]",
208         node->GetId(), curDirtyRegion.left_, curDirtyRegion.top_, curDirtyRegion.width_, curDirtyRegion.height_,
209         uifirstDirtyRegion.left_, uifirstDirtyRegion.top_, uifirstDirtyRegion.width_, uifirstDirtyRegion.height_);
210     RS_LOGD("MergeOldDirtyToDirtyManager %{public}" PRIu64","
211         " curDirtyRegion[%{public}d %{public}d %{public}d %{public}d],"
212         " uifirstDirtyRegion[%{public}d %{public}d %{public}d %{public}d]",
213         node->GetId(), curDirtyRegion.left_, curDirtyRegion.top_, curDirtyRegion.width_, curDirtyRegion.height_,
214         uifirstDirtyRegion.left_, uifirstDirtyRegion.top_, uifirstDirtyRegion.width_, uifirstDirtyRegion.height_);
215     if (!uifirstDirtyRegion.IsEmpty()) {
216         node->AddToPendingSyncList();
217     }
218 }
219 
RenderGroupUpdate(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable)220 void RSUifirstManager::RenderGroupUpdate(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable)
221 {
222     if (mainThread_ == nullptr) {
223         return;
224     }
225     auto nodeSp = mainThread_->GetContext().GetNodeMap().GetRenderNode(drawable->GetId());
226     if (nodeSp == nullptr) {
227         return;
228     }
229     auto surfaceNode = std::static_pointer_cast<const RSSurfaceRenderNode>(nodeSp);
230     if (surfaceNode == nullptr) {
231         return;
232     }
233     // mark all parent rendergroup need update; planning: mark autoCache need update
234     auto node = surfaceNode->GetParent().lock();
235 
236     while (node != nullptr) {
237         if (node->GetType() == RSRenderNodeType::DISPLAY_NODE) {
238             break;
239         }
240         if (node->IsSuggestedDrawInGroup()) {
241             RS_OPTIONAL_TRACE_NAME_FMT("cache_changed by uifirst card %" PRIu64"", node->GetId());
242             node->SetDrawingCacheChanged(true);
243             node->AddToPendingSyncList();
244         }
245         node = node->GetParent().lock();
246     }
247 }
248 
ProcessForceUpdateNode()249 void RSUifirstManager::ProcessForceUpdateNode()
250 {
251     if (!mainThread_) {
252         return;
253     }
254     std::vector<std::shared_ptr<RSRenderNode>> toDirtyNodes;
255     for (auto id : pendingForceUpdateNode_) {
256         auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(id);
257         if (!node || node->GetLastFrameUifirstFlag() != MultiThreadCacheType::ARKTS_CARD) {
258             continue;
259         }
260         toDirtyNodes.push_back(node);
261         if (!node->IsDirty() && !node->IsSubTreeDirty()) {
262             markForceUpdateByUifirst_.push_back(node);
263             node->SetForceUpdateByUifirst(true);
264         }
265     }
266     for (auto& node : toDirtyNodes) {
267         node->SetDirty(true);
268     }
269     pendingForceUpdateNode_.clear();
270 }
271 
NotifyUIStartingWindow(NodeId id,bool wait)272 void RSUifirstManager::NotifyUIStartingWindow(NodeId id, bool wait)
273 {
274     if (mainThread_ == nullptr) {
275         return;
276     }
277     auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
278         mainThread_->GetContext().GetNodeMap().GetRenderNode(id));
279     if (node == nullptr || !node->IsLeashWindow()) {
280         return;
281     }
282     for (auto& child : *node->GetChildren()) {
283         if (!child) {
284             continue;
285         }
286         auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
287         if (surfaceChild && surfaceChild->IsMainWindowType()) {
288             surfaceChild->SetWaitUifirstFirstFrame(wait);
289         }
290     }
291 }
292 
ProcessDoneNodeInner()293 void RSUifirstManager::ProcessDoneNodeInner()
294 {
295     std::vector<NodeId> tmp;
296     {
297         std::lock_guard<std::mutex> lock(childernDrawableMutex_);
298         if (subthreadProcessDoneNode_.size() == 0) {
299             return;
300         }
301         std::swap(tmp, subthreadProcessDoneNode_);
302     }
303     RS_TRACE_NAME_FMT("ProcessDoneNode num%d", tmp.size());
304     for (auto& id : tmp) {
305         RS_OPTIONAL_TRACE_NAME_FMT("Done %" PRIu64"", id);
306         auto drawable = GetSurfaceDrawableByID(id);
307         if (drawable && drawable->GetCacheSurfaceNeedUpdated() &&
308             drawable->CheckCacheSurface()) {
309             drawable->UpdateCompletedCacheSurface();
310             RenderGroupUpdate(drawable);
311             SetNodeNeedForceUpdateFlag(true);
312             pendingForceUpdateNode_.push_back(id);
313         }
314         subthreadProcessingNode_.erase(id);
315     }
316 }
317 
ProcessSkippedNode()318 void RSUifirstManager::ProcessSkippedNode()
319 {
320     std::unordered_set<NodeId> tmp;
321     {
322         std::lock_guard<std::mutex> lock(skippedNodeMutex_);
323         if (subthreadProcessSkippedNode_.empty()) {
324             return;
325         }
326         std::swap(tmp, subthreadProcessSkippedNode_);
327     }
328     RS_TRACE_NAME_FMT("ProcessSkippedNode num %zu", tmp.size());
329     for (auto& id : tmp) {
330         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
331             mainThread_->GetContext().GetNodeMap().GetRenderNode(id));
332         if (UNLIKELY(!surfaceNode)) {
333             continue;
334         }
335         // If node not on the tree, do not draw it.
336         if (UNLIKELY(!surfaceNode->IsOnTheTree())) {
337             RS_TRACE_NAME_FMT("ProcessSkippedNode %s %" PRIu64 " not OnTheTree", surfaceNode->GetName().c_str(), id);
338             continue;
339         }
340         // If node not enable uifirst, do not draw it in subThread.
341         if (UNLIKELY(surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE)) {
342             RS_TRACE_NAME_FMT("ProcessSkippedNode %s %" PRIu64 " disabled", surfaceNode->GetName().c_str(), id);
343             continue;
344         }
345         if (surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD) {
346             if (pendingPostCardNodes_.find(id) == pendingPostCardNodes_.end()) {
347                 pendingPostCardNodes_.emplace(id, surfaceNode);
348                 surfaceNode->SetForceDrawWithSkipped(true);
349                 RS_TRACE_NAME_FMT("ProcessSkippedCardNode %" PRIu64 " added", id);
350                 RS_LOGI("ProcessSkippedCardNode %{public}" PRIu64 " added", id);
351             }
352         } else {
353             if (pendingPostNodes_.find(id) == pendingPostNodes_.end()) {
354                 pendingPostNodes_.emplace(id, surfaceNode);
355                 surfaceNode->SetForceDrawWithSkipped(true);
356                 RS_TRACE_NAME_FMT("ProcessSkippedNode %s %" PRIu64 " Type %d added", surfaceNode->GetName().c_str(), id,
357                     static_cast<int>(surfaceNode->GetLastFrameUifirstFlag()));
358             }
359         }
360     }
361 }
362 
ProcessDoneNode()363 void RSUifirstManager::ProcessDoneNode()
364 {
365 #ifdef RS_ENABLE_PREFETCH
366     __builtin_prefetch(&pendingResetNodes_, 0, 1);
367 #endif
368     SetNodeNeedForceUpdateFlag(false);
369     ProcessDoneNodeInner();
370 
371     // reset node when node is not doing
372     for (auto it = capturedNodes_.begin(); it != capturedNodes_.end();) {
373         if (mainThread_ && subthreadProcessingNode_.find(*it) == subthreadProcessingNode_.end()) {
374             // reset uifirst
375             auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
376                 mainThread_->GetContext().GetNodeMap().GetRenderNode(*it));
377             if (node == nullptr) {
378                 it = capturedNodes_.erase(it);
379                 continue;
380             }
381             node->SetIsNodeToBeCaptured(false);
382             if (node->GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE) {
383                 ResetUifirstNode(node);
384             }
385             it = capturedNodes_.erase(it);
386         } else {
387             it++;
388         }
389     }
390     for (auto it = pendingResetNodes_.begin(); it != pendingResetNodes_.end();) {
391         if (subthreadProcessingNode_.find(it->first) == subthreadProcessingNode_.end()) {
392             ResetUifirstNode(it->second);
393             it = pendingResetNodes_.erase(it);
394         } else {
395             it++;
396         }
397     }
398     for (auto& surfaceNode : pindingResetWindowCachedNodes_) {
399         ResetUifirstNode(surfaceNode);
400     }
401     pindingResetWindowCachedNodes_.clear();
402 
403     for (auto it = subthreadProcessingNode_.begin(); it != subthreadProcessingNode_.end();) {
404         auto id = it->first;
405         auto drawable = GetSurfaceDrawableByID(id);
406         if (!drawable) {
407             ++it;
408             continue;
409         }
410         auto cacheStatus = drawable->GetCacheSurfaceProcessedStatus();
411         if (cacheStatus == CacheProcessStatus::SKIPPED) {
412             it = subthreadProcessingNode_.erase(it);
413             continue;
414         }
415         RS_LOGI("erase processingNode %{public}" PRIu64, id);
416         RS_TRACE_NAME_FMT("erase processingNode %s %{public}" PRIu64, drawable->GetName().c_str(), id);
417         pendingPostNodes_.erase(it->first); // dele doing node in pendingpostlist
418         pendingPostCardNodes_.erase(it->first);
419         // skipped by doing, need update cache because the doing cache is too old
420         RSUifirstManager::Instance().AddProcessSkippedNode(it->first);
421         ++it;
422     }
423 }
424 
SyncHDRDisplayParam(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable,const GraphicColorGamut & colorGamut)425 void RSUifirstManager::SyncHDRDisplayParam(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable,
426     const GraphicColorGamut& colorGamut)
427 {
428 #ifdef RS_ENABLE_GPU
429     auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
430     if (!surfaceParams || !surfaceParams->GetAncestorDisplayNode().lock()) {
431         return;
432     }
433     auto ancestor = surfaceParams->GetAncestorDisplayNode().lock()->ReinterpretCastTo<RSDisplayRenderNode>();
434     if (!ancestor) {
435         return;
436     }
437     auto displayParams = static_cast<RSDisplayRenderParams*>(ancestor->GetRenderParams().get());
438     if (!displayParams) {
439         return;
440     }
441     bool isHdrOn = displayParams->GetHDRPresent();
442     ScreenId id = displayParams->GetScreenId();
443     drawable->SetHDRPresent(isHdrOn);
444     bool isScRGBEnable = RSSystemParameters::IsNeedScRGBForP3(displayParams->GetNewColorSpace()) &&
445         RSMainThread::Instance()->IsUIFirstOn();
446     bool changeColorSpace = drawable->GetTargetColorGamut() != colorGamut;
447     if (isHdrOn || isScRGBEnable || changeColorSpace) {
448         if (isScRGBEnable && changeColorSpace) {
449             RS_LOGI("UIFirstHDR SyncDisplayParam: ColorSpace change, ClearCacheSurface,"
450                 "nodeID: [%{public}" PRIu64"]", id);
451             RS_TRACE_NAME_FMT("UIFirstHDR SyncDisplayParam: ColorSpace change, ClearCacheSurface,"
452                 "nodeID: [%{public}" PRIu64"]", id);
453             drawable->ClearCacheSurfaceInThread();
454         }
455         drawable->SetScreenId(id);
456         drawable->SetTargetColorGamut(colorGamut);
457     }
458     RS_LOGD("UIFirstHDR SyncDisplayParam:%{public}d, ratio:%{public}f", drawable->GetHDRPresent(),
459         surfaceParams->GetBrightnessRatio());
460 #endif
461 }
462 
CurSurfaceHasVisibleDirtyRegion(const std::shared_ptr<RSSurfaceRenderNode> & node)463 bool RSUifirstManager::CurSurfaceHasVisibleDirtyRegion(const std::shared_ptr<RSSurfaceRenderNode>& node)
464 {
465     auto visibleRegion = node->GetVisibleRegion();
466     if (visibleRegion.IsEmpty()) {
467         RS_OPTIONAL_TRACE_NAME_FMT("curSurface name:%s id:%" PRIu64" visibleRegion is IsEmpty",
468         node->GetName().c_str(), node->GetId());
469         return false;
470     }
471     auto drawable = node->GetRenderDrawable();
472     if (!drawable) {
473         RS_TRACE_NAME_FMT("node id:%" PRIu64" drawable is nullptr", node->GetId());
474         return true;
475     }
476     auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
477     if (!surfaceDrawable) {
478         RS_TRACE_NAME_FMT("node id:%" PRIu64" surfaceDrawable is nullptr", node->GetId());
479         return true;
480     }
481     auto surfaceDirtyManager = surfaceDrawable->GetSyncDirtyManager();
482     if (!surfaceDirtyManager) {
483         RS_TRACE_NAME_FMT("node id:%" PRIu64" surfaceDirtyManager is nullptr", node->GetId());
484         return true;
485     }
486     auto surfaceDirtyRect = surfaceDirtyManager->GetUifirstFrameDirtyRegion();
487     RS_TRACE_NAME_FMT("uifirstFrameDirtyRegion %" PRIu64", surfaceDirtyRegion[%d %d %d %d]",
488         surfaceDrawable->GetId(),
489         surfaceDirtyRect.left_, surfaceDirtyRect.top_, surfaceDirtyRect.width_, surfaceDirtyRect.height_);
490     Occlusion::Region surfaceDirtyRegion { { surfaceDirtyRect.left_, surfaceDirtyRect.top_,
491         surfaceDirtyRect.GetRight(), surfaceDirtyRect.GetBottom() } };
492     Occlusion::Region surfaceVisibleDirtyRegion = surfaceDirtyRegion.And(visibleRegion);
493     if (surfaceVisibleDirtyRegion.IsEmpty()) {
494         RS_OPTIONAL_TRACE_NAME_FMT("curSurface name:%s id:%" PRIu64" visibleDirtyRegion is IsEmpty",
495             node->GetName().c_str(), node->GetId());
496         return false;
497     }
498     return true;
499 }
500 
CheckVisibleDirtyRegionIsEmpty(const std::shared_ptr<RSSurfaceRenderNode> & node)501 bool RSUifirstManager::CheckVisibleDirtyRegionIsEmpty(const std::shared_ptr<RSSurfaceRenderNode>& node)
502 {
503     if (GetUiFirstMode() != UiFirstModeType::MULTI_WINDOW_MODE) {
504         return false;
505     }
506     if (ROSEN_EQ(node->GetGlobalAlpha(), 0.0f) &&
507         RSMainThread::Instance()->GetSystemAnimatedScenes() == SystemAnimatedScenes::LOCKSCREEN_TO_LAUNCHER &&
508         node->IsLeashWindow()) {
509         RS_TRACE_NAME_FMT("Doing LOCKSCREEN_TO_LAUNCHER, fullTransparent node[%s] skips", node->GetName().c_str());
510         return true;
511     }
512     if (node->GetUifirstContentDirty()) {
513         return false;
514     }
515     bool hasSurfaceVisibleDirtyRegion = CurSurfaceHasVisibleDirtyRegion(node);
516     std::vector<std::pair<NodeId, std::weak_ptr<RSSurfaceRenderNode>>> allSubSurfaceNodes;
517     node->GetAllSubSurfaceNodes(allSubSurfaceNodes);
518     for (auto& [id, subSurfaceNode] : allSubSurfaceNodes) {
519         if (hasSurfaceVisibleDirtyRegion) {
520             break;
521         }
522         auto subSurfaceNodePtr = subSurfaceNode.lock();
523         if (!subSurfaceNodePtr) {
524             continue;
525         }
526         hasSurfaceVisibleDirtyRegion =
527             hasSurfaceVisibleDirtyRegion || CurSurfaceHasVisibleDirtyRegion(subSurfaceNodePtr);
528     }
529     RS_TRACE_NAME_FMT("allSurface name:%s id:%" PRIu64" hasSurfaceVisibleDirtyRegion:%d",
530         node->GetName().c_str(), node->GetId(), hasSurfaceVisibleDirtyRegion);
531     if (!hasSurfaceVisibleDirtyRegion) {
532         return true;
533     }
534     return false;
535 }
536 
DoPurgePendingPostNodes(std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>> & pendingNode)537 void RSUifirstManager::DoPurgePendingPostNodes(std::unordered_map<NodeId,
538     std::shared_ptr<RSSurfaceRenderNode>>& pendingNode)
539 {
540     for (auto it = pendingNode.begin(); it != pendingNode.end();) {
541         auto id = it->first;
542         auto drawable = GetSurfaceDrawableByID(id);
543         auto node = it->second;
544         if (!drawable || !node) {
545             ++it;
546             continue;
547         }
548         auto forceDraw = node->GetForceDrawWithSkipped();
549         node->SetForceDrawWithSkipped(false);
550         SyncHDRDisplayParam(drawable, node->GetFirstLevelNodeColorGamut());
551         auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
552         if (!surfaceParams) {
553             ++it;
554             continue;
555         }
556 
557         if (!node->IsOnTheTree() && subthreadProcessingNode_.find(id) == subthreadProcessingNode_.end()) {
558             it = pendingNode.erase(it);
559             continue;
560         }
561 
562         if (forceDraw) {
563             RS_TRACE_NAME_FMT("Purge GetForceDrawWithSkipped name: %s %" PRIu64,
564                 surfaceParams->GetName().c_str(), drawable->GetId());
565             ++it;
566             continue;
567         }
568 
569         bool staticContent = drawable->IsCurFrameStatic();
570         RS_TRACE_NAME_FMT("Purge node name: %s, PurgeEnable:%d, HasCachedTexture:%d, staticContent: %d %" PRIu64,
571             surfaceParams->GetName().c_str(), purgeEnable_,
572             drawable->HasCachedTexture(), staticContent, drawable->GetId());
573         if (purgeEnable_ && drawable->HasCachedTexture() &&
574             (staticContent || CheckVisibleDirtyRegionIsEmpty(node)) &&
575             (subthreadProcessingNode_.find(id) == subthreadProcessingNode_.end()) &&
576             !drawable->IsSubThreadSkip()) {
577             RS_OPTIONAL_TRACE_NAME_FMT("Purge node name %s", surfaceParams->GetName().c_str());
578             it = pendingNode.erase(it);
579         } else {
580             ++it;
581         }
582     }
583 }
584 
PurgePendingPostNodes()585 void RSUifirstManager::PurgePendingPostNodes()
586 {
587     RS_OPTIONAL_TRACE_NAME_FMT("PurgePendingPostNodes");
588     DoPurgePendingPostNodes(pendingPostNodes_);
589     DoPurgePendingPostNodes(pendingPostCardNodes_);
590     for (auto& node : markForceUpdateByUifirst_) {
591         node->SetForceUpdateByUifirst(false);
592     }
593     markForceUpdateByUifirst_.clear();
594     for (auto id : pendingForceUpdateNode_) {
595         MergeOldDirty(id);
596     }
597 }
598 
PostSubTask(NodeId id)599 void RSUifirstManager::PostSubTask(NodeId id)
600 {
601     RS_TRACE_NAME_FMT("post UpdateCacheSurface %" PRIu64"", id);
602 
603     if (subthreadProcessingNode_.find(id) != subthreadProcessingNode_.end()) { // drawable is doing, do not send
604         RS_TRACE_NAME_FMT("node %" PRIu64" is doing", id);
605         RS_LOGE("RSUifirstManager ERROR: post task twice");
606         return;
607     }
608 
609     // 1.find in cache list(done to dele) 2.find in global list
610     auto drawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
611     if (drawable) {
612         // ref drawable
613         subthreadProcessingNode_.emplace(id, drawable);
614         // post task
615         RS_OPTIONAL_TRACE_NAME_FMT("Post_SubTask_s %" PRIu64"", id);
616         RSSubThreadManager::Instance()->ScheduleRenderNodeDrawable(
617             std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable));
618     }
619 }
620 
TryReleaseTextureForIdleThread()621 void RSUifirstManager::TryReleaseTextureForIdleThread()
622 {
623     if (noUifirstNodeFrameCount_.load() <= CLEAR_RES_THRESHOLD) {
624         return;
625     }
626     RSSubThreadManager::Instance()->TryReleaseTextureForIdleThread();
627 }
628 
PostReleaseCacheSurfaceSubTasks()629 void RSUifirstManager::PostReleaseCacheSurfaceSubTasks()
630 {
631     for (auto& cardNode : collectedCardNodes_) {
632         PostReleaseCacheSurfaceSubTask(cardNode);
633     }
634 }
635 
PostReleaseCacheSurfaceSubTask(NodeId id)636 void RSUifirstManager::PostReleaseCacheSurfaceSubTask(NodeId id)
637 {
638     RS_OPTIONAL_TRACE_NAME_FMT("post ReleaseCacheSurface %d", id);
639 
640     if (subthreadProcessingNode_.find(id) != subthreadProcessingNode_.end()) { // drawable is doing, do not send
641         RS_TRACE_NAME_FMT("node %" PRIu64" is doing", id);
642         RS_LOGE("RSUifirstManager ERROR: try to clean running node");
643         return;
644     }
645 
646     // 1.find in cache list(done to dele) 2.find in global list
647     auto drawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
648     if (drawable) {
649         // post task
650         RS_OPTIONAL_TRACE_NAME_FMT("Post_SubTask_s %" PRIu64"", id);
651         RSSubThreadManager::Instance()->ScheduleReleaseCacheSurfaceOnly(
652             std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable));
653     }
654 }
655 
UpdateSkipSyncNode()656 void RSUifirstManager::UpdateSkipSyncNode()
657 {
658     processingNodeSkipSync_.clear();
659     processingNodePartialSync_.clear();
660     processingCardNodeSkipSync_.clear();
661     RS_OPTIONAL_TRACE_NAME_FMT("UpdateSkipSyncNode doning%d", subthreadProcessingNode_.size());
662     if (subthreadProcessingNode_.size() == 0) {
663         return;
664     }
665     if (!mainThread_) {
666         return;
667     }
668     for (auto it = subthreadProcessingNode_.begin(); it != subthreadProcessingNode_.end(); it++) {
669         RS_OPTIONAL_TRACE_NAME_FMT("doning%" PRIu64"", it->first);
670         auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(it->first);
671         if (!node) {
672             continue;
673         }
674         auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>();
675         if (!surfaceNode) {
676             continue;
677         }
678         // ArkTSCard
679         if (NodeIsInCardWhiteList(*node)) {
680             if (surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD) {
681                 processingCardNodeSkipSync_.insert(it->first);
682                 continue;
683             }
684         }
685 
686         // leash window
687         processingNodePartialSync_.insert(it->first); // partial sync
688         std::vector<std::pair<NodeId, std::weak_ptr<RSSurfaceRenderNode>>> allSubSurfaceNodes;
689         surfaceNode->GetAllSubSurfaceNodes(allSubSurfaceNodes);
690         for (auto& [id, subSurfaceNode] : allSubSurfaceNodes) {
691             processingNodeSkipSync_.insert(id); // skip sync
692         }
693     }
694 }
695 
ProcessSubDoneNode()696 void RSUifirstManager::ProcessSubDoneNode()
697 {
698     RS_OPTIONAL_TRACE_NAME_FMT("ProcessSubDoneNode");
699     ProcessSkippedNode(); // try rescheduale skipped node
700     ProcessDoneNode(); // release finish drawable
701     UpdateSkipSyncNode();
702     RestoreSkipSyncNode();
703     ResetCurrentFrameDeletedCardNodes();
704 }
705 
SetUifirstSkipPartialSync(const std::shared_ptr<RSRenderNode> & node,bool needSync)706 static inline void SetUifirstSkipPartialSync(const std::shared_ptr<RSRenderNode> &node, bool needSync)
707 {
708     // node not null in caller
709     if (!needSync) {
710         return;
711     }
712     node->SetUifirstSkipPartialSync(true);
713 }
714 
GetUifirstCachedState(NodeId id)715 CacheProcessStatus& RSUifirstManager::GetUifirstCachedState(NodeId id)
716 {
717     auto ret = uifirstCacheState_.insert({ id, CacheProcessStatus::UNKNOWN });
718     auto& curRootIdState = ret.first->second;
719     if (curRootIdState == CacheProcessStatus::UNKNOWN) {
720         /* first time to get the state of uifirstRoot, and cache the state for the remaining other times */
721         auto uifirstRootNodeDrawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
722         if (uifirstRootNodeDrawable && uifirstRootNodeDrawable->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
723             auto drawableNode =
724                 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(uifirstRootNodeDrawable);
725             curRootIdState = drawableNode->GetCacheSurfaceProcessedStatus();
726         }
727     }
728     return curRootIdState;
729 }
730 
CollectSkipSyncNodeWithDrawableState(const std::shared_ptr<RSRenderNode> & node)731 RSUifirstManager::SkipSyncState RSUifirstManager::CollectSkipSyncNodeWithDrawableState(
732     const std::shared_ptr<RSRenderNode>& node)
733 {
734     auto isPreDoing = IsPreFirstLevelNodeDoingAndTryClear(node);
735     auto drawable = node->GetRenderDrawable();
736     if (UNLIKELY(!drawable || !drawable->GetRenderParams())) {
737         RS_LOGE("RSUifirstManager::CollectSkipSyncNode drawable/params nullptr");
738         // must not be in the DOING state with the invalid drawable.
739         return SkipSyncState::STATE_NOT_SKIP;
740     }
741     auto& params = drawable->GetRenderParams();
742     if (params->GetStartingWindowFlag()) {
743         RS_LOGD("starting node %{public}" PRIu64 " not skipsync", params->GetId());
744         RS_TRACE_NAME_FMT("starting node %" PRIu64 " not skipsync", params->GetId());
745         return SkipSyncState::STATE_NOT_SKIP;
746     }
747     // if node's UifirstRootNodeId is valid (e.g. ArkTsCard), use it first
748     auto uifirstRootId = params->GetUifirstRootNodeId() != INVALID_NODEID ?
749         params->GetUifirstRootNodeId() : params->GetFirstLevelNodeId();
750     auto& curRootIdState = GetUifirstCachedState(uifirstRootId);
751     RS_OPTIONAL_TRACE_NAME_FMT("node[%" PRIu64 " %" PRIu64 "] drawable[%"
752         PRIu64 " %" PRIu64 "] and curNodeId [%" PRIu64"] cacheState[%d]",
753         node->GetStagingRenderParams()->GetUifirstRootNodeId(), node->GetStagingRenderParams()->GetFirstLevelNodeId(),
754         params->GetUifirstRootNodeId(), params->GetFirstLevelNodeId(), node->GetId(), curRootIdState);
755 
756     if (curRootIdState == CacheProcessStatus::DOING || curRootIdState == CacheProcessStatus::WAITING ||
757         /* unknow state to check prefirstLevelNode */
758         (uifirstRootId == INVALID_NODEID && isPreDoing)) {
759         pendingSyncForSkipBefore_[uifirstRootId].push_back(node);
760         auto isUifirstRootNode = (uifirstRootId == node->GetId());
761         RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
762             isUifirstRootNode ? "set partial_sync" : "CollectSkipSyncNode", node->GetId(), uifirstRootId);
763         SetUifirstSkipPartialSync(node, isUifirstRootNode);
764         return isUifirstRootNode ? SkipSyncState::STATE_NOT_SKIP : SkipSyncState::STATE_NEED_SKIP;
765     }
766     return SkipSyncState::STATE_NEED_CHECK;
767 }
768 
CollectSkipSyncNode(const std::shared_ptr<RSRenderNode> & node)769 bool RSUifirstManager::CollectSkipSyncNode(const std::shared_ptr<RSRenderNode> &node)
770 {
771     if (!node) {
772         return false;
773     }
774     if (pendingPostNodes_.find(node->GetId()) != pendingPostNodes_.end() ||
775         pendingPostCardNodes_.find(node->GetId()) != pendingPostCardNodes_.end()) {
776         node->SetUifirstSyncFlag(true);
777     }
778 
779     auto ret = CollectSkipSyncNodeWithDrawableState(node);
780     if (ret != SkipSyncState::STATE_NEED_CHECK) {
781         return ret == SkipSyncState::STATE_NEED_SKIP;
782     }
783 
784     if (NodeIsInCardWhiteList(*node) && processingCardNodeSkipSync_.count(node->GetUifirstRootNodeId())) {
785         pendingSyncForSkipBefore_[node->GetUifirstRootNodeId()].push_back(node);
786         auto isUifirstRootNode = (node->GetUifirstRootNodeId() == node->GetId());
787         RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
788             isUifirstRootNode ? "set partial_sync card" : "CollectSkipSyncNode card",
789             node->GetId(), node->GetInstanceRootNodeId());
790         SetUifirstSkipPartialSync(node, isUifirstRootNode);
791         return !isUifirstRootNode;
792     }
793     if (processingNodePartialSync_.count(node->GetInstanceRootNodeId()) > 0) {
794         pendingSyncForSkipBefore_[node->GetInstanceRootNodeId()].push_back(node);
795         auto isInstanceRootNode = (node->GetInstanceRootNodeId() == node->GetId());
796         RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
797             isInstanceRootNode ? "set partial_sync" : "CollectSkipSyncNode",
798             node->GetId(), node->GetInstanceRootNodeId());
799         SetUifirstSkipPartialSync(node, isInstanceRootNode);
800         return !isInstanceRootNode;
801     } else if (processingNodeSkipSync_.count(node->GetInstanceRootNodeId()) > 0) {
802         RS_OPTIONAL_TRACE_NAME_FMT("CollectSkipSyncNode root %" PRIu64", node %" PRIu64,
803             node->GetInstanceRootNodeId(), node->GetId());
804         pendingSyncForSkipBefore_[node->GetInstanceRootNodeId()].push_back(node);
805         return true;
806     }
807     return false;
808 }
809 
RestoreSkipSyncNode()810 void RSUifirstManager::RestoreSkipSyncNode()
811 {
812     std::vector<NodeId> todele;
813     for (auto& it : pendingSyncForSkipBefore_) {
814         if (processingNodeSkipSync_.count(it.first) == 0 && processingNodePartialSync_.count(it.first) == 0 &&
815             processingCardNodeSkipSync_.count(it.first) == 0) {
816             todele.push_back(it.first);
817             RS_OPTIONAL_TRACE_NAME_FMT("RestoreSkipSyncNode %" PRIu64" num%d", it.first, it.second.size());
818             for (auto& node : it.second) {
819                 node->SetUifirstSkipPartialSync(false);
820                 node->AddToPendingSyncList();
821             }
822         }
823     }
824     for (auto id : todele) {
825         pendingSyncForSkipBefore_.erase(id);
826         if (!mainThread_) {
827             continue;
828         }
829         auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(id);
830         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node);
831         if (!surfaceNode) {
832             continue;
833         }
834         if (surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD &&
835             surfaceNode->GetUifirstRootNodeId() == surfaceNode->GetId() &&
836             pendingPostCardNodes_.find(surfaceNode->GetId()) == pendingPostCardNodes_.end()) {
837             pendingPostCardNodes_[surfaceNode->GetId()] = surfaceNode;
838             RS_OPTIONAL_TRACE_NAME_FMT("RestoreSkipSyncNode AddPendingPostCard %llu", id);
839         }
840     }
841 }
842 
ClearSubthreadRes()843 void RSUifirstManager::ClearSubthreadRes()
844 {
845     RS_OPTIONAL_TRACE_NAME_FMT("ClearSubthreadRes");
846     if (subthreadProcessingNode_.size() == 0 &&
847         pendingSyncForSkipBefore_.size() == 0) {
848         noUifirstNodeFrameCount_.fetch_add(1);
849         if (noUifirstNodeFrameCount_.load() == CLEAR_RES_THRESHOLD) {
850             RSSubThreadManager::Instance()->ResetSubThreadGrContext();
851             PostReleaseCacheSurfaceSubTasks();
852         }
853     } else {
854         noUifirstNodeFrameCount_.store(0);
855     }
856     reuseNodes_.clear();
857 }
858 
ForceClearSubthreadRes()859 void RSUifirstManager::ForceClearSubthreadRes()
860 {
861     noUifirstNodeFrameCount_.store(0);
862     RSSubThreadManager::Instance()->ReleaseTexture();
863 }
864 
IsPreFirstLevelNodeDoingAndTryClear(std::shared_ptr<RSRenderNode> node)865 bool RSUifirstManager::IsPreFirstLevelNodeDoingAndTryClear(std::shared_ptr<RSRenderNode> node)
866 {
867     if (!node) {
868         return true;
869     }
870     auto& preFirstLevelNodeIdSet = node->GetMutablePreFirstLevelNodeIdSet();
871     for (auto it = preFirstLevelNodeIdSet.begin(); it != preFirstLevelNodeIdSet.end();
872          it = preFirstLevelNodeIdSet.erase(it)) {
873         const auto& curRootIdState = GetUifirstCachedState(*it);
874         if (curRootIdState == CacheProcessStatus::DOING || curRootIdState == CacheProcessStatus::WAITING) {
875             return true;
876         }
877     }
878     return false;
879 }
880 
SetNodePriorty(std::list<NodeId> & result,std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>> & pendingNode)881 void RSUifirstManager::SetNodePriorty(std::list<NodeId>& result,
882     std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>& pendingNode)
883 {
884     bool isFocusNodeFound = false;
885     auto isFocusId = RSMainThread::Instance()->GetFocusNodeId();
886     auto isLeashId = RSMainThread::Instance()->GetFocusLeashWindowId();
887     uint32_t postOrder = 0;
888     for (auto& item : pendingNode) {
889         postOrder++;
890         auto const& [id, value] = item;
891         if (IsPreFirstLevelNodeDoingAndTryClear(value)) {
892             continue;
893         }
894         auto drawable = GetSurfaceDrawableByID(id);
895         if (!drawable) {
896             continue;
897         }
898         if (drawable->HasCachedTexture()) {
899             drawable->SetRenderCachePriority(NodePriorityType::SUB_LOW_PRIORITY);
900         } else {
901             drawable->SetRenderCachePriority(NodePriorityType::SUB_HIGH_PRIORITY);
902         }
903         if (drawable->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::WAITING) {
904             drawable->SetRenderCachePriority(NodePriorityType::SUB_HIGH_PRIORITY);
905         }
906         if (!isFocusNodeFound) {
907             if (id == isFocusId || id == isLeashId) {
908                 // for resolving response latency
909                 drawable->SetRenderCachePriority(NodePriorityType::SUB_FOCUSNODE_PRIORITY);
910                 isFocusNodeFound = true;
911             }
912         }
913         auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
914         if (surfaceParams && surfaceParams->GetPreSubHighPriorityType()) {
915             drawable->SetRenderCachePriority(NodePriorityType::SUB_VIDEO_PRIORITY);
916         }
917         drawable->SetUifirstPostOrder(postOrder);
918         sortedSubThreadNodeIds_.emplace_back(id);
919     }
920     RS_TRACE_NAME_FMT("SetNodePriorty result [%zu] pendingNode [%zu]", result.size(), pendingNode.size());
921 }
922 
SortSubThreadNodesPriority()923 void RSUifirstManager::SortSubThreadNodesPriority()
924 {
925     sortedSubThreadNodeIds_.clear();
926     SetNodePriorty(sortedSubThreadNodeIds_, pendingPostNodes_);
927     SetNodePriorty(sortedSubThreadNodeIds_, pendingPostCardNodes_);
928     RS_LOGD("SetNodePriorty result [%{public}zu] pendingNode [%{public}zu] pendingCardNode [%{public}zu]",
929         sortedSubThreadNodeIds_.size(), pendingPostNodes_.size(), pendingPostCardNodes_.size());
930     sortedSubThreadNodeIds_.sort([this](const auto& first, const auto& second) -> bool {
931         auto drawable1 = GetSurfaceDrawableByID(first);
932         auto drawable2 = GetSurfaceDrawableByID(second);
933         if (drawable1 == nullptr || drawable2 == nullptr) {
934             ROSEN_LOGE("RSUifirstManager::SortSubThreadNodesPriority sort nullptr found in pendingPostNodes_, "
935                 "this should not happen");
936             return false;
937         }
938         auto surfaceParams1 = static_cast<RSSurfaceRenderParams*>(drawable1->GetRenderParams().get());
939         if (!surfaceParams1) {
940             RS_LOGE("RSSurfaceRenderNodeDrawable::sortsubthread params1 is nullptr");
941             return false;
942         }
943         auto surfaceParams2 = static_cast<RSSurfaceRenderParams*>(drawable2->GetRenderParams().get());
944         if (!surfaceParams2) {
945             RS_LOGE("RSSurfaceRenderNodeDrawable::sortsubthread params2 is nullptr");
946             return false;
947         }
948         if (drawable1->GetRenderCachePriority() == drawable2->GetRenderCachePriority()) {
949             return drawable1->GetUifirstPostOrder() > drawable2->GetUifirstPostOrder();
950         } else {
951             return drawable1->GetRenderCachePriority() < drawable2->GetRenderCachePriority();
952         }
953     });
954 }
955 
956 // post in drawframe sync time
PostUifistSubTasks()957 void RSUifirstManager::PostUifistSubTasks()
958 {
959     // if screen is power-off, uifirst sub thread can be suspended.
960     if (RSUniRenderUtil::CheckRenderSkipIfScreenOff()) {
961         return;
962     }
963     PurgePendingPostNodes();
964     SortSubThreadNodesPriority();
965     if (sortedSubThreadNodeIds_.size() > 0) {
966         RS_TRACE_NAME_FMT("PostUifistSubTasks %zu", sortedSubThreadNodeIds_.size());
967         for (auto& id : sortedSubThreadNodeIds_) {
968             PostSubTask(id);
969         }
970         pendingPostNodes_.clear();
971         pendingPostCardNodes_.clear();
972         sortedSubThreadNodeIds_.clear();
973     } else {
974         ClearSubthreadRes();
975     }
976     UifirstCurStateClear();
977 }
978 
IsInLeashWindowTree(RSSurfaceRenderNode & node,NodeId instanceRootId)979 bool RSUifirstManager::IsInLeashWindowTree(RSSurfaceRenderNode& node, NodeId instanceRootId)
980 {
981     if (node.GetInstanceRootNodeId() == instanceRootId) {
982         return true;
983     }
984     if (!node.IsLeashWindow()) {
985         return false;
986     }
987     for (auto& child : *(node.GetChildren())) {
988         if (!child) {
989             continue;
990         }
991         auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
992         if (!surfaceChild) {
993             continue;
994         }
995         if (surfaceChild->GetInstanceRootNodeId() == instanceRootId) {
996             return true;
997         }
998     }
999     return false;
1000 }
1001 
LeashWindowContainMainWindow(RSSurfaceRenderNode & node)1002 static inline bool LeashWindowContainMainWindow(RSSurfaceRenderNode& node)
1003 {
1004     if (node.IsLeashWindow() && node.HasSubSurfaceNodes()) {
1005         return true;
1006     }
1007     return false;
1008 }
1009 
AddPendingPostNode(NodeId id,std::shared_ptr<RSSurfaceRenderNode> & node,MultiThreadCacheType currentFrameCacheType)1010 void RSUifirstManager::AddPendingPostNode(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node,
1011     MultiThreadCacheType currentFrameCacheType)
1012 {
1013     if (id == INVALID_NODEID || !node) {
1014         return;
1015     }
1016 
1017     // process for uifirst node
1018     UpdateChildrenDirtyRect(*node);
1019     node->SetHwcChildrenDisabledState();
1020     RS_OPTIONAL_TRACE_NAME_FMT("hwc debug: name:%s id:%" PRIu64 " children disabled by uifirst",
1021         node->GetName().c_str(), node->GetId());
1022     node->AddToPendingSyncList();
1023 
1024     if (currentFrameCacheType == MultiThreadCacheType::LEASH_WINDOW ||
1025         currentFrameCacheType == MultiThreadCacheType::NONFOCUS_WINDOW) {
1026         if (isRecentTaskScene_.load() && !node->IsNodeToBeCaptured() &&
1027             currentFrameCacheType == MultiThreadCacheType::LEASH_WINDOW) {
1028             node->SetIsNodeToBeCaptured(true);
1029         } else if (!isRecentTaskScene_.load()) {
1030             node->SetIsNodeToBeCaptured(false);
1031         }
1032         // delete card node in leashwindow tree
1033         for (auto it = pendingPostCardNodes_.begin(); it != pendingPostCardNodes_.end();) {
1034             auto surfaceNode = it->second;
1035             if (surfaceNode && IsInLeashWindowTree(*node, surfaceNode->GetInstanceRootNodeId())) {
1036                 DisableUifirstNode(*surfaceNode);
1037                 it = pendingPostCardNodes_.erase(it);
1038             } else {
1039                 it++;
1040             }
1041         }
1042         pendingPostNodes_[id] = node;
1043     } else if (currentFrameCacheType == MultiThreadCacheType::ARKTS_CARD) {
1044         pendingPostCardNodes_[id] = node;
1045     }
1046 
1047     pendingResetNodes_.erase(id); // enable uifirst when waiting for reset
1048 }
1049 
LeashWindowContainMainWindowAndStarting(RSSurfaceRenderNode & node)1050 NodeId RSUifirstManager::LeashWindowContainMainWindowAndStarting(RSSurfaceRenderNode& node)
1051 {
1052     if (!node.IsLeashWindow()) {
1053         return INVALID_NODEID;
1054     }
1055     int mainwindowNum = 0;
1056     int canvasNodeNum = 0;
1057     bool support = true;
1058     std::shared_ptr<RSRenderNode> startingWindow = nullptr;
1059     for (auto& child : *(node.GetSortedChildren())) {
1060         if (!child) {
1061             continue;
1062         }
1063         RS_TRACE_NAME_FMT("nID:%" PRIu64" , nType:%d, support:%d, canvasNodeNum:%d, mainwindowNum:%d",
1064             child->GetId(), static_cast<int>(child->GetType()), support, canvasNodeNum, mainwindowNum);
1065         auto canvasChild = child->ReinterpretCastTo<RSCanvasRenderNode>();
1066         if (canvasChild && canvasChild->GetChildrenCount() == 0 && mainwindowNum > 0) {
1067             canvasNodeNum++;
1068             if (startingWindow != nullptr) {
1069                 startingWindow->SetStartingWindowFlag(false);
1070             }
1071             startingWindow = canvasChild;
1072             continue;
1073         }
1074         auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1075         if (surfaceChild && surfaceChild->IsMainWindowType() && canvasNodeNum == 0) {
1076             mainwindowNum++;
1077             continue;
1078         }
1079         support = false;
1080     }
1081     RS_TRACE_NAME_FMT("uifirst_node support:%d, canvasNodeNum:%d, mainwindowNum:%d, startingWindow:%d",
1082         support, canvasNodeNum, mainwindowNum, startingWindow != nullptr);
1083     if (support && canvasNodeNum == 1 && mainwindowNum > 0 && startingWindow) { // starting window & appwindow
1084         startingWindow->SetStartingWindowFlag(true);
1085         return startingWindow->GetId();
1086     } else {
1087         if (startingWindow) {
1088             startingWindow->SetStartingWindowFlag(false);
1089         }
1090         return INVALID_NODEID;
1091     }
1092 }
1093 
AddPendingResetNode(NodeId id,std::shared_ptr<RSSurfaceRenderNode> & node)1094 void RSUifirstManager::AddPendingResetNode(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node)
1095 {
1096     if (id == INVALID_NODEID) {
1097         return;
1098     }
1099     pendingResetNodes_[id] = node;
1100 }
1101 
GetNodeStatus(NodeId id)1102 CacheProcessStatus RSUifirstManager::GetNodeStatus(NodeId id)
1103 {
1104     auto drawable = GetSurfaceDrawableByID(id);
1105     if (drawable) {
1106         return drawable->GetCacheSurfaceProcessedStatus();
1107     }
1108     return CacheProcessStatus::UNKNOWN;
1109 }
1110 
UpdateCompletedSurface(NodeId id)1111 void RSUifirstManager::UpdateCompletedSurface(NodeId id)
1112 {
1113     auto drawable = GetSurfaceDrawableByID(id);
1114     if (drawable) {
1115         drawable->UpdateCompletedCacheSurface();
1116     }
1117 }
1118 
1119 // add&clear in render
AddReuseNode(NodeId id)1120 void RSUifirstManager::AddReuseNode(NodeId id)
1121 {
1122     if (id == INVALID_NODEID) {
1123         return;
1124     }
1125     reuseNodes_.insert(id);
1126 }
1127 
OnProcessEventResponse(DataBaseRs & info)1128 void RSUifirstManager::OnProcessEventResponse(DataBaseRs& info)
1129 {
1130     RSReclaimMemoryManager::Instance().InterruptReclaimTask(info.sceneId);
1131     RS_OPTIONAL_TRACE_NAME_FMT("uifirst uniqueId:%" PRId64", appPid:%" PRId32", sceneId:%s",
1132         info.uniqueId, info.appPid, info.sceneId.c_str());
1133     EventInfo eventInfo = {GetCurSysTime(), 0, info.uniqueId, info.appPid, info.sceneId, {}};
1134     std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1135     for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
1136         it->disableNodes.clear();
1137     }
1138     globalFrameEvent_.push_back(std::move(eventInfo));
1139     currentFrameCanSkipFirstWait_ = EventsCanSkipFirstWait(globalFrameEvent_);
1140 }
1141 
OnProcessEventComplete(DataBaseRs & info)1142 void RSUifirstManager::OnProcessEventComplete(DataBaseRs& info)
1143 {
1144     int64_t curSysTime = GetCurSysTime();
1145     std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1146     for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
1147         if (it->uniqueId == info.uniqueId && it->sceneId == info.sceneId) {
1148             // delay delete for animation continue
1149             it->stopTime = curSysTime;
1150             break;
1151         }
1152     }
1153 }
1154 
EventDisableLeashWindowCache(NodeId id,EventInfo & info)1155 void RSUifirstManager::EventDisableLeashWindowCache(NodeId id, EventInfo& info)
1156 {
1157     std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1158     for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
1159         if (it->uniqueId == info.uniqueId && it->sceneId == info.sceneId) {
1160             it->disableNodes.insert(id);
1161             break;
1162         }
1163     }
1164 }
1165 
PrepareCurrentFrameEvent()1166 void RSUifirstManager::PrepareCurrentFrameEvent()
1167 {
1168     int64_t curSysTime = GetCurSysTime();
1169     currentFrameEvent_.clear();
1170     if (!mainThread_ || entryViewNodeId_ == INVALID_NODEID || negativeScreenNodeId_ == INVALID_NODEID) {
1171         mainThread_ = RSMainThread::Instance();
1172         if (mainThread_) {
1173             entryViewNodeId_ = mainThread_->GetContext().GetNodeMap().GetEntryViewNodeId();
1174             negativeScreenNodeId_ = mainThread_->GetContext().GetNodeMap().GetNegativeScreenNodeId();
1175             scbPid_ = ExtractPid(entryViewNodeId_);
1176         }
1177     }
1178     {
1179         std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1180         for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end();) {
1181             if (it->stopTime != 0 &&
1182                 ((curSysTime > it->stopTime) && (curSysTime - it->stopTime) > EVENT_STOP_TIMEOUT)) {
1183                 it = globalFrameEvent_.erase(it);
1184                 continue;
1185             }
1186 
1187             if ((curSysTime > it->startTime) && (curSysTime - it->startTime) > EVENT_START_TIMEOUT) {
1188                 it = globalFrameEvent_.erase(it);
1189                 continue;
1190             }
1191             it++;
1192         }
1193         if (globalFrameEvent_.empty()) {
1194             currentFrameCanSkipFirstWait_ = false;
1195             return;
1196         }
1197         // copy global to current, judge leashwindow stop
1198         currentFrameEvent_.assign(globalFrameEvent_.begin(), globalFrameEvent_.end());
1199     }
1200     currentFrameCanSkipFirstWait_ = EventsCanSkipFirstWait(currentFrameEvent_);
1201 }
1202 
OnProcessAnimateScene(SystemAnimatedScenes systemAnimatedScene)1203 void RSUifirstManager::OnProcessAnimateScene(SystemAnimatedScenes systemAnimatedScene)
1204 {
1205     RS_TRACE_NAME_FMT("RSUifirstManager::OnProcessAnimateScene systemAnimatedScene:%d", systemAnimatedScene);
1206     if ((systemAnimatedScene == SystemAnimatedScenes::ENTER_RECENTS) && !isRecentTaskScene_.load()) {
1207         isRecentTaskScene_ = true;
1208     } else if ((systemAnimatedScene == SystemAnimatedScenes::EXIT_RECENTS) && isRecentTaskScene_.load()) {
1209         isRecentTaskScene_ = false;
1210     }
1211 }
1212 
NodeIsInCardWhiteList(RSRenderNode & node)1213 bool RSUifirstManager::NodeIsInCardWhiteList(RSRenderNode& node)
1214 {
1215     if ((entryViewNodeId_ != INVALID_NODEID) && (negativeScreenNodeId_ != INVALID_NODEID)) {
1216         auto instanceRootId = node.GetInstanceRootNodeId();
1217         if (instanceRootId == entryViewNodeId_ || instanceRootId == negativeScreenNodeId_) {
1218             return true;
1219         }
1220     }
1221     return false;
1222 }
1223 
IsCardSkipFirstWaitScene(std::string & scene,int32_t appPid)1224 bool RSUifirstManager::IsCardSkipFirstWaitScene(std::string& scene, int32_t appPid)
1225 {
1226     if (appPid != scbPid_) {
1227         return false;
1228     }
1229     for (auto& item : cardCanSkipFirstWaitScene_) {
1230         if ((scene.find(item) != std::string::npos)) {
1231             return true;
1232         }
1233     }
1234     return false;
1235 }
1236 
EventsCanSkipFirstWait(std::vector<EventInfo> & events)1237 bool RSUifirstManager::EventsCanSkipFirstWait(std::vector<EventInfo>& events)
1238 {
1239     if (events.empty()) {
1240         return false;
1241     }
1242     if (isCurrentFrameHasCardNodeReCreate_) {
1243         RS_OPTIONAL_TRACE_NAME("uifirst current frame can't skip wait");
1244         return false;
1245     }
1246     for (auto& item : events) {
1247         if (IsCardSkipFirstWaitScene(item.sceneId, item.appPid)) {
1248             return true;
1249         }
1250     }
1251     return false;
1252 }
1253 
CheckIfAppWindowHasAnimation(RSSurfaceRenderNode & node)1254 bool RSUifirstManager::CheckIfAppWindowHasAnimation(RSSurfaceRenderNode& node)
1255 {
1256     if (currentFrameEvent_.empty()) {
1257         return false;
1258     }
1259 
1260     std::set<int32_t> appPids;
1261     if (node.IsAppWindow()) {
1262         appPids.insert(ExtractPid(node.GetId()));
1263     } else if (node.IsLeashWindow()) {
1264         for (auto& child : *(node.GetChildren())) {
1265             if (!child) {
1266                 continue;
1267             }
1268             auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1269             if (!surfaceChild) {
1270                 continue;
1271             }
1272             if (surfaceChild->IsAppWindow()) {
1273                 appPids.insert(ExtractPid(surfaceChild->GetId()));
1274             }
1275         }
1276     }
1277 
1278     if (appPids.empty()) {
1279         return false;
1280     }
1281     for (auto& item : currentFrameEvent_) {
1282         if (item.disableNodes.count(node.GetId())) {
1283             return true;
1284         }
1285         if (appPids.count(item.appPid) && (node.GetUifirstStartTime() > 0) &&
1286             (node.GetUifirstStartTime() < (item.startTime - EVENT_DISABLE_UIFIRST_GAP)) &&
1287             (item.sceneId.find(EVENT_DISABLE_UIFIRST) != std::string::npos)) {
1288             EventDisableLeashWindowCache(node.GetId(), item);
1289             return true; // app has animation, stop leashwindow uifirst
1290         }
1291     }
1292     return false;
1293 }
1294 
IsArkTsCardCache(RSSurfaceRenderNode & node,bool animation)1295 bool RSUifirstManager::IsArkTsCardCache(RSSurfaceRenderNode& node, bool animation) // maybe canvas node ?
1296 {
1297     bool flag = ((RSUifirstManager::Instance().GetUiFirstMode() == UiFirstModeType::SINGLE_WINDOW_MODE) &&
1298         (node.GetSurfaceNodeType() == RSSurfaceNodeType::ABILITY_COMPONENT_NODE) &&
1299         RSUifirstManager::Instance().NodeIsInCardWhiteList(node) &&
1300         (node.ShouldPaint()) && (node.GetName().find(ARKTSCARDNODE_NAME) != std::string::npos));
1301     if (flag) { // Planning: mark by arkui or app
1302         return true;
1303     }
1304     return false;
1305 }
1306 
1307 // animation first, may reuse last image cache
IsLeashWindowCache(RSSurfaceRenderNode & node,bool animation)1308 bool RSUifirstManager::IsLeashWindowCache(RSSurfaceRenderNode& node, bool animation)
1309 {
1310     bool isNeedAssignToSubThread = false;
1311     if ((RSUifirstManager::Instance().GetUiFirstMode() == UiFirstModeType::MULTI_WINDOW_MODE) ||
1312         (node.GetFirstLevelNodeId() != node.GetId()) ||
1313         (RSUifirstManager::Instance().NodeIsInCardWhiteList(node)) ||
1314         (RSUifirstManager::Instance().CheckIfAppWindowHasAnimation(node))) {
1315         return false;
1316     }
1317     if (node.IsLeashWindow()) {
1318         if (RSUifirstManager::Instance().IsRecentTaskScene()) {
1319             isNeedAssignToSubThread = node.IsScale() && LeashWindowContainMainWindow(node);
1320         } else {
1321             isNeedAssignToSubThread = animation;
1322         }
1323         // 1: Planning: support multi appwindows
1324         isNeedAssignToSubThread = (isNeedAssignToSubThread ||
1325                 (node.GetForceUIFirst() || node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_ENABLE_LIMIT))
1326                 && !node.HasFilter() && !RSUifirstManager::Instance().rotationChanged_;
1327     }
1328 
1329     bool needFilterSCB = node.GetSurfaceWindowType() == SurfaceWindowType::SYSTEM_SCB_WINDOW;
1330     if (needFilterSCB || node.IsSelfDrawingType()) {
1331         RS_TRACE_NAME_FMT("IsLeashWindowCache: needFilterSCB [%d]", needFilterSCB);
1332         return false;
1333     }
1334     RS_TRACE_NAME_FMT("IsLeashWindowCache: toSubThread[%d] IsScale[%d]"
1335         " filter:[%d] rotate[%d] captured[%d]",
1336         isNeedAssignToSubThread, node.IsScale(),
1337         node.HasFilter(), RSUifirstManager::Instance().rotationChanged_, node.IsNodeToBeCaptured());
1338     return isNeedAssignToSubThread;
1339 }
1340 
1341 // Vm app not use uifirst when it is focused
IsVMSurfaceName(std::string surfaceName)1342 bool RSUifirstManager::IsVMSurfaceName(std::string surfaceName)
1343 {
1344     for (auto& item : vmAppNameSet_) {
1345         if (surfaceName.find(item) != std::string::npos) {
1346             return true;
1347         }
1348     }
1349 
1350     return false;
1351 }
1352 
1353 // NonFocusWindow, may reuse last image cache
IsNonFocusWindowCache(RSSurfaceRenderNode & node,bool animation)1354 bool RSUifirstManager::IsNonFocusWindowCache(RSSurfaceRenderNode& node, bool animation)
1355 {
1356     bool isDisplayRotation = RSUifirstManager::Instance().rotationChanged_;
1357     if ((RSUifirstManager::Instance().GetUiFirstMode() != UiFirstModeType::MULTI_WINDOW_MODE) ||
1358         (node.GetFirstLevelNodeId() != node.GetId()) ||
1359         (RSUifirstManager::Instance().NodeIsInCardWhiteList(node))) {
1360         return false;
1361     }
1362 
1363     std::string surfaceName = node.GetName();
1364     bool needFilterSCB = node.GetSurfaceWindowType() == SurfaceWindowType::SYSTEM_SCB_WINDOW;
1365     if (!(node.GetForceUIFirst() || node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_ENABLE_LIMIT)
1366         && (needFilterSCB || node.IsSelfDrawingType())) {
1367         return false;
1368     }
1369     bool focus = node.IsFocusedNode(RSMainThread::Instance()->GetFocusNodeId()) ||
1370         node.IsFocusedNode(RSMainThread::Instance()->GetFocusLeashWindowId());
1371     // open app with modal window animation, close uifirst
1372     bool modalAnimation = animation && node.GetUIFirstSwitch() == RSUIFirstSwitch::MODAL_WINDOW_CLOSE;
1373     bool optFocus = focus || UNLIKELY(node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_DISABLE_NONFOCUS);
1374     if (optFocus && (node.GetHasSharedTransitionNode() ||
1375         RSUifirstManager::Instance().IsVMSurfaceName(surfaceName) ||
1376         !animation || modalAnimation)) {
1377         RS_TRACE_NAME_FMT("IsNonFocusWindowCache: surfaceName[%s] focus:%d optFocus:%d animation:%d switch:%d",
1378             surfaceName.c_str(), focus, optFocus, animation, node.GetUIFirstSwitch());
1379         return false;
1380     }
1381     return RSUifirstManager::Instance().QuerySubAssignable(node, isDisplayRotation);
1382 }
1383 
IsToSubByAppAnimation() const1384 bool RSUifirstManager::IsToSubByAppAnimation() const
1385 {
1386     for (auto& it : currentFrameEvent_) {
1387         if (std::find(toSubByAppAnimation_.begin(), toSubByAppAnimation_.end(), it.sceneId) !=
1388             toSubByAppAnimation_.end()) {
1389             return true;
1390         }
1391     }
1392     return false;
1393 }
1394 
GetSubNodeIsTransparent(RSSurfaceRenderNode & node,std::string & dfxMsg)1395 bool RSUifirstManager::GetSubNodeIsTransparent(RSSurfaceRenderNode& node, std::string& dfxMsg)
1396 {
1397     bool hasTransparent = false;
1398     if (node.IsLeashWindow()) {
1399         for (auto &child : *node.GetSortedChildren()) {
1400             auto childSurfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1401             if (childSurfaceNode == nullptr) {
1402                 continue;
1403             }
1404             hasTransparent |= childSurfaceNode->IsTransparent();
1405         }
1406     } else {
1407         hasTransparent = node.IsTransparent();
1408     }
1409     if (!hasTransparent || !IsToSubByAppAnimation()) {
1410         // if not transparent, no need to check IsToSubByAppAnimation;
1411         return hasTransparent;
1412     }
1413 
1414     bool isAbilityBgColorTransparent = true;
1415     if (node.IsLeashWindow()) {
1416         for (auto &child : *node.GetSortedChildren()) {
1417             auto childSurfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1418             if (childSurfaceNode == nullptr) {
1419                 continue;
1420             }
1421             const auto& properties = childSurfaceNode->GetRenderProperties();
1422             if (properties.GetNeedDrawBehindWindow() || (childSurfaceNode->GetAbilityBgAlpha() < UINT8_MAX)) {
1423                 isAbilityBgColorTransparent = true;
1424                 dfxMsg = "AbBgAlpha: " + std::to_string(childSurfaceNode->GetAbilityBgAlpha()) + " behindWindow: " +
1425                     std::to_string(properties.GetNeedDrawBehindWindow());
1426                 break;
1427             } else {
1428                 isAbilityBgColorTransparent = false;
1429             }
1430         }
1431     } else {
1432         const auto& properties = node.GetRenderProperties();
1433         isAbilityBgColorTransparent = properties.GetNeedDrawBehindWindow() || (node.GetAbilityBgAlpha() < UINT8_MAX);
1434         dfxMsg = "AbBgAlpha: " + std::to_string(node.GetAbilityBgAlpha()) + " behindWindow: " +
1435             std::to_string(properties.GetNeedDrawBehindWindow());
1436     }
1437     return isAbilityBgColorTransparent;
1438 }
1439 
QuerySubAssignable(RSSurfaceRenderNode & node,bool isRotation)1440 bool RSUifirstManager::QuerySubAssignable(RSSurfaceRenderNode& node, bool isRotation)
1441 {
1442     if (!node.IsFirstLevelNode()) {
1443         return false;
1444     }
1445 
1446     auto childHasVisibleFilter = node.ChildHasVisibleFilter();
1447     auto hasFilter = node.HasFilter();
1448     auto globalAlpha = node.GetGlobalAlpha();
1449     auto hasProtectedLayer = node.GetSpecialLayerMgr().Find(SpecialLayerType::HAS_PROTECTED);
1450     std::string dfxMsg;
1451     auto hasTransparentSurface = GetSubNodeIsTransparent(node, dfxMsg);
1452 
1453     RS_TRACE_NAME_FMT("SubThreadAssignable node[%lld] hasTransparent: %d, childHasVisibleFilter: %d, hasFilter: %d,"
1454         "isRotation: %d & %d globalAlpha[%f], hasProtectedLayer: %d %s", node.GetId(), hasTransparentSurface,
1455         childHasVisibleFilter, hasFilter, isRotation, RSSystemProperties::GetCacheOptimizeRotateEnable(), globalAlpha,
1456         hasProtectedLayer, dfxMsg.c_str());
1457     bool rotateOptimize = RSSystemProperties::GetCacheOptimizeRotateEnable() ?
1458         !(isRotation && ROSEN_EQ(globalAlpha, 0.0f)) : !isRotation;
1459     return !(hasTransparentSurface && childHasVisibleFilter) && !hasFilter && rotateOptimize && !hasProtectedLayer;
1460 }
1461 
ForceUpdateUifirstNodes(RSSurfaceRenderNode & node)1462 bool RSUifirstManager::ForceUpdateUifirstNodes(RSSurfaceRenderNode& node)
1463 {
1464     if (!isUiFirstOn_ || !node.GetUifirstSupportFlag() || node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_DISABLE ||
1465         node.GetSpecialLayerMgr().Find(SpecialLayerType::HAS_PROTECTED)) {
1466         UifirstStateChange(node, MultiThreadCacheType::NONE);
1467         // This branch will be discarded
1468         if (!node.isUifirstNode_) {
1469             node.isUifirstDelay_++;
1470             if (node.isUifirstDelay_ > EVENT_STOP_TIMEOUT) {
1471                 node.isUifirstNode_ = true;
1472             }
1473         }
1474         return true;
1475     }
1476     // This branch will be discarded
1477     if (node.isForceFlag_ && node.IsLeashWindow()) {
1478         RS_OPTIONAL_TRACE_NAME_FMT("ForceUpdateUifirstNodes: isUifirstEnable: %d", node.isUifirstEnable_);
1479         if (!node.isUifirstEnable_) {
1480             UifirstStateChange(node, MultiThreadCacheType::NONE);
1481             return true;
1482         }
1483         UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1484         return true;
1485     }
1486     if (node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_ENABLE && node.IsLeashWindow()) {
1487         RS_OPTIONAL_TRACE_NAME_FMT("ForceUpdateUifirstNodes: nodeName: %s, uiFirstSwitch: %d",
1488             node.GetName().c_str(), node.GetUIFirstSwitch());
1489         if (RSUifirstManager::Instance().GetUiFirstMode() == UiFirstModeType::MULTI_WINDOW_MODE) {
1490             UifirstStateChange(node, MultiThreadCacheType::NONFOCUS_WINDOW);
1491         } else {
1492             UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1493         }
1494         return true;
1495     }
1496     return false;
1497 }
1498 
UpdateUifirstNodes(RSSurfaceRenderNode & node,bool ancestorNodeHasAnimation)1499 void RSUifirstManager::UpdateUifirstNodes(RSSurfaceRenderNode& node, bool ancestorNodeHasAnimation)
1500 {
1501     RS_TRACE_NAME_FMT("UpdateUifirstNodes: Id[%llu] name[%s] FLId[%llu] Ani[%d] Support[%d] isUiFirstOn[%d],"
1502         " isForceFlag:[%d], hasProtectedLayer:[%d] switch:[%d]", node.GetId(), node.GetName().c_str(),
1503         node.GetFirstLevelNodeId(), ancestorNodeHasAnimation, node.GetUifirstSupportFlag(), isUiFirstOn_,
1504         node.isForceFlag_, node.GetSpecialLayerMgr().Find(SpecialLayerType::HAS_PROTECTED), node.GetUIFirstSwitch());
1505     if (ForceUpdateUifirstNodes(node)) {
1506         return;
1507     }
1508     if (RSUifirstManager::IsLeashWindowCache(node, ancestorNodeHasAnimation)) {
1509         UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1510         return;
1511     }
1512     if (RSUifirstManager::IsNonFocusWindowCache(node, ancestorNodeHasAnimation)) {
1513         // purpose: to avoid that RT waits uifirst cache long time when switching to uifirst first frame,
1514         // draw and cache win in RT on first frame, then use RT thread cache to draw until uifirst cache ready.
1515         if (node.GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE && !node.GetSubThreadAssignable()) {
1516             RS_TRACE_NAME_FMT("AssignMainThread selfAndParentShouldPaint: %d, skipDraw: %d",
1517                 node.GetSelfAndParentShouldPaint(), node.GetSkipDraw());
1518             UifirstStateChange(node, MultiThreadCacheType::NONE);   // mark as draw win in RT thread
1519             if (node.GetSelfAndParentShouldPaint() && !node.GetSkipDraw()) {
1520                 node.SetSubThreadAssignable(true);                      // mark as assignable to uifirst next frame
1521                 node.SetNeedCacheSurface(true);                         // mark as that needs cache win in RT
1522 
1523                 // disable HWC, to prevent the rect of self-drawing nodes in cache from becoming transparent
1524                 node.SetHwcChildrenDisabledState();
1525                 RS_OPTIONAL_TRACE_NAME_FMT("hwc debug: name:%s id:%" PRIu64 " children disabled by uifirst first frame",
1526                     node.GetName().c_str(), node.GetId());
1527 
1528                 auto func = &RSUifirstManager::ProcessTreeStateChange;
1529                 node.RegisterTreeStateChangeCallback(func);
1530             }
1531         } else {
1532             UifirstStateChange(node, MultiThreadCacheType::NONFOCUS_WINDOW);
1533         }
1534         return;
1535     }
1536     if (RSUifirstManager::IsArkTsCardCache(node, ancestorNodeHasAnimation)) {
1537         UifirstStateChange(node, MultiThreadCacheType::ARKTS_CARD);
1538         return;
1539     }
1540     UifirstStateChange(node, MultiThreadCacheType::NONE);
1541 }
1542 
UifirstStateChange(RSSurfaceRenderNode & node,MultiThreadCacheType currentFrameCacheType)1543 void RSUifirstManager::UifirstStateChange(RSSurfaceRenderNode& node, MultiThreadCacheType currentFrameCacheType)
1544 {
1545     auto lastFrameCacheType = node.GetLastFrameUifirstFlag();
1546     if ((lastFrameCacheType != MultiThreadCacheType::NONE) && (lastFrameCacheType != currentFrameCacheType)) {
1547         // not support cache type switch, just disable multithread cache
1548         currentFrameCacheType = MultiThreadCacheType::NONE;
1549     }
1550     if (lastFrameCacheType == MultiThreadCacheType::NONE) { // likely branch: last is disable
1551         if (currentFrameCacheType != MultiThreadCacheType::NONE) { // switch: disable -> enable
1552             auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.shared_from_this());
1553             if (!surfaceNode) {
1554                 RS_LOGE("UifirstStateChange surfaceNode is nullptr");
1555                 return;
1556             }
1557             RS_TRACE_NAME_FMT("UIFirst_switch disable -> enable %" PRIu64, node.GetId());
1558             RS_LOGI("uifirst disable -> enable. %{public}s id:%{public}" PRIu64, node.GetName().c_str(), node.GetId());
1559             SetUifirstNodeEnableParam(node, currentFrameCacheType);
1560             if (currentFrameCacheType == MultiThreadCacheType::ARKTS_CARD) { // now only update ArkTSCardNode
1561                 node.UpdateTreeUifirstRootNodeId(node.GetId());
1562             }
1563             if (currentFrameCacheType == MultiThreadCacheType::LEASH_WINDOW) {
1564                 node.SetUifirstUseStarting(LeashWindowContainMainWindowAndStarting(*surfaceNode));
1565                 NotifyUIStartingWindow(node.GetId(), true);
1566             }
1567             auto func = &RSUifirstManager::ProcessTreeStateChange;
1568             node.RegisterTreeStateChangeCallback(func);
1569             node.SetUifirstStartTime(GetCurSysTime());
1570             AddPendingPostNode(node.GetId(), surfaceNode, currentFrameCacheType); // clear pending reset status
1571             AddCardNodes(node.GetId(), currentFrameCacheType);
1572             node.SetSubThreadAssignable(true);
1573             node.SetNeedCacheSurface(false);
1574         } else { // keep disable
1575             RS_OPTIONAL_TRACE_NAME_FMT("UIFirst_keep disable  %" PRIu64, node.GetId());
1576             node.SetSubThreadAssignable(false);
1577             node.SetNeedCacheSurface(false);
1578         }
1579     } else { // last is enable
1580         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.shared_from_this());
1581         if (currentFrameCacheType != MultiThreadCacheType::NONE) { // keep enable
1582             RS_OPTIONAL_TRACE_NAME_FMT("UIFirst_keep enable  %" PRIu64, node.GetId());
1583             RS_LOGD("uifirst keep enable. %{public}s id:%{public}" PRIu64, node.GetName().c_str(), node.GetId());
1584             AddPendingPostNode(node.GetId(), surfaceNode, currentFrameCacheType);
1585         } else { // switch: enable -> disable
1586             RS_TRACE_NAME_FMT("UIFirst_switch enable -> disable %" PRIu64, node.GetId());
1587             RS_LOGI("uifirst enable -> disable. %{public}s id:%{public}" PRIu64, node.GetName().c_str(), node.GetId());
1588             node.SetUifirstStartTime(-1); // -1: default start time
1589             AddPendingResetNode(node.GetId(), surfaceNode); // set false onsync when task done
1590             RemoveCardNodes(node.GetId());
1591             node.SetSubThreadAssignable(false);
1592             node.SetNeedCacheSurface(false);
1593         }
1594     }
1595     node.SetLastFrameUifirstFlag(currentFrameCacheType);
1596 }
1597 
1598 // appwindow will not be traversed in process when cache leashwindow
UpdateChildrenDirtyRect(RSSurfaceRenderNode & node)1599 void RSUifirstManager::UpdateChildrenDirtyRect(RSSurfaceRenderNode& node)
1600 {
1601     RectI rect(0, 0, 0, 0);
1602     if (node.IsLeashWindow()) {
1603         for (auto& child : *(node.GetChildren())) {
1604             if (!child) {
1605                 continue;
1606             }
1607             auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1608             if (!surfaceChild) {
1609                 continue;
1610             }
1611             if (surfaceChild->IsMainWindowType()) {
1612                 rect = rect.JoinRect(surfaceChild->GetOldDirtyInSurface());
1613                 continue;
1614             }
1615         }
1616     }
1617     node.SetUifirstChildrenDirtyRectParam(rect);
1618 }
1619 
ProcessTreeStateChange(RSSurfaceRenderNode & node)1620 void RSUifirstManager::ProcessTreeStateChange(RSSurfaceRenderNode& node)
1621 {
1622     RSUifirstManager::Instance().CheckCurrentFrameHasCardNodeReCreate(node);
1623     // Planning: do not clear complete image for card
1624     if (node.IsOnTheTree()) {
1625         return;
1626     }
1627     RSUifirstManager::Instance().DisableUifirstNode(node);
1628     RSUifirstManager::Instance().ForceClearSubthreadRes();
1629     RSUifirstManager::Instance().RemoveCardNodes(node.GetId());
1630 }
1631 
DisableUifirstNode(RSSurfaceRenderNode & node)1632 void RSUifirstManager::DisableUifirstNode(RSSurfaceRenderNode& node)
1633 {
1634     RS_TRACE_NAME_FMT("DisableUifirstNode node[%lld] %s", node.GetId(), node.GetName().c_str());
1635     UifirstStateChange(node, MultiThreadCacheType::NONE);
1636 
1637     auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.shared_from_this());
1638     pindingResetWindowCachedNodes_.emplace_back(surfaceNode);
1639 }
1640 
AddCapturedNodes(NodeId id)1641 void RSUifirstManager::AddCapturedNodes(NodeId id)
1642 {
1643     capturedNodes_.push_back(id);
1644 }
1645 
ResetCurrentFrameDeletedCardNodes()1646 void RSUifirstManager::ResetCurrentFrameDeletedCardNodes()
1647 {
1648     currentFrameDeletedCardNodes_.clear();
1649     isCurrentFrameHasCardNodeReCreate_ = false;
1650 }
1651 
CheckCurrentFrameHasCardNodeReCreate(const RSSurfaceRenderNode & node)1652 void RSUifirstManager::CheckCurrentFrameHasCardNodeReCreate(const RSSurfaceRenderNode& node)
1653 {
1654     if (node.GetSurfaceNodeType() != RSSurfaceNodeType::ABILITY_COMPONENT_NODE ||
1655         node.GetName().find(ARKTSCARDNODE_NAME) == std::string::npos) {
1656         return;
1657     }
1658     if (!node.IsOnTheTree()) {
1659         currentFrameDeletedCardNodes_.emplace_back(node.GetId());
1660     } else if (std::find(currentFrameDeletedCardNodes_.begin(), currentFrameDeletedCardNodes_.end(),
1661         node.GetId()) != currentFrameDeletedCardNodes_.end()) {
1662         isCurrentFrameHasCardNodeReCreate_ = true;
1663     }
1664 }
1665 
GetUiFirstMode()1666 UiFirstModeType RSUifirstManager::GetUiFirstMode()
1667 {
1668     if (uifirstType_ == UiFirstCcmType::SINGLE) {
1669         return UiFirstModeType::SINGLE_WINDOW_MODE;
1670     }
1671     if (uifirstType_ == UiFirstCcmType::MULTI) {
1672         return UiFirstModeType::MULTI_WINDOW_MODE;
1673     }
1674     if (uifirstType_ == UiFirstCcmType::HYBRID) {
1675         return isFreeMultiWindowEnabled_ ? UiFirstModeType::MULTI_WINDOW_MODE : UiFirstModeType::SINGLE_WINDOW_MODE;
1676     }
1677     return UiFirstModeType::SINGLE_WINDOW_MODE;
1678 }
1679 
ReadUIFirstCcmParam()1680 void RSUifirstManager::ReadUIFirstCcmParam()
1681 {
1682     auto uifirstFeature = GraphicFeatureParamManager::GetInstance().GetFeatureParam("UIFirstConfig");
1683     std::shared_ptr<UIFirstParam> uifirstParam = std::make_shared<UIFirstParam>();
1684     isUiFirstOn_ = uifirstParam->IsUIFirstEnable();
1685     isCardUiFirstOn_ = uifirstParam->IsCardUIFirstEnable();
1686     SetUiFirstType(uifirstParam->GetUIFirstType());
1687     auto param = std::static_pointer_cast<UIFirstParam>(uifirstFeature);
1688     if (param) {
1689         isUiFirstOn_ = param->IsUIFirstEnable();
1690         isCardUiFirstOn_ = param->IsCardUIFirstEnable();
1691         SetUiFirstType(param->GetUIFirstType());
1692         RS_LOGI("RSUifirstManager::ReadUIFirstCcmParam isUiFirstOn_=%{public}d isCardUiFirstOn_=%{public}d"
1693             " uifirstType_=%{public}d", isUiFirstOn_, isCardUiFirstOn_, (int)uifirstType_);
1694     }
1695 }
1696 
SetUiFirstType(int type)1697 void RSUifirstManager::SetUiFirstType(int type)
1698 {
1699     if (type < (int)UiFirstCcmType::SINGLE || type > (int)UiFirstCcmType::HYBRID) {
1700         return;
1701     }
1702     if (type == (int)UiFirstCcmType::SINGLE) {
1703         uifirstType_ = UiFirstCcmType::SINGLE;
1704     } else if (type == (int)UiFirstCcmType::MULTI) {
1705         uifirstType_ = UiFirstCcmType::MULTI;
1706     } else if (type == (int)UiFirstCcmType::HYBRID) {
1707         uifirstType_ = UiFirstCcmType::HYBRID;
1708     }
1709 }
1710 
CheckMatchAndWaitNotify(const RSRenderParams & params,bool checkMatch)1711 bool RSUiFirstProcessStateCheckerHelper::CheckMatchAndWaitNotify(const RSRenderParams& params, bool checkMatch)
1712 {
1713     if (checkMatch && IsCurFirstLevelMatch(params)) {
1714         return true;
1715     }
1716     return CheckAndWaitPreFirstLevelDrawableNotify(params);
1717 }
1718 
CheckAndWaitPreFirstLevelDrawableNotify(const RSRenderParams & params)1719 bool RSUiFirstProcessStateCheckerHelper::CheckAndWaitPreFirstLevelDrawableNotify(const RSRenderParams& params)
1720 {
1721     auto firstLevelNodeId = params.GetFirstLevelNodeId();
1722     auto uifirstRootNodeId = params.GetUifirstRootNodeId();
1723     auto rootId = uifirstRootNodeId != INVALID_NODEID ? uifirstRootNodeId : firstLevelNodeId;
1724     if (rootId == INVALID_NODEID) {
1725         /* uifirst will not draw with no firstlevel node, and there's no need to check and wait for uifirst onDraw */
1726         RS_LOGW("uifirst node %{public}" PRIu64 " uifirstrootNodeId is INVALID_NODEID", params.GetId());
1727         return true;
1728     }
1729 
1730     auto uifirstRootNodeDrawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(rootId);
1731     if (!uifirstRootNodeDrawable) {
1732         // drawable may release when node off tree
1733         // uifirst will not draw with null uifirstRootNodeDrawable
1734         RS_LOGW("uifirstnode %{public}" PRIu64 " uifirstroot %{public}" PRIu64 " nullptr", params.GetId(), rootId);
1735         return true;
1736     }
1737 
1738     if (UNLIKELY(uifirstRootNodeDrawable->GetNodeType() != RSRenderNodeType::SURFACE_NODE)) {
1739         RS_LOGE("uifirst invalid uifirstrootNodeId %{public}" PRIu64, rootId);
1740         return false;
1741     }
1742     auto uifirstRootSurfaceNodeDrawable =
1743         std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(uifirstRootNodeDrawable);
1744 
1745     RS_TRACE_NAME_FMT("CheckAndWaitPreFirstLevelDrawableNotify %" PRIu64 " wait for %" PRIu64 "",
1746         params.GetId(), uifirstRootSurfaceNodeDrawable->GetId());
1747 
1748     static constexpr auto TIME_OUT = std::chrono::milliseconds(500); // 500ms for timeout
1749     auto pred = [uifirstRootSurfaceNodeDrawable] {
1750         auto curState = uifirstRootSurfaceNodeDrawable->GetCacheSurfaceProcessedStatus();
1751         return curState == CacheProcessStatus::DONE || curState == CacheProcessStatus::UNKNOWN ||
1752             curState == CacheProcessStatus::SKIPPED;
1753     };
1754     std::unique_lock<std::mutex> lock(notifyMutex_);
1755     notifyCv_.wait_for(lock, TIME_OUT, pred);
1756     auto ret = pred();
1757     if (!ret) {
1758         RS_LOGE("uifirst nodeId %{public}" PRIu64
1759             " wait uifirstrootNodeId %{public}" PRIu64 " until 500ms timeout", params.GetId(), rootId);
1760     }
1761     return ret;
1762 }
1763 
IsCurFirstLevelMatch(const RSRenderParams & params)1764 bool RSUiFirstProcessStateCheckerHelper::IsCurFirstLevelMatch(const RSRenderParams& params)
1765 {
1766     auto uifirstRootNodeId = params.GetUifirstRootNodeId();
1767     auto firstLevelNodeId = params.GetFirstLevelNodeId();
1768 
1769     RS_OPTIONAL_TRACE_NAME_FMT("RSUiFirstProcessStateCheckerHelper IsCurFirstLevelMatch In node[%"
1770         PRIu64 "  %" PRIu64"] cur[%" PRIu64 "  %" PRIu64 "] in nodeId[%" PRIu64 "]",
1771         uifirstRootNodeId, firstLevelNodeId, curUifirstRootNodeId_, curFirstLevelNodeId_, params.GetId());
1772 
1773     if (curUifirstRootNodeId_ == INVALID_NODEID && curFirstLevelNodeId_ == INVALID_NODEID) {
1774         // should draw because uifirst may not inited
1775         return true;
1776     }
1777     auto uiFirstCheckRet = uifirstRootNodeId == curUifirstRootNodeId_ && curUifirstRootNodeId_ != INVALID_NODEID;
1778     auto firstLevelCheckRet = firstLevelNodeId == curFirstLevelNodeId_ && curFirstLevelNodeId_ != INVALID_NODEID;
1779     if (uiFirstCheckRet || firstLevelCheckRet) {
1780         return true;
1781     }
1782     return false;
1783 }
1784 
IsSubTreeNeedPrepareForSnapshot(RSSurfaceRenderNode & node)1785 bool RSUifirstManager::IsSubTreeNeedPrepareForSnapshot(RSSurfaceRenderNode& node)
1786 {
1787     return RSUifirstManager::Instance().IsRecentTaskScene() &&
1788         (node.IsFocusedNode(RSMainThread::Instance()->GetFocusLeashWindowId()) ||
1789         node.IsFocusedNode(RSMainThread::Instance()->GetFocusNodeId()));
1790 }
1791 
IsSubHighPriorityType(RSSurfaceRenderNode & node) const1792 bool RSUifirstManager::IsSubHighPriorityType(RSSurfaceRenderNode& node) const
1793 {
1794     return node.GetName().find("hipreview") != std::string::npos;
1795 }
1796 
CheckHwcChildrenType(RSSurfaceRenderNode & node,SurfaceHwcNodeType & enabledType)1797 void RSUifirstManager::CheckHwcChildrenType(RSSurfaceRenderNode& node, SurfaceHwcNodeType& enabledType)
1798 {
1799     if (enabledType == SurfaceHwcNodeType::DEFAULT_HWC_ROSENWEB) {
1800         return;
1801     }
1802     if (node.IsAppWindow()) {
1803         auto hwcNodes = node.GetChildHardwareEnabledNodes();
1804         if (hwcNodes.empty()) {
1805             return;
1806         }
1807         if (IsSubHighPriorityType(node)) {
1808             enabledType = SurfaceHwcNodeType::DEFAULT_HWC_VIDEO;
1809             return;
1810         }
1811         if (node.IsRosenWeb()) {
1812             enabledType = SurfaceHwcNodeType::DEFAULT_HWC_ROSENWEB;
1813             return;
1814         }
1815         for (auto hwcNode : hwcNodes) {
1816             auto hwcNodePtr = hwcNode.lock();
1817             if (!hwcNodePtr) {
1818                 continue;
1819             }
1820             if (hwcNodePtr->IsRosenWeb()) {
1821                 enabledType = SurfaceHwcNodeType::DEFAULT_HWC_ROSENWEB;
1822                 return;
1823             }
1824             if (IsSubHighPriorityType(*hwcNodePtr)) {
1825                 enabledType = SurfaceHwcNodeType::DEFAULT_HWC_VIDEO;
1826                 return;
1827             }
1828         }
1829     } else if (node.IsLeashWindow()) {
1830         for (auto& child : *(node.GetChildren())) {
1831             auto surfaceNode = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1832             if (surfaceNode == nullptr) {
1833                 continue;
1834             }
1835             CheckHwcChildrenType(*surfaceNode, enabledType);
1836         }
1837     }
1838 }
1839 
MarkSubHighPriorityType(RSSurfaceRenderNode & node)1840 void RSUifirstManager::MarkSubHighPriorityType(RSSurfaceRenderNode& node)
1841 {
1842     if (uifirstType_ != UiFirstCcmType::MULTI) {
1843         return;
1844     }
1845     SurfaceHwcNodeType preSubHighPriority = SurfaceHwcNodeType::DEFAULT_HWC_TYPE;
1846     CheckHwcChildrenType(node, preSubHighPriority);
1847     RS_OPTIONAL_TRACE_NAME_FMT("SubHighPriorityType::name:[%s] preSub:%d", node.GetName().c_str(), preSubHighPriority);
1848     node.SetPreSubHighPriorityType(preSubHighPriority == SurfaceHwcNodeType::DEFAULT_HWC_VIDEO);
1849 }
1850 } // namespace Rosen
1851 } // namespace OHOS
1852