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