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