1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "rs_sub_thread_cache.h"
17 #include "rs_trace.h"
18
19 #include "common/rs_common_hook.h"
20 #include "common/rs_optional_trace.h"
21 #include "display_engine/rs_luminance_control.h"
22 #include "drawable/rs_surface_render_node_drawable.h"
23 #include "feature/uifirst/rs_sub_thread_manager.h"
24 #include "feature/uifirst/rs_uifirst_manager.h"
25 #include "feature/uifirst/rs_uifirst_frame_rate_control.h"
26 #include "feature_cfg/graphic_feature_param_manager.h"
27 #include "memory/rs_memory_manager.h"
28 #include "params/rs_screen_render_params.h"
29 #include "pipeline/render_thread/rs_uni_render_util.h"
30 #include "pipeline/rs_canvas_render_node.h"
31 #include "pipeline/rs_root_render_node.h"
32 #include "pipeline/main_thread/rs_main_thread.h"
33 #include "platform/common/rs_log.h"
34
35 #undef LOG_TAG
36 #define LOG_TAG "RSUifirstManager"
37
38 // use in mainthread, post subthread, not affect renderthread
39 namespace OHOS {
40 namespace Rosen {
41 namespace {
42 constexpr int EVENT_START_TIMEOUT = 500;
43 constexpr int EVENT_STOP_TIMEOUT = 150;
44 constexpr int EVENT_DISABLE_UIFIRST_GAP = 100;
45 constexpr int CLEAR_CACHE_DELAY = 400;
46 const std::string CLEAR_CACHE_TASK_PREFIX = "uifirst_clear_cache_";
47 constexpr std::string_view ARKTSCARDNODE_NAME = "ArkTSCardNode";
48 constexpr std::string_view EVENT_DISABLE_UIFIRST = "APP_LIST_FLING";
49 constexpr int UIFIRST_TASKSKIP_PRIO_THRESHOLD = 3;
50 constexpr int UIFIRST_POSTTASK_HIGHPRIO_MAX = 6;
51 constexpr int SUBTHREAD_CONTROL_FRAMERATE_NODE_LIMIT = 10;
52 constexpr int CACHED_SURFACE_IS_TRANSPARENT = 0;
GetCurSysTime()53 inline int64_t GetCurSysTime()
54 {
55 auto curTime = std::chrono::system_clock::now().time_since_epoch();
56 return std::chrono::duration_cast<std::chrono::milliseconds>(curTime).count();
57 }
58 };
59
Instance()60 RSUifirstManager& RSUifirstManager::Instance()
61 {
62 static RSUifirstManager instance; // store in mainthread instance ?
63 return instance;
64 }
65
GetSurfaceDrawableByID(NodeId id)66 std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> RSUifirstManager::GetSurfaceDrawableByID(NodeId id)
67 {
68 if (const auto cacheIt = subthreadProcessingNode_.find(id); cacheIt != subthreadProcessingNode_.end()) {
69 const auto ptr = cacheIt->second;
70 if (ptr && ptr->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
71 return std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(ptr);
72 }
73 }
74 // unlikely
75 auto ptr = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
76 if (ptr && ptr->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
77 return std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(ptr);
78 }
79 return nullptr;
80 }
81
SetUifirstNodeEnableParam(RSSurfaceRenderNode & node,MultiThreadCacheType type)82 bool RSUifirstManager::SetUifirstNodeEnableParam(RSSurfaceRenderNode& node, MultiThreadCacheType type)
83 {
84 auto ret = node.SetUifirstNodeEnableParam(type); // update drawable param
85 auto isType = type == MultiThreadCacheType::LEASH_WINDOW || type == MultiThreadCacheType::NONFOCUS_WINDOW;
86 if (node.IsLeashWindow() && type != MultiThreadCacheType::ARKTS_CARD) {
87 for (auto& child : *(node.GetChildren())) {
88 if (!child) {
89 continue;
90 }
91 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
92 if (!surfaceChild) {
93 continue;
94 }
95 if (surfaceChild->IsMainWindowType()) {
96 surfaceChild->SetIsParentUifirstNodeEnableParam(isType);
97 continue;
98 }
99 }
100 }
101 return ret;
102 }
103
104 // unref in sub when cache done
AddProcessDoneNode(NodeId id)105 void RSUifirstManager::AddProcessDoneNode(NodeId id)
106 {
107 // mutex
108 if (id == INVALID_NODEID) {
109 return;
110 }
111 RS_OPTIONAL_TRACE_NAME_FMT("sub done %" PRIu64"", id);
112 std::lock_guard<std::mutex> lock(childernDrawableMutex_);
113 subthreadProcessDoneNode_.push_back(id);
114 }
115
AddProcessSkippedNode(NodeId id)116 void RSUifirstManager::AddProcessSkippedNode(NodeId id)
117 {
118 if (id == INVALID_NODEID) {
119 return;
120 }
121 RS_OPTIONAL_TRACE_NAME_FMT("sub skipped %" PRIu64, id);
122 std::lock_guard<std::mutex> lock(skippedNodeMutex_);
123 subthreadProcessSkippedNode_.insert(id);
124 }
125
NeedNextDrawForSkippedNode()126 bool RSUifirstManager::NeedNextDrawForSkippedNode()
127 {
128 std::lock_guard<std::mutex> lock(skippedNodeMutex_);
129 return !subthreadProcessSkippedNode_.empty();
130 }
131
ResetUifirstNode(std::shared_ptr<RSSurfaceRenderNode> & nodePtr)132 void RSUifirstManager::ResetUifirstNode(std::shared_ptr<RSSurfaceRenderNode>& nodePtr)
133 {
134 if (!nodePtr) {
135 return;
136 }
137 RS_TRACE_NAME_FMT("ResetUifirstNode name:%s,id:%" PRIu64 ",isOnTheTree:%d,"
138 "toBeCaptured:%d", nodePtr->GetName().c_str(), nodePtr->GetId(), nodePtr->IsOnTheTree(),
139 nodePtr->IsNodeToBeCaptured());
140 RS_LOGI("ResetUifirstNode name:%{public}s,id:%{public}" PRIu64 ",isOnTheTree:%{public}d,"
141 "toBeCaptured:%{public}d", nodePtr->GetName().c_str(), nodePtr->GetId(), nodePtr->IsOnTheTree(),
142 nodePtr->IsNodeToBeCaptured());
143 pendingPostNodes_.erase(nodePtr->GetId());
144 pendingPostCardNodes_.erase(nodePtr->GetId());
145 nodePtr->SetUifirstUseStarting(false);
146 if (SetUifirstNodeEnableParam(*nodePtr, MultiThreadCacheType::NONE)) {
147 // enable ->disable
148 SetNodeNeedForceUpdateFlag(true);
149 pendingForceUpdateNode_.push_back(nodePtr->GetId());
150 }
151 RSMainThread::Instance()->GetContext().AddPendingSyncNode(nodePtr);
152
153 auto drawable = GetSurfaceDrawableByID(nodePtr->GetId());
154 if (!drawable) {
155 return;
156 }
157 auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
158 if (!nodePtr->IsOnTheTree() && nodePtr->IsNodeToBeCaptured()) {
159 rsSubThreadCache.ResetUifirst(true);
160 auto taskName = CLEAR_CACHE_TASK_PREFIX + std::to_string(nodePtr->GetId());
161 auto releaseTask = [drawable] {
162 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
163 if (surfaceParams && surfaceParams->GetUifirstNodeEnableParam() == MultiThreadCacheType::NONE) {
164 RS_TRACE_NAME_FMT("ResetUifirstNode clearCache id:%llu", surfaceParams->GetId());
165 drawable->GetRsSubThreadCache().ResetUifirst();
166 }
167 };
168 RSUniRenderThread::Instance().PostTask(releaseTask, taskName, CLEAR_CACHE_DELAY);
169 } else {
170 nodePtr->SetIsNodeToBeCaptured(false);
171 rsSubThreadCache.ResetUifirst();
172 }
173 }
174
ResetWindowCache(std::shared_ptr<RSSurfaceRenderNode> & nodePtr)175 void RSUifirstManager::ResetWindowCache(std::shared_ptr<RSSurfaceRenderNode>& nodePtr)
176 {
177 if (!nodePtr) {
178 RS_LOGE("ResetWindowCache nodePtr is null");
179 return;
180 }
181 auto drawable = GetSurfaceDrawableByID(nodePtr->GetId());
182 if (!drawable) {
183 RS_LOGE("ResetWindowCache drawable is null");
184 return;
185 }
186 // run in RT thread
187 drawable->GetRsSubThreadCache().ResetWindowCache();
188 }
189
MergeOldDirty(NodeId id)190 void RSUifirstManager::MergeOldDirty(NodeId id)
191 {
192 if (!mainThread_) {
193 return;
194 }
195 auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
196 mainThread_->GetContext().GetNodeMap().GetRenderNode(id));
197 if (!node) {
198 return;
199 }
200 if (node->IsAppWindow() &&
201 !RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node->GetParent().lock())) {
202 auto& curDirtyManager = node->GetDirtyManagerForUifirst();
203 if (curDirtyManager) {
204 curDirtyManager->SetUifirstFrameDirtyRect(node->GetOldDirty());
205 }
206 return;
207 }
208 bool hasAppWindow = false;
209 for (auto& child : * node-> GetSortedChildren()) {
210 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
211 if (surfaceNode && surfaceNode->IsAppWindow()) {
212 hasAppWindow = true;
213 auto& curDirtyManager = surfaceNode->GetDirtyManagerForUifirst();
214 if (curDirtyManager) {
215 curDirtyManager->SetUifirstFrameDirtyRect(surfaceNode->GetOldDirty());
216 }
217 break;
218 }
219 }
220 if (!hasAppWindow) {
221 auto& curDirtyManager = node->GetDirtyManagerForUifirst();
222 if (curDirtyManager) {
223 curDirtyManager->SetUifirstFrameDirtyRect(node->GetOldDirty());
224 }
225 }
226 }
227
MergeOldDirtyToDirtyManager(std::shared_ptr<RSSurfaceRenderNode> & node)228 void RSUifirstManager::MergeOldDirtyToDirtyManager(std::shared_ptr<RSSurfaceRenderNode>& node)
229 {
230 auto& curDirtyManager = node->GetDirtyManagerForUifirst();
231 if (!curDirtyManager) {
232 RS_LOGE("MergeOldDirtyToDirtyManager curDirtyManager is nullptr");
233 return;
234 }
235 auto curDirtyRegion = curDirtyManager->GetCurrentFrameDirtyRegion();
236 auto uifirstDirtyRegion = curDirtyManager->GetUifirstFrameDirtyRegion();
237 curDirtyManager->MergeDirtyRect(uifirstDirtyRegion);
238 curDirtyManager->SetUifirstFrameDirtyRect(curDirtyRegion);
239 RS_OPTIONAL_TRACE_NAME_FMT("MergeOldDirtyToDirtyManager %" PRIu64","
240 " curDirtyRegion[%d %d %d %d], uifirstDirtyRegion[%d %d %d %d]",
241 node->GetId(), curDirtyRegion.left_, curDirtyRegion.top_, curDirtyRegion.width_, curDirtyRegion.height_,
242 uifirstDirtyRegion.left_, uifirstDirtyRegion.top_, uifirstDirtyRegion.width_, uifirstDirtyRegion.height_);
243 if (!uifirstDirtyRegion.IsEmpty()) {
244 node->AddToPendingSyncList();
245 }
246 }
247
RenderGroupUpdate(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable)248 void RSUifirstManager::RenderGroupUpdate(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable)
249 {
250 if (mainThread_ == nullptr) {
251 return;
252 }
253 auto nodeSp = mainThread_->GetContext().GetNodeMap().GetRenderNode(drawable->GetId());
254 if (nodeSp == nullptr) {
255 return;
256 }
257 auto surfaceNode = std::static_pointer_cast<const RSSurfaceRenderNode>(nodeSp);
258 if (surfaceNode == nullptr) {
259 return;
260 }
261 // mark all parent rendergroup need update; planning: mark autoCache need update
262 auto node = surfaceNode->GetParent().lock();
263
264 while (node != nullptr) {
265 if (node->GetType() == RSRenderNodeType::SCREEN_NODE) {
266 break;
267 }
268 if (node->IsSuggestedDrawInGroup()) {
269 RS_OPTIONAL_TRACE_NAME_FMT("cache_changed by uifirst card %" PRIu64"", node->GetId());
270 node->SetDrawingCacheChanged(true);
271 node->AddToPendingSyncList();
272 }
273 node = node->GetParent().lock();
274 }
275 }
276
ProcessForceUpdateNode()277 void RSUifirstManager::ProcessForceUpdateNode()
278 {
279 if (!mainThread_) {
280 return;
281 }
282 std::vector<std::shared_ptr<RSRenderNode>> toDirtyNodes;
283 for (auto id : pendingForceUpdateNode_) {
284 auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(id);
285 if (!node || node->GetLastFrameUifirstFlag() != MultiThreadCacheType::ARKTS_CARD) {
286 continue;
287 }
288 toDirtyNodes.push_back(node);
289 if (!node->IsDirty() && !node->IsSubTreeDirty()) {
290 markForceUpdateByUifirst_.push_back(node);
291 node->SetForceUpdateByUifirst(true);
292 }
293 }
294 for (auto& node : toDirtyNodes) {
295 node->SetDirty(true);
296 }
297 pendingForceUpdateNode_.clear();
298 }
299
NotifyUIStartingWindow(NodeId id,bool wait)300 void RSUifirstManager::NotifyUIStartingWindow(NodeId id, bool wait)
301 {
302 if (mainThread_ == nullptr) {
303 return;
304 }
305 auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
306 mainThread_->GetContext().GetNodeMap().GetRenderNode(id));
307 if (node == nullptr || !node->IsLeashWindow()) {
308 return;
309 }
310 for (auto& child : *node->GetChildren()) {
311 if (!child) {
312 continue;
313 }
314 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
315 if (surfaceChild && surfaceChild->IsMainWindowType()) {
316 surfaceChild->SetWaitUifirstFirstFrame(wait);
317 }
318 }
319 }
320
ProcessDoneNodeInner()321 void RSUifirstManager::ProcessDoneNodeInner()
322 {
323 std::vector<NodeId> tmp;
324 {
325 std::lock_guard<std::mutex> lock(childernDrawableMutex_);
326 if (subthreadProcessDoneNode_.size() == 0) {
327 return;
328 }
329 std::swap(tmp, subthreadProcessDoneNode_);
330 }
331 RS_TRACE_NAME_FMT("ProcessDoneNode num:%d", tmp.size());
332 for (auto& id : tmp) {
333 RS_OPTIONAL_TRACE_NAME_FMT("Done %" PRIu64"", id);
334 auto drawable = GetSurfaceDrawableByID(id);
335 if (drawable && drawable->GetRsSubThreadCache().GetCacheSurfaceNeedUpdated() &&
336 drawable->GetRsSubThreadCache().CheckCacheSurface()) {
337 drawable->GetRsSubThreadCache().UpdateCompletedCacheSurface();
338 RenderGroupUpdate(drawable);
339 SetNodeNeedForceUpdateFlag(true);
340 pendingForceUpdateNode_.push_back(id);
341 }
342 NotifyUIStartingWindow(id, false);
343 subthreadProcessingNode_.erase(id);
344 }
345 }
346
ProcessSkippedNode()347 void RSUifirstManager::ProcessSkippedNode()
348 {
349 std::unordered_set<NodeId> tmp;
350 {
351 std::lock_guard<std::mutex> lock(skippedNodeMutex_);
352 if (subthreadProcessSkippedNode_.empty()) {
353 return;
354 }
355 std::swap(tmp, subthreadProcessSkippedNode_);
356 }
357 RS_TRACE_NAME_FMT("ProcessSkippedNode num %zu", tmp.size());
358 for (auto& id : tmp) {
359 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
360 mainThread_->GetContext().GetNodeMap().GetRenderNode(id));
361 if (UNLIKELY(!surfaceNode)) {
362 continue;
363 }
364 // If node not on the tree, do not draw it.
365 if (UNLIKELY(!surfaceNode->IsOnTheTree())) {
366 RS_TRACE_NAME_FMT("ProcessSkippedNode %s %" PRIu64 " not OnTheTree", surfaceNode->GetName().c_str(), id);
367 continue;
368 }
369 // If node not enable uifirst, do not draw it in subThread.
370 if (UNLIKELY(surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE)) {
371 RS_TRACE_NAME_FMT("ProcessSkippedNode %s %" PRIu64 " disabled", surfaceNode->GetName().c_str(), id);
372 continue;
373 }
374 if (surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD) {
375 if (pendingPostCardNodes_.find(id) == pendingPostCardNodes_.end()) {
376 pendingPostCardNodes_.emplace(id, surfaceNode);
377 surfaceNode->SetForceDrawWithSkipped(true);
378 RS_TRACE_NAME_FMT("ProcessSkippedCardNode %" PRIu64 " added", id);
379 RS_LOGI("ProcessSkippedCardNode %{public}" PRIu64 " added", id);
380 }
381 } else {
382 if (pendingPostNodes_.find(id) == pendingPostNodes_.end()) {
383 pendingPostNodes_.emplace(id, surfaceNode);
384 surfaceNode->SetForceDrawWithSkipped(true);
385 RS_TRACE_NAME_FMT("ProcessSkippedNode %s %" PRIu64 " Type %d added", surfaceNode->GetName().c_str(), id,
386 static_cast<int>(surfaceNode->GetLastFrameUifirstFlag()));
387 }
388 }
389 }
390 }
391
ProcessDoneNode()392 void RSUifirstManager::ProcessDoneNode()
393 {
394 #ifdef RS_ENABLE_PREFETCH
395 __builtin_prefetch(&pendingResetNodes_, 0, 1);
396 #endif
397 SetNodeNeedForceUpdateFlag(false);
398 ProcessDoneNodeInner();
399
400 // reset node when node is not doing
401 for (auto it = capturedNodes_.begin(); it != capturedNodes_.end();) {
402 if (mainThread_ && subthreadProcessingNode_.find(*it) == subthreadProcessingNode_.end()) {
403 // reset uifirst
404 auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
405 mainThread_->GetContext().GetNodeMap().GetRenderNode(*it));
406 if (node == nullptr) {
407 it = capturedNodes_.erase(it);
408 continue;
409 }
410 node->SetIsNodeToBeCaptured(false);
411 if (node->GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE) {
412 ResetUifirstNode(node);
413 }
414 it = capturedNodes_.erase(it);
415 } else {
416 it++;
417 }
418 }
419 for (auto it = pendingResetNodes_.begin(); it != pendingResetNodes_.end();) {
420 if (subthreadProcessingNode_.find(it->first) == subthreadProcessingNode_.end()) {
421 ResetUifirstNode(it->second);
422 it = pendingResetNodes_.erase(it);
423 } else {
424 it++;
425 }
426 }
427 for (auto& surfaceNode : pendingResetWindowCachedNodes_) {
428 ResetWindowCache(surfaceNode);
429 }
430 pendingResetWindowCachedNodes_.clear();
431
432 for (auto it = subthreadProcessingNode_.begin(); it != subthreadProcessingNode_.end();) {
433 auto id = it->first;
434 auto drawable = GetSurfaceDrawableByID(id);
435 if (!drawable) {
436 ++it;
437 continue;
438 }
439 auto cacheStatus = drawable->GetRsSubThreadCache().GetCacheSurfaceProcessedStatus();
440 if (cacheStatus == CacheProcessStatus::SKIPPED) {
441 it = subthreadProcessingNode_.erase(it);
442 continue;
443 }
444 RS_LOGI("erase processingNode %{public}" PRIu64, id);
445 RS_TRACE_NAME_FMT("erase processingNode %s %" PRIu64, drawable->GetName().c_str(), id);
446 pendingPostNodes_.erase(it->first); // dele doing node in pendingpostlist
447 pendingPostCardNodes_.erase(it->first);
448 // skipped by doing, need update cache because the doing cache is too old
449 RSUifirstManager::Instance().AddProcessSkippedNode(it->first);
450 ++it;
451 }
452 }
453
SyncHDRDisplayParam(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable,const GraphicColorGamut & colorGamut)454 void RSUifirstManager::SyncHDRDisplayParam(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> drawable,
455 const GraphicColorGamut& colorGamut)
456 {
457 #ifdef RS_ENABLE_GPU
458 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
459 if (!surfaceParams || !surfaceParams->GetAncestorScreenNode().lock()) {
460 return;
461 }
462 auto ancestor = surfaceParams->GetAncestorScreenNode().lock()->ReinterpretCastTo<RSScreenRenderNode>();
463 if (!ancestor) {
464 return;
465 }
466 auto screenParams = static_cast<RSScreenRenderParams*>(ancestor->GetRenderParams().get());
467 if (!screenParams) {
468 return;
469 }
470 bool isHdrOn = screenParams->GetHDRPresent();
471 ScreenId id = screenParams->GetScreenId();
472 auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
473 rsSubThreadCache.SetHDRPresent(isHdrOn);
474 bool isScRGBEnable = RSSystemParameters::IsNeedScRGBForP3(screenParams->GetNewColorSpace()) &&
475 GetUiFirstSwitch();
476 bool changeColorSpace = rsSubThreadCache.GetTargetColorGamut() != colorGamut;
477 if (isHdrOn || isScRGBEnable || changeColorSpace) {
478 // When ScRGB or Adaptive P3 is enabled, some operations may cause the window color gamut to change.
479 // In this case, the uifirst cache needs to be cleared.
480 if ((isScRGBEnable || ColorGamutParam::IsAdaptiveColorGamutEnabled()) && changeColorSpace) {
481 RS_LOGI("UIFirstHDR SyncDisplayParam: ColorSpace change, ClearCacheSurface,"
482 "nodeID: [%{public}" PRIu64"]", id);
483 RS_TRACE_NAME_FMT("UIFirstHDR SyncScreenParam: ColorSpace change, ClearCacheSurface,"
484 "nodeID: [%{public}" PRIu64"]", id);
485 drawable->GetRsSubThreadCache().ClearCacheSurfaceInThread();
486 }
487 rsSubThreadCache.SetScreenId(id);
488 rsSubThreadCache.SetTargetColorGamut(colorGamut);
489 }
490 RS_LOGD("UIFirstHDR SyncDisplayParam:%{public}d, ratio:%{public}f", rsSubThreadCache.GetHDRPresent(),
491 surfaceParams->GetBrightnessRatio());
492 #endif
493 }
494
CurSurfaceHasVisibleDirtyRegion(const std::shared_ptr<RSSurfaceRenderNode> & node)495 bool RSUifirstManager::CurSurfaceHasVisibleDirtyRegion(const std::shared_ptr<RSSurfaceRenderNode>& node)
496 {
497 auto visibleRegion = node->GetVisibleRegion();
498 if (visibleRegion.IsEmpty()) {
499 RS_OPTIONAL_TRACE_NAME_FMT("curSurface name:%s id:%" PRIu64" visibleRegion is IsEmpty",
500 node->GetName().c_str(), node->GetId());
501 return false;
502 }
503 auto drawable = node->GetRenderDrawable();
504 if (!drawable) {
505 RS_TRACE_NAME_FMT("node id:%" PRIu64" drawable is nullptr", node->GetId());
506 return true;
507 }
508 auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
509 if (!surfaceDrawable) {
510 RS_TRACE_NAME_FMT("node id:%" PRIu64" surfaceDrawable is nullptr", node->GetId());
511 return true;
512 }
513 auto surfaceDirtyManager = surfaceDrawable->GetSyncDirtyManager();
514 if (!surfaceDirtyManager) {
515 RS_TRACE_NAME_FMT("node id:%" PRIu64" surfaceDirtyManager is nullptr", node->GetId());
516 return true;
517 }
518 auto surfaceDirtyRect = surfaceDirtyManager->GetUifirstFrameDirtyRegion();
519 RS_TRACE_NAME_FMT("uifirstFrameDirtyRegion %" PRIu64", surfaceDirtyRegion[%d %d %d %d]",
520 surfaceDrawable->GetId(),
521 surfaceDirtyRect.left_, surfaceDirtyRect.top_, surfaceDirtyRect.width_, surfaceDirtyRect.height_);
522 Occlusion::Region surfaceDirtyRegion { { surfaceDirtyRect.left_, surfaceDirtyRect.top_,
523 surfaceDirtyRect.GetRight(), surfaceDirtyRect.GetBottom() } };
524 Occlusion::Region surfaceVisibleDirtyRegion = surfaceDirtyRegion.And(visibleRegion);
525 if (surfaceVisibleDirtyRegion.IsEmpty()) {
526 RS_OPTIONAL_TRACE_NAME_FMT("curSurface name:%s id:%" PRIu64" visibleDirtyRegion is IsEmpty",
527 node->GetName().c_str(), node->GetId());
528 return false;
529 }
530 return true;
531 }
532
CheckVisibleDirtyRegionIsEmpty(const std::shared_ptr<RSSurfaceRenderNode> & node)533 bool RSUifirstManager::CheckVisibleDirtyRegionIsEmpty(const std::shared_ptr<RSSurfaceRenderNode>& node)
534 {
535 if (GetUiFirstMode() != UiFirstModeType::MULTI_WINDOW_MODE) {
536 return false;
537 }
538 if (ROSEN_EQ(node->GetGlobalAlpha(), 0.0f) &&
539 RSMainThread::Instance()->GetSystemAnimatedScenes() == SystemAnimatedScenes::LOCKSCREEN_TO_LAUNCHER &&
540 node->IsLeashWindow()) {
541 RS_TRACE_NAME_FMT("Doing LOCKSCREEN_TO_LAUNCHER, fullTransparent node[%s] skips", node->GetName().c_str());
542 return true;
543 }
544 if (node->GetUifirstContentDirty()) {
545 return false;
546 }
547 bool hasSurfaceVisibleDirtyRegion = CurSurfaceHasVisibleDirtyRegion(node);
548 std::vector<std::pair<NodeId, std::weak_ptr<RSSurfaceRenderNode>>> allSubSurfaceNodes;
549 node->GetAllSubSurfaceNodes(allSubSurfaceNodes);
550 for (auto& [id, subSurfaceNode] : allSubSurfaceNodes) {
551 if (hasSurfaceVisibleDirtyRegion) {
552 break;
553 }
554 auto subSurfaceNodePtr = subSurfaceNode.lock();
555 if (!subSurfaceNodePtr) {
556 continue;
557 }
558 hasSurfaceVisibleDirtyRegion =
559 hasSurfaceVisibleDirtyRegion || CurSurfaceHasVisibleDirtyRegion(subSurfaceNodePtr);
560 }
561 RS_TRACE_NAME_FMT("allSurface name:%s id:%" PRIu64" hasSurfaceVisibleDirtyRegion:%d",
562 node->GetName().c_str(), node->GetId(), hasSurfaceVisibleDirtyRegion);
563 if (!hasSurfaceVisibleDirtyRegion) {
564 return true;
565 }
566 return false;
567 }
568
SubThreadControlFrameRate(NodeId id,std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> & drawable,std::shared_ptr<RSSurfaceRenderNode> & node)569 bool RSUifirstManager::SubThreadControlFrameRate(NodeId id,
570 std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable>& drawable,
571 std::shared_ptr<RSSurfaceRenderNode>& node)
572 {
573 if (!RSSystemProperties::GetSubThreadControlFrameRate()) {
574 return false;
575 }
576
577 auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
578 bool hasAvailableTexture = rsSubThreadCache.HasCachedTexture() &&
579 rsSubThreadCache.GetCacheSurfaceAlphaInfo() != CACHED_SURFACE_IS_TRANSPARENT &&
580 rsSubThreadCache.GetCacheSurfaceProcessedNodes() > SUBTHREAD_CONTROL_FRAMERATE_NODE_LIMIT;
581 bool isLeashWindow = node->GetLastFrameUifirstFlag() == MultiThreadCacheType::LEASH_WINDOW;
582
583 return purgeEnable_ && hasAvailableTexture && isLeashWindow &&
584 RSUifirstFrameRateControl::Instance().NeedRSUifirstControlFrameDrop(*node) &&
585 (subthreadProcessingNode_.find(id) == subthreadProcessingNode_.end()) &&
586 !drawable->GetRsSubThreadCache().IsSubThreadSkip();
587 }
588
NeedPurgeByBehindWindow(NodeId id,bool hasTexture,const std::shared_ptr<RSSurfaceRenderNode> & node)589 bool RSUifirstManager::NeedPurgeByBehindWindow(NodeId id, bool hasTexture,
590 const std::shared_ptr<RSSurfaceRenderNode>& node)
591 {
592 if (GetUiFirstMode() != UiFirstModeType::MULTI_WINDOW_MODE) {
593 return false;
594 }
595 if (!RSSystemProperties::GetUIFirstBehindWindowEnabled()) {
596 RS_LOGD("Behind window control framerate switch is off");
597 return false;
598 }
599 bool isBehindWindowOcclusion = IsBehindWindowOcclusion(node);
600 return purgeEnable_ && hasTexture &&
601 node->GetLastFrameUifirstFlag() == MultiThreadCacheType::NONFOCUS_WINDOW && isBehindWindowOcclusion;
602 }
603
HandlePurgeBehindWindow(std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>>::iterator & it,std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>> & pendingNode)604 void RSUifirstManager::HandlePurgeBehindWindow(
605 std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>::iterator& it,
606 std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>& pendingNode)
607 {
608 auto id = it->first;
609 auto node = it->second;
610 uint64_t currentTime = GetMainThreadVsyncTime();
611 uint64_t timeDiffInMilliseconds = GetTimeDiffBehindWindow(currentTime, id);
612 // control the frequency of purge as the designed time
613 if (timeDiffInMilliseconds >= PURGE_BEHIND_WINDOW_TIME || pendingNodeBehindWindow_[id].isFirst) {
614 ++it;
615 pendingNodeBehindWindow_[id].curTime = currentTime;
616 pendingNodeBehindWindow_[id].isFirst = false;
617 RS_OPTIONAL_TRACE_NAME_FMT("Don't Purge by behind window %s", node->GetName().c_str());
618 } else {
619 RS_TRACE_NAME_FMT("Purge by behind window %s", node->GetName().c_str());
620 it = pendingNode.erase(it);
621 }
622 }
623
DoPurgePendingPostNodes(std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>> & pendingNode)624 void RSUifirstManager::DoPurgePendingPostNodes(std::unordered_map<NodeId,
625 std::shared_ptr<RSSurfaceRenderNode>>& pendingNode)
626 {
627 for (auto it = pendingNode.begin(); it != pendingNode.end();) {
628 auto id = it->first;
629 auto drawable = GetSurfaceDrawableByID(id);
630 auto node = it->second;
631 if (!drawable || !node) {
632 ++it;
633 continue;
634 }
635 auto forceDraw = node->GetForceDrawWithSkipped();
636 node->SetForceDrawWithSkipped(false);
637 SyncHDRDisplayParam(drawable, node->GetFirstLevelNodeColorGamut());
638 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
639 if (!surfaceParams) {
640 ++it;
641 continue;
642 }
643
644 if (!node->IsOnTheTree() && subthreadProcessingNode_.find(id) == subthreadProcessingNode_.end()) {
645 it = pendingNode.erase(it);
646 continue;
647 }
648
649 if (forceDraw) {
650 RS_TRACE_NAME_FMT("Purge GetForceDrawWithSkipped name: %s %" PRIu64,
651 surfaceParams->GetName().c_str(), drawable->GetId());
652 ++it;
653 continue;
654 }
655
656 auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
657 bool staticContent = surfaceParams->GetSurfaceCacheContentStatic();
658 RS_TRACE_NAME_FMT("Purge node name: %s, PurgeEnable:%d, HasCachedTexture:%d, staticContent: %d %" PRIu64,
659 surfaceParams->GetName().c_str(), purgeEnable_,
660 rsSubThreadCache.HasCachedTexture(), staticContent, drawable->GetId());
661 if (purgeEnable_ && rsSubThreadCache.HasCachedTexture() &&
662 (staticContent || CheckVisibleDirtyRegionIsEmpty(node)) &&
663 (subthreadProcessingNode_.find(id) == subthreadProcessingNode_.end()) &&
664 !rsSubThreadCache.IsSubThreadSkip()) {
665 RS_OPTIONAL_TRACE_NAME_FMT("Purge node name %s", surfaceParams->GetName().c_str());
666 it = pendingNode.erase(it);
667 } else if (SubThreadControlFrameRate(id, drawable, node)) {
668 RS_OPTIONAL_TRACE_NAME_FMT("Purge frame drop node name %s", surfaceParams->GetName().c_str());
669 it = pendingNode.erase(it);
670 } else if (NeedPurgeByBehindWindow(id, rsSubThreadCache.HasCachedTexture(), node)) {
671 RS_OPTIONAL_TRACE_NAME_FMT("Decide Whether to Purge node by behind window or not");
672 HandlePurgeBehindWindow(it, pendingNode);
673 } else {
674 ++it;
675 }
676 }
677 }
678
IsBehindWindowOcclusion(const std::shared_ptr<RSSurfaceRenderNode> & node)679 bool RSUifirstManager::IsBehindWindowOcclusion(const std::shared_ptr<RSSurfaceRenderNode>& node)
680 {
681 std::vector<std::pair<NodeId, std::weak_ptr<RSSurfaceRenderNode>>> allSubSurfaceNodes;
682 node->GetAllSubSurfaceNodes(allSubSurfaceNodes);
683 auto nodeVisibleRegion = node->GetVisibleRegion();
684 auto nodeVisibleRegionBehindWindow = node->GetVisibleRegionBehindWindow();
685
686 for (const auto &[subId, subSurfaceNode] : allSubSurfaceNodes) {
687 const auto subNodePtr = subSurfaceNode.lock();
688 if (subNodePtr) {
689 auto visibleRegion = nodeVisibleRegion.OrSelf(subNodePtr->GetVisibleRegion());
690 auto visibleRegionBehindWindow =
691 nodeVisibleRegionBehindWindow.OrSelf(subNodePtr->GetVisibleRegionBehindWindow());
692 RS_OPTIONAL_TRACE_NAME_FMT("visibleRegion is [%s], visibleRegionBehindWindow is [%s]",
693 visibleRegion.GetRegionInfo().c_str(),
694 visibleRegionBehindWindow.GetRegionInfo().c_str());
695
696 if (visibleRegionBehindWindow.IsEmpty() && !visibleRegion.IsEmpty()) {
697 return true;
698 }
699 }
700 }
701 return false;
702 }
703
GetTimeDiffBehindWindow(uint64_t currentTime,NodeId id)704 uint64_t RSUifirstManager::GetTimeDiffBehindWindow(uint64_t currentTime, NodeId id)
705 {
706 uint64_t timeDiff = currentTime - pendingNodeBehindWindow_[id].curTime;
707 RS_OPTIONAL_TRACE_NAME_FMT("timeDiff is %lu", timeDiff);
708 return timeDiff;
709 }
710
GetMainThreadVsyncTime()711 uint64_t RSUifirstManager::GetMainThreadVsyncTime()
712 {
713 uint64_t mainThreadVsyncTime = RSMainThread::Instance()->GetCurrentVsyncTime();
714 uint64_t mainThreadVsyncTimeMS = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(
715 std::chrono::nanoseconds(mainThreadVsyncTime)).count());
716 return mainThreadVsyncTimeMS;
717 }
718
PurgePendingPostNodes()719 void RSUifirstManager::PurgePendingPostNodes()
720 {
721 RS_OPTIONAL_TRACE_NAME_FMT("PurgePendingPostNodes");
722 DoPurgePendingPostNodes(pendingPostNodes_);
723 DoPurgePendingPostNodes(pendingPostCardNodes_);
724 ProcessMarkedNodeSubThreadCache();
725 for (auto& node : markForceUpdateByUifirst_) {
726 node->SetForceUpdateByUifirst(false);
727 }
728 markForceUpdateByUifirst_.clear();
729 for (auto id : pendingForceUpdateNode_) {
730 MergeOldDirty(id);
731 }
732 }
733
PostSubTask(NodeId id)734 void RSUifirstManager::PostSubTask(NodeId id)
735 {
736 RS_TRACE_NAME_FMT("post UpdateCacheSurface %" PRIu64"", id);
737 if (subthreadProcessingNode_.find(id) != subthreadProcessingNode_.end()) { // drawable is doing, do not send
738 RS_TRACE_NAME_FMT("node %" PRIu64" is doing", id);
739 RS_LOGE("RSUifirstManager ERROR: post task twice");
740 return;
741 }
742
743 // 1.find in cache list(done to dele) 2.find in global list
744 auto drawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
745 if (drawable) {
746 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
747 if (surfaceNodeDrawable) {
748 surfaceNodeDrawable->GetRsSubThreadCache().UpdateUifirstDirtyManager(surfaceNodeDrawable.get());
749 }
750 // ref drawable
751 subthreadProcessingNode_.emplace(id, drawable);
752 // post task
753 RS_OPTIONAL_TRACE_NAME_FMT("Post_SubTask_s %" PRIu64"", id);
754 RSSubThreadManager::Instance()->ScheduleRenderNodeDrawable(
755 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable));
756 }
757 }
758
TryReleaseTextureForIdleThread()759 void RSUifirstManager::TryReleaseTextureForIdleThread()
760 {
761 if (noUifirstNodeFrameCount_.load() <= CLEAR_RES_THRESHOLD) {
762 return;
763 }
764 RSSubThreadManager::Instance()->TryReleaseTextureForIdleThread();
765 }
766
PostReleaseCacheSurfaceSubTasks()767 void RSUifirstManager::PostReleaseCacheSurfaceSubTasks()
768 {
769 for (auto& cardNode : collectedCardNodes_) {
770 PostReleaseCacheSurfaceSubTask(cardNode);
771 }
772 }
773
PostReleaseCacheSurfaceSubTask(NodeId id)774 void RSUifirstManager::PostReleaseCacheSurfaceSubTask(NodeId id)
775 {
776 RS_OPTIONAL_TRACE_NAME_FMT("post ReleaseCacheSurface %d", id);
777
778 if (subthreadProcessingNode_.find(id) != subthreadProcessingNode_.end()) { // drawable is doing, do not send
779 RS_TRACE_NAME_FMT("node %" PRIu64" is doing", id);
780 RS_LOGE("RSUifirstManager ERROR: try to clean running node");
781 return;
782 }
783
784 // 1.find in cache list(done to dele) 2.find in global list
785 auto drawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
786 if (drawable) {
787 // post task
788 RS_OPTIONAL_TRACE_NAME_FMT("Post_SubTask_s %" PRIu64"", id);
789 RSSubThreadManager::Instance()->ScheduleReleaseCacheSurfaceOnly(
790 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable));
791 }
792 }
793
UpdateSkipSyncNode()794 void RSUifirstManager::UpdateSkipSyncNode()
795 {
796 processingNodeSkipSync_.clear();
797 processingNodePartialSync_.clear();
798 processingCardNodeSkipSync_.clear();
799 RS_OPTIONAL_TRACE_NAME_FMT("UpdateSkipSyncNode doning%d", subthreadProcessingNode_.size());
800 if (subthreadProcessingNode_.size() == 0) {
801 return;
802 }
803 if (!mainThread_) {
804 return;
805 }
806 for (auto it = subthreadProcessingNode_.begin(); it != subthreadProcessingNode_.end(); it++) {
807 RS_OPTIONAL_TRACE_NAME_FMT("doning%" PRIu64"", it->first);
808 auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(it->first);
809 if (!node) {
810 continue;
811 }
812 auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>();
813 if (!surfaceNode) {
814 continue;
815 }
816 // ArkTSCard
817 if (NodeIsInCardWhiteList(*node)) {
818 if (surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD) {
819 processingCardNodeSkipSync_.insert(it->first);
820 continue;
821 }
822 }
823
824 // leash window
825 processingNodePartialSync_.insert(it->first); // partial sync
826 std::vector<std::pair<NodeId, std::weak_ptr<RSSurfaceRenderNode>>> allSubSurfaceNodes;
827 surfaceNode->GetAllSubSurfaceNodes(allSubSurfaceNodes);
828 for (auto& [id, subSurfaceNode] : allSubSurfaceNodes) {
829 processingNodeSkipSync_.insert(id); // skip sync
830 }
831 }
832 }
833
ProcessSubDoneNode()834 void RSUifirstManager::ProcessSubDoneNode()
835 {
836 RS_OPTIONAL_TRACE_NAME_FMT("ProcessSubDoneNode");
837 ProcessSkippedNode(); // try rescheduale skipped node
838 ProcessDoneNode(); // release finish drawable
839 UpdateSkipSyncNode();
840 RestoreSkipSyncNode();
841 ResetCurrentFrameDeletedCardNodes();
842 }
843
SetUifirstSkipPartialSync(const std::shared_ptr<RSRenderNode> & node,bool needSync)844 static inline void SetUifirstSkipPartialSync(const std::shared_ptr<RSRenderNode> &node, bool needSync)
845 {
846 // node not null in caller
847 if (!needSync) {
848 return;
849 }
850 node->SetUifirstSkipPartialSync(true);
851 }
852
GetUifirstCachedState(NodeId id)853 CacheProcessStatus& RSUifirstManager::GetUifirstCachedState(NodeId id)
854 {
855 auto ret = uifirstCacheState_.insert({ id, CacheProcessStatus::UNKNOWN });
856 auto& curRootIdState = ret.first->second;
857 if (curRootIdState == CacheProcessStatus::UNKNOWN) {
858 /* first time to get the state of uifirstRoot, and cache the state for the remaining other times */
859 auto uifirstRootNodeDrawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(id);
860 if (uifirstRootNodeDrawable && uifirstRootNodeDrawable->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
861 auto drawableNode =
862 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(uifirstRootNodeDrawable);
863 curRootIdState = drawableNode->GetRsSubThreadCache().GetCacheSurfaceProcessedStatus();
864 }
865 }
866 return curRootIdState;
867 }
868
CollectSkipSyncNodeWithDrawableState(const std::shared_ptr<RSRenderNode> & node)869 RSUifirstManager::SkipSyncState RSUifirstManager::CollectSkipSyncNodeWithDrawableState(
870 const std::shared_ptr<RSRenderNode>& node)
871 {
872 auto isPreDoing = IsPreFirstLevelNodeDoingAndTryClear(node);
873 auto drawable = node->GetRenderDrawable();
874 if (UNLIKELY(!drawable || !drawable->GetRenderParams())) {
875 RS_LOGE("CollectSkipSyncNode drawable/params nullptr");
876 // must not be in the DOING state with the invalid drawable.
877 return SkipSyncState::STATE_NOT_SKIP;
878 }
879 auto& params = drawable->GetRenderParams();
880 if (params->GetStartingWindowFlag()) {
881 RS_LOGD("starting node %{public}" PRIu64 " not skipsync", params->GetId());
882 RS_TRACE_NAME_FMT("starting node %" PRIu64 " not skipsync", params->GetId());
883 return SkipSyncState::STATE_NOT_SKIP;
884 }
885 // if node's UifirstRootNodeId is valid (e.g. ArkTsCard), use it first
886 auto uifirstRootId = params->GetUifirstRootNodeId() != INVALID_NODEID ?
887 params->GetUifirstRootNodeId() : params->GetFirstLevelNodeId();
888 auto& curRootIdState = GetUifirstCachedState(uifirstRootId);
889 RS_OPTIONAL_TRACE_NAME_FMT("node[%" PRIu64 " %" PRIu64 "] drawable[%"
890 PRIu64 " %" PRIu64 "] and curNodeId [%" PRIu64"] cacheState[%d]",
891 node->GetStagingRenderParams()->GetUifirstRootNodeId(), node->GetStagingRenderParams()->GetFirstLevelNodeId(),
892 params->GetUifirstRootNodeId(), params->GetFirstLevelNodeId(), node->GetId(), curRootIdState);
893
894 if (curRootIdState == CacheProcessStatus::DOING || curRootIdState == CacheProcessStatus::WAITING ||
895 /* unknow state to check prefirstLevelNode */
896 (uifirstRootId == INVALID_NODEID && isPreDoing)) {
897 pendingSyncForSkipBefore_[uifirstRootId].push_back(node);
898 auto isUifirstRootNode = (uifirstRootId == node->GetId());
899 RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
900 isUifirstRootNode ? "set partial_sync" : "CollectSkipSyncNode", node->GetId(), uifirstRootId);
901 SetUifirstSkipPartialSync(node, isUifirstRootNode);
902 return isUifirstRootNode ? SkipSyncState::STATE_NOT_SKIP : SkipSyncState::STATE_NEED_SKIP;
903 }
904 return SkipSyncState::STATE_NEED_CHECK;
905 }
906
CollectSkipSyncNode(const std::shared_ptr<RSRenderNode> & node)907 CM_INLINE bool RSUifirstManager::CollectSkipSyncNode(const std::shared_ptr<RSRenderNode>& node)
908 {
909 if (!node) {
910 return false;
911 }
912 if (pendingPostNodes_.find(node->GetId()) != pendingPostNodes_.end() ||
913 pendingPostCardNodes_.find(node->GetId()) != pendingPostCardNodes_.end()) {
914 node->SetUifirstSyncFlag(true);
915 }
916
917 auto ret = CollectSkipSyncNodeWithDrawableState(node);
918 if (ret != SkipSyncState::STATE_NEED_CHECK) {
919 return ret == SkipSyncState::STATE_NEED_SKIP;
920 }
921 if (NodeIsInCardWhiteList(*node) && processingCardNodeSkipSync_.count(node->GetUifirstRootNodeId())) {
922 pendingSyncForSkipBefore_[node->GetUifirstRootNodeId()].push_back(node);
923 auto isUifirstRootNode = (node->GetUifirstRootNodeId() == node->GetId());
924 RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
925 isUifirstRootNode ? "set partial_sync card" : "CollectSkipSyncNode card",
926 node->GetId(), node->GetInstanceRootNodeId());
927 SetUifirstSkipPartialSync(node, isUifirstRootNode);
928 return !isUifirstRootNode;
929 }
930 if (processingNodePartialSync_.count(node->GetInstanceRootNodeId()) > 0) {
931 pendingSyncForSkipBefore_[node->GetInstanceRootNodeId()].push_back(node);
932 auto isInstanceRootNode = (node->GetInstanceRootNodeId() == node->GetId());
933 RS_OPTIONAL_TRACE_NAME_FMT("%s %" PRIu64 " root%" PRIu64,
934 isInstanceRootNode ? "set partial_sync" : "CollectSkipSyncNode",
935 node->GetId(), node->GetInstanceRootNodeId());
936 SetUifirstSkipPartialSync(node, isInstanceRootNode);
937 return !isInstanceRootNode;
938 } else if (processingNodeSkipSync_.count(node->GetInstanceRootNodeId()) > 0) {
939 RS_OPTIONAL_TRACE_NAME_FMT("CollectSkipSyncNode root %" PRIu64", node %" PRIu64,
940 node->GetInstanceRootNodeId(), node->GetId());
941 pendingSyncForSkipBefore_[node->GetInstanceRootNodeId()].push_back(node);
942 return true;
943 } else {
944 return false;
945 }
946 }
947
RestoreSkipSyncNode()948 void RSUifirstManager::RestoreSkipSyncNode()
949 {
950 std::vector<NodeId> todele;
951 for (auto& it : pendingSyncForSkipBefore_) {
952 if (processingNodeSkipSync_.count(it.first) == 0 && processingNodePartialSync_.count(it.first) == 0 &&
953 processingCardNodeSkipSync_.count(it.first) == 0) {
954 todele.push_back(it.first);
955 RS_OPTIONAL_TRACE_NAME_FMT("RestoreSkipSyncNode %" PRIu64" num%d", it.first, it.second.size());
956 for (auto& node : it.second) {
957 node->SetUifirstSkipPartialSync(false);
958 node->AddToPendingSyncList();
959 }
960 }
961 }
962 for (auto id : todele) {
963 pendingSyncForSkipBefore_.erase(id);
964 if (!mainThread_) {
965 continue;
966 }
967 auto node = mainThread_->GetContext().GetNodeMap().GetRenderNode(id);
968 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node);
969 if (!surfaceNode) {
970 continue;
971 }
972 if (surfaceNode->GetLastFrameUifirstFlag() == MultiThreadCacheType::ARKTS_CARD &&
973 surfaceNode->GetUifirstRootNodeId() == surfaceNode->GetId() &&
974 pendingPostCardNodes_.find(surfaceNode->GetId()) == pendingPostCardNodes_.end()) {
975 pendingPostCardNodes_[surfaceNode->GetId()] = surfaceNode;
976 RS_OPTIONAL_TRACE_NAME_FMT("RestoreSkipSyncNode AddPendingPostCard %llu", id);
977 }
978 }
979 }
980
ClearSubthreadRes()981 void RSUifirstManager::ClearSubthreadRes()
982 {
983 RS_OPTIONAL_TRACE_NAME_FMT("ClearSubthreadRes");
984 if (subthreadProcessingNode_.size() == 0 &&
985 pendingSyncForSkipBefore_.size() == 0) {
986 noUifirstNodeFrameCount_.fetch_add(1);
987 if (noUifirstNodeFrameCount_.load() == CLEAR_RES_THRESHOLD) {
988 RSSubThreadManager::Instance()->ResetSubThreadGrContext();
989 PostReleaseCacheSurfaceSubTasks();
990 }
991 } else {
992 noUifirstNodeFrameCount_.store(0);
993 }
994 }
995
ForceClearSubthreadRes()996 void RSUifirstManager::ForceClearSubthreadRes()
997 {
998 noUifirstNodeFrameCount_.store(0);
999 RSSubThreadManager::Instance()->ReleaseTexture();
1000 }
1001
IsPreFirstLevelNodeDoingAndTryClear(std::shared_ptr<RSRenderNode> node)1002 bool RSUifirstManager::IsPreFirstLevelNodeDoingAndTryClear(std::shared_ptr<RSRenderNode> node)
1003 {
1004 if (!node) {
1005 return true;
1006 }
1007 auto& preFirstLevelNodeIdSet = node->GetMutablePreFirstLevelNodeIdSet();
1008 for (auto it = preFirstLevelNodeIdSet.begin(); it != preFirstLevelNodeIdSet.end();
1009 it = preFirstLevelNodeIdSet.erase(it)) {
1010 const auto& curRootIdState = GetUifirstCachedState(*it);
1011 if (curRootIdState == CacheProcessStatus::DOING || curRootIdState == CacheProcessStatus::WAITING) {
1012 return true;
1013 }
1014 }
1015 return false;
1016 }
1017
SetNodePriorty(std::list<NodeId> & result,std::unordered_map<NodeId,std::shared_ptr<RSSurfaceRenderNode>> & pendingNode)1018 void RSUifirstManager::SetNodePriorty(std::list<NodeId>& result,
1019 std::unordered_map<NodeId, std::shared_ptr<RSSurfaceRenderNode>>& pendingNode)
1020 {
1021 auto isFocusId = RSMainThread::Instance()->GetFocusNodeId();
1022 auto isLeashId = RSMainThread::Instance()->GetFocusLeashWindowId();
1023 int32_t postOrder = 0;
1024 for (auto& item : pendingNode) {
1025 postOrder++;
1026 auto const& [id, value] = item;
1027 if (IsPreFirstLevelNodeDoingAndTryClear(value)) {
1028 continue;
1029 }
1030 auto drawable = GetSurfaceDrawableByID(id);
1031 if (!drawable) {
1032 continue;
1033 }
1034 auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
1035 if (rsSubThreadCache.HasCachedTexture()) {
1036 rsSubThreadCache.SetRenderCachePriority(NodePriorityType::SUB_LOW_PRIORITY);
1037 } else {
1038 rsSubThreadCache.SetRenderCachePriority(NodePriorityType::SUB_HIGH_PRIORITY);
1039 }
1040 if (rsSubThreadCache.GetCacheSurfaceProcessedStatus() == CacheProcessStatus::WAITING) {
1041 rsSubThreadCache.SetRenderCachePriority(NodePriorityType::SUB_HIGH_PRIORITY);
1042 }
1043 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
1044 if (surfaceParams && surfaceParams->GetPreSubHighPriorityType()) {
1045 rsSubThreadCache.SetRenderCachePriority(NodePriorityType::SUB_VIDEO_PRIORITY);
1046 }
1047 // focusWindow is highest priority.
1048 if (!isFocusNodeFound_) {
1049 if (id == isFocusId || id == isLeashId) {
1050 // for resolving response latency
1051 rsSubThreadCache.SetRenderCachePriority(NodePriorityType::SUB_FOCUSNODE_PRIORITY);
1052 isFocusNodeFound_ = true;
1053 focusNodeThreadIndex_ = rsSubThreadCache.GetLastFrameUsedThreadIndex();
1054 }
1055 }
1056 if (RSSystemProperties::GetUIFirstOptScheduleEnabled() &&
1057 rsSubThreadCache.GetSurfaceSkipCount() >= UIFIRST_TASKSKIP_PRIO_THRESHOLD) {
1058 postOrder += rsSubThreadCache.GetSurfaceSkipPriority();
1059 }
1060 rsSubThreadCache.SetUifirstPostOrder(postOrder);
1061 rsSubThreadCache.SetHighPostPriority(false);
1062 sortedSubThreadNodeIds_.emplace_back(id);
1063 }
1064 RS_TRACE_NAME_FMT("SetNodePriorty result [%zu] pendingNode [%zu]", result.size(), pendingNode.size());
1065 }
1066
SortSubThreadNodesPriority()1067 void RSUifirstManager::SortSubThreadNodesPriority()
1068 {
1069 sortedSubThreadNodeIds_.clear();
1070 isFocusNodeFound_ = false;
1071 focusNodeThreadIndex_ = UINT32_MAX;
1072 SetNodePriorty(sortedSubThreadNodeIds_, pendingPostNodes_);
1073 SetNodePriorty(sortedSubThreadNodeIds_, pendingPostCardNodes_);
1074 RS_LOGD("SetNodePriorty result [%{public}zu] pendingNode [%{public}zu] pendingCardNode [%{public}zu]",
1075 sortedSubThreadNodeIds_.size(), pendingPostNodes_.size(), pendingPostCardNodes_.size());
1076 sortedSubThreadNodeIds_.sort([this](const auto& first, const auto& second) -> bool {
1077 auto drawable1 = GetSurfaceDrawableByID(first);
1078 auto drawable2 = GetSurfaceDrawableByID(second);
1079 if (drawable1 == nullptr || drawable2 == nullptr) {
1080 ROSEN_LOGE("SortSubThreadNodesPriority sort nullptr found in pendingPostNodes_, "
1081 "this should not happen");
1082 return false;
1083 }
1084 auto surfaceParams1 = static_cast<RSSurfaceRenderParams*>(drawable1->GetRenderParams().get());
1085 if (!surfaceParams1) {
1086 RS_LOGE("sortsubthread params1 is nullptr");
1087 return false;
1088 }
1089 auto surfaceParams2 = static_cast<RSSurfaceRenderParams*>(drawable2->GetRenderParams().get());
1090 if (!surfaceParams2) {
1091 RS_LOGE("sortsubthread params2 is nullptr");
1092 return false;
1093 }
1094 auto& rsSubThreadCache1 = drawable1->GetRsSubThreadCache();
1095 auto& rsSubThreadCache2 = drawable2->GetRsSubThreadCache();
1096 if (rsSubThreadCache1.GetRenderCachePriority() == rsSubThreadCache2.GetRenderCachePriority()) {
1097 return rsSubThreadCache1.GetUifirstPostOrder() > rsSubThreadCache2.GetUifirstPostOrder();
1098 } else {
1099 return rsSubThreadCache1.GetRenderCachePriority() < rsSubThreadCache2.GetRenderCachePriority();
1100 }
1101 });
1102 }
1103
MarkPostNodesPriority()1104 void RSUifirstManager::MarkPostNodesPriority()
1105 {
1106 if (!RSSystemProperties::GetUIFirstOptScheduleEnabled()) {
1107 return;
1108 }
1109 int postTaskCount = 0;
1110 for (auto& id : sortedSubThreadNodeIds_) {
1111 auto drawable = GetSurfaceDrawableByID(id);
1112 if (!drawable) {
1113 continue;
1114 }
1115 auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
1116 postTaskCount++;
1117 if (rsSubThreadCache.GetRenderCachePriority() > NodePriorityType::SUB_LOW_PRIORITY) {
1118 rsSubThreadCache.SetHighPostPriority(true);
1119 continue;
1120 }
1121 if (!isFocusNodeFound_) {
1122 if (postTaskCount < UIFIRST_POSTTASK_HIGHPRIO_MAX) {
1123 rsSubThreadCache.SetHighPostPriority(true);
1124 } else {
1125 rsSubThreadCache.SetHighPostPriority(false);
1126 }
1127 } else {
1128 if (focusNodeThreadIndex_ == rsSubThreadCache.GetLastFrameUsedThreadIndex()) {
1129 rsSubThreadCache.SetHighPostPriority(true);
1130 } else {
1131 rsSubThreadCache.SetHighPostPriority(false);
1132 }
1133 }
1134 }
1135 }
1136
1137 // post in drawframe sync time
PostUifistSubTasks()1138 void RSUifirstManager::PostUifistSubTasks()
1139 {
1140 // if screen is power-off, uifirst sub thread can be suspended.
1141 if (RSUniRenderUtil::CheckRenderSkipIfScreenOff()) {
1142 return;
1143 }
1144 PurgePendingPostNodes();
1145 SortSubThreadNodesPriority();
1146 MarkPostNodesPriority();
1147 if (sortedSubThreadNodeIds_.size() > 0) {
1148 RS_TRACE_NAME_FMT("PostUifistSubTasks %zu", sortedSubThreadNodeIds_.size());
1149 for (auto& id : sortedSubThreadNodeIds_) {
1150 PostSubTask(id);
1151 }
1152 pendingPostNodes_.clear();
1153 pendingPostCardNodes_.clear();
1154 sortedSubThreadNodeIds_.clear();
1155 } else {
1156 ClearSubthreadRes();
1157 }
1158 UifirstCurStateClear();
1159 }
1160
IsInLeashWindowTree(RSSurfaceRenderNode & node,NodeId instanceRootId)1161 bool RSUifirstManager::IsInLeashWindowTree(RSSurfaceRenderNode& node, NodeId instanceRootId)
1162 {
1163 if (node.GetInstanceRootNodeId() == instanceRootId) {
1164 return true;
1165 }
1166 if (!node.IsLeashWindow()) {
1167 return false;
1168 }
1169 for (auto& child : *(node.GetChildren())) {
1170 if (!child) {
1171 continue;
1172 }
1173 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1174 if (!surfaceChild) {
1175 continue;
1176 }
1177 if (surfaceChild->GetInstanceRootNodeId() == instanceRootId) {
1178 return true;
1179 }
1180 }
1181 return false;
1182 }
1183
LeashWindowContainMainWindow(RSSurfaceRenderNode & node)1184 static inline bool LeashWindowContainMainWindow(RSSurfaceRenderNode& node)
1185 {
1186 if (node.IsLeashWindow() && node.HasSubSurfaceNodes()) {
1187 return true;
1188 }
1189 return false;
1190 }
1191
LeashWindowContainMainWindowAndStarting(RSSurfaceRenderNode & node)1192 NodeId RSUifirstManager::LeashWindowContainMainWindowAndStarting(RSSurfaceRenderNode& node)
1193 {
1194 if (!node.IsLeashWindow()) {
1195 return INVALID_NODEID;
1196 }
1197 int mainwindowNum = 0;
1198 int canvasNodeNum = 0;
1199 bool support = true;
1200 std::shared_ptr<RSRenderNode> startingWindow = nullptr;
1201 for (auto& child : *(node.GetSortedChildren())) {
1202 if (!child) {
1203 continue;
1204 }
1205 RS_TRACE_NAME_FMT("nID:%" PRIu64" , nType:%d, support:%d, canvasNodeNum:%d, mainwindowNum:%d",
1206 child->GetId(), static_cast<int>(child->GetType()), support, canvasNodeNum, mainwindowNum);
1207 auto canvasChild = child->ReinterpretCastTo<RSCanvasRenderNode>();
1208 if (canvasChild && canvasChild->GetChildrenCount() == 0 && mainwindowNum > 0) {
1209 canvasNodeNum++;
1210 if (startingWindow != nullptr) {
1211 startingWindow->SetStartingWindowFlag(false);
1212 }
1213 startingWindow = canvasChild;
1214 continue;
1215 }
1216 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1217 if (surfaceChild && surfaceChild->IsMainWindowType() && canvasNodeNum == 0) {
1218 mainwindowNum++;
1219 continue;
1220 }
1221 support = false;
1222 }
1223 RS_TRACE_NAME_FMT("uifirst_node support:%d, canvasNodeNum:%d, mainwindowNum:%d, hasStartingWindow:%d",
1224 support, canvasNodeNum, mainwindowNum, startingWindow != nullptr);
1225 if (support && canvasNodeNum == 1 && mainwindowNum > 0 && startingWindow) { // starting window & appwindow
1226 startingWindow->SetStartingWindowFlag(true);
1227 return startingWindow->GetId();
1228 } else {
1229 if (startingWindow) {
1230 startingWindow->SetStartingWindowFlag(false);
1231 }
1232 return INVALID_NODEID;
1233 }
1234 }
1235
HasStartingWindow(RSSurfaceRenderNode & node)1236 bool RSUifirstManager::HasStartingWindow(RSSurfaceRenderNode& node)
1237 {
1238 auto startingWindowId = LeashWindowContainMainWindowAndStarting(node);
1239 if (startingWindowId != INVALID_NODEID) { // has starting window
1240 node.SetUifirstUseStarting(startingWindowId);
1241 // block first frame callback
1242 NotifyUIStartingWindow(node.GetId(), true);
1243 return true;
1244 }
1245 return false;
1246 }
1247
AddPendingPostNode(NodeId id,std::shared_ptr<RSSurfaceRenderNode> & node,MultiThreadCacheType currentFrameCacheType)1248 void RSUifirstManager::AddPendingPostNode(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node,
1249 MultiThreadCacheType currentFrameCacheType)
1250 {
1251 if (id == INVALID_NODEID || !node) {
1252 return;
1253 }
1254
1255 // process for uifirst node
1256 UpdateChildrenDirtyRect(*node);
1257 node->SetHwcChildrenDisabledState();
1258 RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " children disabled by uifirst",
1259 node->GetName().c_str(), node->GetId());
1260 node->AddToPendingSyncList();
1261
1262 if (currentFrameCacheType == MultiThreadCacheType::LEASH_WINDOW ||
1263 currentFrameCacheType == MultiThreadCacheType::NONFOCUS_WINDOW) {
1264 if (isRecentTaskScene_.load() && !node->IsNodeToBeCaptured() &&
1265 currentFrameCacheType == MultiThreadCacheType::LEASH_WINDOW) {
1266 node->SetIsNodeToBeCaptured(true);
1267 } else if (!isRecentTaskScene_.load()) {
1268 node->SetIsNodeToBeCaptured(false);
1269 }
1270 // delete card node in leashwindow tree
1271 for (auto it = pendingPostCardNodes_.begin(); it != pendingPostCardNodes_.end();) {
1272 auto surfaceNode = it->second;
1273 if (surfaceNode && IsInLeashWindowTree(*node, surfaceNode->GetInstanceRootNodeId())) {
1274 DisableUifirstNode(*surfaceNode);
1275 it = pendingPostCardNodes_.erase(it);
1276 } else {
1277 it++;
1278 }
1279 }
1280 pendingPostNodes_[id] = node;
1281 AddPendingNodeBehindWindow(id, node, currentFrameCacheType);
1282 RS_OPTIONAL_TRACE_NAME_FMT("Add pending id:%" PRIu64 " size:%d", node->GetId(), pendingPostNodes_.size());
1283 } else if (currentFrameCacheType == MultiThreadCacheType::ARKTS_CARD) {
1284 pendingPostCardNodes_[id] = node;
1285 }
1286
1287 pendingResetNodes_.erase(id); // enable uifirst when waiting for reset
1288 }
1289
AddPendingNodeBehindWindow(NodeId id,std::shared_ptr<RSSurfaceRenderNode> & node,MultiThreadCacheType currentFrameCacheType)1290 void RSUifirstManager::AddPendingNodeBehindWindow(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node,
1291 MultiThreadCacheType currentFrameCacheType)
1292 {
1293 if (currentFrameCacheType == MultiThreadCacheType::NONFOCUS_WINDOW &&
1294 RSSystemProperties::GetUIFirstBehindWindowEnabled()) {
1295 auto temp_it = pendingNodeBehindWindow_.find(id);
1296 if (temp_it == pendingNodeBehindWindow_.end()) {
1297 RS_OPTIONAL_TRACE_NAME_FMT("Add to pendingNodeBehindWindow id:%" PRIu64 " name:%s", node->GetId(),
1298 node->GetName().c_str());
1299 pendingNodeBehindWindow_[id] = NodeDataBehindWindow{.curTime = GetMainThreadVsyncTime()};
1300 }
1301 }
1302 }
1303
AddPendingResetNode(NodeId id,std::shared_ptr<RSSurfaceRenderNode> & node)1304 void RSUifirstManager::AddPendingResetNode(NodeId id, std::shared_ptr<RSSurfaceRenderNode>& node)
1305 {
1306 if (id == INVALID_NODEID) {
1307 return;
1308 }
1309 pendingResetNodes_[id] = node;
1310 }
1311
GetNodeStatus(NodeId id)1312 CacheProcessStatus RSUifirstManager::GetNodeStatus(NodeId id)
1313 {
1314 auto drawable = GetSurfaceDrawableByID(id);
1315 if (drawable) {
1316 return drawable->GetRsSubThreadCache().GetCacheSurfaceProcessedStatus();
1317 }
1318 return CacheProcessStatus::UNKNOWN;
1319 }
1320
UpdateCompletedSurface(NodeId id)1321 void RSUifirstManager::UpdateCompletedSurface(NodeId id)
1322 {
1323 auto drawable = GetSurfaceDrawableByID(id);
1324 if (drawable) {
1325 drawable->GetRsSubThreadCache().UpdateCompletedCacheSurface();
1326 }
1327 }
1328
OnProcessEventResponse(DataBaseRs & info)1329 void RSUifirstManager::OnProcessEventResponse(DataBaseRs& info)
1330 {
1331 RSReclaimMemoryManager::Instance().InterruptReclaimTask(info.sceneId);
1332 RS_OPTIONAL_TRACE_NAME_FMT("uifirst uniqueId:%" PRId64", appPid:%" PRId32", sceneId:%s",
1333 info.uniqueId, info.appPid, info.sceneId.c_str());
1334 EventInfo eventInfo = {GetCurSysTime(), 0, info.uniqueId, info.appPid, info.sceneId, {}};
1335 std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1336 for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
1337 it->disableNodes.clear();
1338 }
1339 globalFrameEvent_.push_back(std::move(eventInfo));
1340 currentFrameCanSkipFirstWait_ = EventsCanSkipFirstWait(globalFrameEvent_);
1341 }
1342
OnProcessEventComplete(DataBaseRs & info)1343 void RSUifirstManager::OnProcessEventComplete(DataBaseRs& info)
1344 {
1345 int64_t curSysTime = GetCurSysTime();
1346 std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1347 for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
1348 if (it->uniqueId == info.uniqueId && it->sceneId == info.sceneId) {
1349 // delay delete for animation continue
1350 it->stopTime = curSysTime;
1351 break;
1352 }
1353 }
1354 }
1355
EventDisableLeashWindowCache(NodeId id,EventInfo & info)1356 void RSUifirstManager::EventDisableLeashWindowCache(NodeId id, EventInfo& info)
1357 {
1358 std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1359 for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end(); it++) {
1360 if (it->uniqueId == info.uniqueId && it->sceneId == info.sceneId) {
1361 it->disableNodes.insert(id);
1362 break;
1363 }
1364 }
1365 }
1366
PrepareCurrentFrameEvent()1367 void RSUifirstManager::PrepareCurrentFrameEvent()
1368 {
1369 int64_t curSysTime = GetCurSysTime();
1370 currentFrameEvent_.clear();
1371 if (!mainThread_) {
1372 mainThread_ = RSMainThread::Instance();
1373 }
1374 if (mainThread_) {
1375 const auto& nodeMap = mainThread_->GetContext().GetNodeMap();
1376 entryViewNodeId_ = nodeMap.GetEntryViewNodeId();
1377 negativeScreenNodeId_ = nodeMap.GetNegativeScreenNodeId();
1378 scbPid_ = ExtractPid(entryViewNodeId_);
1379 }
1380 {
1381 std::lock_guard<std::mutex> lock(globalFrameEventMutex_);
1382 for (auto it = globalFrameEvent_.begin(); it != globalFrameEvent_.end();) {
1383 if (it->stopTime != 0 &&
1384 ((curSysTime > it->stopTime) && (curSysTime - it->stopTime) > EVENT_STOP_TIMEOUT)) {
1385 it = globalFrameEvent_.erase(it);
1386 continue;
1387 }
1388
1389 if ((curSysTime > it->startTime) && (curSysTime - it->startTime) > EVENT_START_TIMEOUT) {
1390 it = globalFrameEvent_.erase(it);
1391 continue;
1392 }
1393 it++;
1394 }
1395 if (globalFrameEvent_.empty()) {
1396 currentFrameCanSkipFirstWait_ = false;
1397 return;
1398 }
1399 // copy global to current, judge leashwindow stop
1400 currentFrameEvent_.assign(globalFrameEvent_.begin(), globalFrameEvent_.end());
1401 }
1402 currentFrameCanSkipFirstWait_ = EventsCanSkipFirstWait(currentFrameEvent_);
1403 }
1404
OnProcessAnimateScene(SystemAnimatedScenes systemAnimatedScene)1405 void RSUifirstManager::OnProcessAnimateScene(SystemAnimatedScenes systemAnimatedScene)
1406 {
1407 RS_TRACE_NAME_FMT("OnProcessAnimateScene systemAnimatedScene:%d", systemAnimatedScene);
1408 RS_LOGD("OnProcessAnimateScene SystemAnimatedScene:[%{public}d]", systemAnimatedScene);
1409 switch (systemAnimatedScene) {
1410 // recent task scene for phone
1411 case SystemAnimatedScenes::ENTER_RECENTS:
1412 isRecentTaskScene_.store(true);
1413 break;
1414 case SystemAnimatedScenes::EXIT_RECENTS:
1415 isRecentTaskScene_.store(false);
1416 break;
1417 // enter and exit mission center are two independent animations, the same goes for enter and exit split screen
1418 // enter and exit mission center or enter and exit split screen animation starts for PC
1419 case SystemAnimatedScenes::ENTER_MISSION_CENTER:
1420 case SystemAnimatedScenes::EXIT_MISSION_CENTER:
1421 isMissionCenterScene_.store(true);
1422 break;
1423 case SystemAnimatedScenes::ENTER_SPLIT_SCREEN:
1424 case SystemAnimatedScenes::EXIT_SPLIT_SCREEN:
1425 isSplitScreenScene_.store(true);
1426 break;
1427 case SystemAnimatedScenes::SNAPSHOT_ROTATION:
1428 isSnapshotRotationScene_.store(true);
1429 break;
1430 // enter and exit mission center or enter and exit split screen animation ends for PC
1431 case SystemAnimatedScenes::OTHERS:
1432 isMissionCenterScene_.store(false);
1433 isSplitScreenScene_.store(false);
1434 isSnapshotRotationScene_.store(false);
1435 break;
1436 default:
1437 isSnapshotRotationScene_.store(false);
1438 break;
1439 }
1440 }
1441
NodeIsInCardWhiteList(RSRenderNode & node)1442 bool RSUifirstManager::NodeIsInCardWhiteList(RSRenderNode& node)
1443 {
1444 if ((entryViewNodeId_ != INVALID_NODEID) && (negativeScreenNodeId_ != INVALID_NODEID)) {
1445 auto instanceRootId = node.GetInstanceRootNodeId();
1446 if (instanceRootId == entryViewNodeId_ || instanceRootId == negativeScreenNodeId_) {
1447 return true;
1448 }
1449 }
1450 return false;
1451 }
1452
IsCardSkipFirstWaitScene(std::string & scene,int32_t appPid)1453 bool RSUifirstManager::IsCardSkipFirstWaitScene(std::string& scene, int32_t appPid)
1454 {
1455 if (appPid != scbPid_) {
1456 return false;
1457 }
1458 for (auto& item : cardCanSkipFirstWaitScene_) {
1459 if ((scene.find(item) != std::string::npos)) {
1460 return true;
1461 }
1462 }
1463 return false;
1464 }
1465
EventsCanSkipFirstWait(std::vector<EventInfo> & events)1466 bool RSUifirstManager::EventsCanSkipFirstWait(std::vector<EventInfo>& events)
1467 {
1468 if (events.empty()) {
1469 return false;
1470 }
1471 if (isCurrentFrameHasCardNodeReCreate_) {
1472 RS_OPTIONAL_TRACE_NAME("uifirst current frame can't skip wait");
1473 return false;
1474 }
1475 for (auto& item : events) {
1476 if (IsCardSkipFirstWaitScene(item.sceneId, item.appPid)) {
1477 return true;
1478 }
1479 }
1480 return false;
1481 }
1482
1483 // exit uifirst when leash has APP_LIST_FLING event.
CheckIfAppWindowHasAnimation(RSSurfaceRenderNode & node)1484 bool RSUifirstManager::CheckIfAppWindowHasAnimation(RSSurfaceRenderNode& node)
1485 {
1486 if (currentFrameEvent_.empty()) {
1487 return false;
1488 }
1489
1490 std::set<int32_t> appPids;
1491 if (node.IsAppWindow()) {
1492 appPids.insert(ExtractPid(node.GetId()));
1493 } else if (node.IsLeashWindow()) {
1494 for (auto& child : *(node.GetChildren())) {
1495 if (!child) {
1496 continue;
1497 }
1498 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1499 if (!surfaceChild) {
1500 continue;
1501 }
1502 if (surfaceChild->IsAppWindow()) {
1503 appPids.insert(ExtractPid(surfaceChild->GetId()));
1504 }
1505 }
1506 }
1507
1508 if (appPids.empty()) {
1509 return false;
1510 }
1511 for (auto& item : currentFrameEvent_) {
1512 if (item.disableNodes.count(node.GetId())) {
1513 return true;
1514 }
1515 if (appPids.count(item.appPid) && (node.GetUifirstStartTime() > 0) &&
1516 (node.GetUifirstStartTime() < (item.startTime - EVENT_DISABLE_UIFIRST_GAP)) &&
1517 (item.sceneId.find(EVENT_DISABLE_UIFIRST) != std::string::npos)) {
1518 EventDisableLeashWindowCache(node.GetId(), item);
1519 return true; // app has animation, stop leashwindow uifirst
1520 }
1521 }
1522 return false;
1523 }
1524
HasBgNodeBelowRootNode(RSSurfaceRenderNode & appNode) const1525 bool RSUifirstManager::HasBgNodeBelowRootNode(RSSurfaceRenderNode& appNode) const
1526 {
1527 auto appFirstChildren = appNode.GetFirstChild();
1528 if (!appFirstChildren) {
1529 return false;
1530 }
1531 auto rootNode = RSBaseRenderNode::ReinterpretCast<RSRootRenderNode>(appFirstChildren);
1532 if (!rootNode) {
1533 return false;
1534 }
1535 auto rootFirstChildren = rootNode->GetFirstChild();
1536 if (!rootFirstChildren) {
1537 return false;
1538 }
1539 auto bgColorNode = RSBaseRenderNode::ReinterpretCast<RSCanvasRenderNode>(rootFirstChildren);
1540 if (!bgColorNode) {
1541 return false;
1542 }
1543 auto backgroundColor =
1544 static_cast<Drawing::ColorQuad>(bgColorNode->GetRenderProperties().GetBackgroundColor().AsArgbInt());
1545 if (Drawing::Color::ColorQuadGetA(backgroundColor) != Drawing::Color::COLOR_TRANSPARENT) {
1546 return true;
1547 }
1548 return false;
1549 }
1550
CheckHasTransAndFilter(RSSurfaceRenderNode & node)1551 bool RSUifirstManager::CheckHasTransAndFilter(RSSurfaceRenderNode& node)
1552 {
1553 if (!node.IsLeashWindow()) {
1554 return false;
1555 }
1556 bool childHasVisibleFilter = node.ChildHasVisibleFilter();
1557 bool hasTransparent = false;
1558 RectI mainAppSurfaceRect = {};
1559 bool isMainAppSurface = false;
1560 bool hasChildOutOfMainAppSurface = false;
1561 for (auto &child : *node.GetSortedChildren()) {
1562 auto childSurface = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1563 if (childSurface == nullptr || hasChildOutOfMainAppSurface) {
1564 continue;
1565 }
1566 if (!isMainAppSurface && childSurface->IsAppWindow()) {
1567 bool isBgColorTrans = HasBgNodeBelowRootNode(*childSurface);
1568 hasTransparent |= (childSurface->IsTransparent() && !isBgColorTrans);
1569 mainAppSurfaceRect = childSurface->GetAbsDrawRect();
1570 isMainAppSurface = true;
1571 RS_OPTIONAL_TRACE_NAME_FMT("Id:%" PRIu64 " name[%s] isTrans:%d isBgTrans:%d, hasTrans:%d",
1572 childSurface->GetId(), childSurface->GetName().c_str(),
1573 childSurface->IsTransparent(), isBgColorTrans, hasTransparent);
1574 continue;
1575 }
1576 if (childSurface->IsTransparent() && !childSurface->GetAbsDrawRect().IsInsideOf(mainAppSurfaceRect)) {
1577 RS_OPTIONAL_TRACE_NAME_FMT("Id:%" PRIu64 " name[%s] absDrawRect is outof mainAppNode",
1578 childSurface->GetId(), childSurface->GetName().c_str());
1579 hasChildOutOfMainAppSurface = true;
1580 }
1581 }
1582 hasTransparent |= hasChildOutOfMainAppSurface;
1583 RS_TRACE_NAME_FMT("CheckHasTransAndFilter node:%" PRIu64 " hasTransparent: %d, childHasVisibleFilter: %d",
1584 node.GetId(), hasTransparent, childHasVisibleFilter);
1585 return hasTransparent && childHasVisibleFilter;
1586 }
1587
ProcessFirstFrameCache(RSSurfaceRenderNode & node,MultiThreadCacheType cacheType)1588 void RSUifirstManager::ProcessFirstFrameCache(RSSurfaceRenderNode& node, MultiThreadCacheType cacheType)
1589 {
1590 // purpose: to avoid that RT waits uifirst cache long time when switching to uifirst first frame,
1591 // draw and cache win in RT on first frame, then use RT thread cache to draw until uifirst cache ready.
1592 if (node.GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE &&
1593 !node.GetSubThreadAssignable()) {
1594 RS_TRACE_NAME_FMT("AssignMainThread selfAndParentShouldPaint: %d, skipDraw: %d",
1595 node.GetSelfAndParentShouldPaint(), node.GetSkipDraw());
1596 UifirstStateChange(node, MultiThreadCacheType::NONE); // mark as draw win in RT thread
1597 if (node.GetSelfAndParentShouldPaint() && !node.GetSkipDraw()) {
1598 node.SetSubThreadAssignable(true); // mark as assignable to uifirst next frame
1599 node.SetNeedCacheSurface(true); // mark as that needs cache win in RT
1600 auto parent = node.GetParent().lock();
1601 if (parent != nullptr && cacheType == MultiThreadCacheType::ARKTS_CARD) {
1602 // disable render group for card
1603 parent->SetDrawingCacheType(RSDrawingCacheType::DISABLED_CACHE);
1604 }
1605 node.SetHwcChildrenDisabledState();
1606 RS_OPTIONAL_TRACE_FMT("name:%s id:%" PRIu64 " children disabled by uifirst first frame",
1607 node.GetName().c_str(), node.GetId());
1608 // delte caches when node is not on the tree.
1609 auto func = &RSUifirstManager::ProcessTreeStateChange;
1610 node.RegisterTreeStateChangeCallback(func);
1611 }
1612 } else {
1613 UifirstStateChange(node, cacheType);
1614 }
1615 }
1616
IsArkTsCardCache(RSSurfaceRenderNode & node,bool animation)1617 bool RSUifirstManager::IsArkTsCardCache(RSSurfaceRenderNode& node, bool animation) // maybe canvas node ?
1618 {
1619 auto baseNode = node.GetAncestorScreenNode().lock();
1620 if (!baseNode) {
1621 RS_LOGE("surfaceNode GetAncestorScreenNode().lock() return nullptr");
1622 return false;
1623 }
1624 auto curScreenNode = baseNode->ReinterpretCastTo<RSScreenRenderNode>();
1625 if (curScreenNode == nullptr) {
1626 RS_LOGE("surfaceNode GetAncestorScreenNode().lock() return nullptr");
1627 return false;
1628 }
1629 // card node only enabled uifirst on phone
1630 if (RSUifirstManager::Instance().GetUiFirstMode() != UiFirstModeType::SINGLE_WINDOW_MODE ||
1631 node.GetSurfaceNodeType() != RSSurfaceNodeType::ABILITY_COMPONENT_NODE ||
1632 node.GetName().find(ARKTSCARDNODE_NAME) == std::string::npos) {
1633 return false;
1634 }
1635 bool isWhiteListCard = RSUifirstManager::Instance().NodeIsInCardWhiteList(node);
1636 bool shouldPaint = node.ShouldPaint();
1637 bool isNeedAssignToSubThread = isWhiteListCard && shouldPaint;
1638 RS_TRACE_NAME_FMT("IsArkTsCardCache toSubThread[%d] whiteListCard[%d] shouldPaint[%d]",
1639 isNeedAssignToSubThread, isWhiteListCard, shouldPaint);
1640 return isNeedAssignToSubThread;
1641 }
1642
1643 // animation first, may reuse last image cache
IsLeashWindowCache(RSSurfaceRenderNode & node,bool animation)1644 bool RSUifirstManager::IsLeashWindowCache(RSSurfaceRenderNode& node, bool animation)
1645 {
1646 if ((RSUifirstManager::Instance().GetUiFirstMode() == UiFirstModeType::MULTI_WINDOW_MODE) ||
1647 (node.GetFirstLevelNodeId() != node.GetId()) ||
1648 (RSUifirstManager::Instance().NodeIsInCardWhiteList(node)) ||
1649 (RSUifirstManager::Instance().CheckIfAppWindowHasAnimation(node))) {
1650 return false;
1651 }
1652 if (!node.IsLeashWindow()) {
1653 return false;
1654 }
1655 // check transparent and childHasVisibleFilter
1656 if (RSUifirstManager::Instance().CheckHasTransAndFilter(node)) {
1657 return false;
1658 }
1659
1660 bool isNeedAssignToSubThread = false;
1661 bool isScale = node.IsScale();
1662 bool hasFilter = node.HasFilter();
1663 bool isRotate = RSUifirstManager::Instance().rotationChanged_ &&
1664 !RSUifirstManager::Instance().IsSnapshotRotationScene();
1665 bool isRecentScene = RSUifirstManager::Instance().IsRecentTaskScene();
1666 if (isRecentScene) {
1667 isNeedAssignToSubThread = isScale && LeashWindowContainMainWindow(node);
1668 } else {
1669 isNeedAssignToSubThread = animation;
1670 }
1671 isNeedAssignToSubThread = (isNeedAssignToSubThread ||
1672 (node.GetForceUIFirst() || node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_ENABLE_LIMIT)) &&
1673 !hasFilter && !isRotate;
1674
1675 bool needFilterSCB = IS_SCB_WINDOW_TYPE(node.GetSurfaceWindowType());
1676 if (needFilterSCB || node.IsSelfDrawingType()) {
1677 RS_TRACE_NAME_FMT("IsLeashWindowCache: needFilterSCB [%d]", needFilterSCB);
1678 return false;
1679 }
1680 RS_TRACE_NAME_FMT("IsLeashWindowCache: toSubThread[%d] IsScale[%d]"
1681 " filter:[%d] rotate[%d] captured[%d] snapshotRotation[%d]",
1682 isNeedAssignToSubThread, node.IsScale(),
1683 node.HasFilter(), RSUifirstManager::Instance().rotationChanged_, node.IsNodeToBeCaptured(),
1684 RSUifirstManager::Instance().IsSnapshotRotationScene());
1685 RS_LOGD("IsLeashWindowCache: toSubThread[%{public}d] recent[%{public}d] scale[%{public}d] filter[%{public}d] "
1686 "rotate[%{public}d] snapshotRotation[%{public}d]", isNeedAssignToSubThread, isRecentScene, isScale, hasFilter,
1687 isRotate, RSUifirstManager::Instance().IsSnapshotRotationScene());
1688 return isNeedAssignToSubThread;
1689 }
1690
1691 // Vm app not use uifirst when it is focused
IsVMSurfaceName(std::string surfaceName)1692 bool RSUifirstManager::IsVMSurfaceName(std::string surfaceName)
1693 {
1694 for (auto& item : vmAppNameSet_) {
1695 if (surfaceName.find(item) != std::string::npos) {
1696 return true;
1697 }
1698 }
1699
1700 return false;
1701 }
1702
1703 // NonFocusWindow, may reuse last image cache
IsNonFocusWindowCache(RSSurfaceRenderNode & node,bool animation)1704 bool RSUifirstManager::IsNonFocusWindowCache(RSSurfaceRenderNode& node, bool animation)
1705 {
1706 if (RSUifirstManager::Instance().IsExceededWindowsThreshold(node)) {
1707 RS_TRACE_NAME_FMT("exceededThreshold id:%" PRIu64 ", threshold:%d, curUifirstWindowNums:%d", node.GetId(),
1708 RSUifirstManager::Instance().uifirstWindowsNumThreshold_,
1709 RSUifirstManager::Instance().curUifirstWindowNums_);
1710 return false;
1711 }
1712 bool isDisplayRotation = RSUifirstManager::Instance().rotationChanged_;
1713 if ((RSUifirstManager::Instance().GetUiFirstMode() != UiFirstModeType::MULTI_WINDOW_MODE) ||
1714 (node.GetFirstLevelNodeId() != node.GetId()) ||
1715 (RSUifirstManager::Instance().NodeIsInCardWhiteList(node))) {
1716 return false;
1717 }
1718
1719 std::string surfaceName = node.GetName();
1720 bool needFilterSCB = IS_SCB_WINDOW_TYPE(node.GetSurfaceWindowType());
1721 if (!(node.GetForceUIFirst() || node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_ENABLE_LIMIT)
1722 && (needFilterSCB || node.IsSelfDrawingType())) {
1723 return false;
1724 }
1725 bool focus = RSUifirstManager::Instance().IsFocusedNode(node);
1726 // open app with modal window animation, close uifirst
1727 bool modalAnimation = animation && node.GetUIFirstSwitch() == RSUIFirstSwitch::MODAL_WINDOW_CLOSE;
1728 bool optFocus = focus || UNLIKELY(node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_DISABLE_NONFOCUS);
1729 if (optFocus && (node.GetHasSharedTransitionNode() ||
1730 (RSUifirstManager::Instance().IsVMSurfaceName(surfaceName) && !animation) ||
1731 !animation || modalAnimation)) {
1732 RS_TRACE_NAME_FMT("IsNonFocusWindowCache: surfaceName[%s] focus:%d optFocus:%d animation:%d switch:%d",
1733 surfaceName.c_str(), focus, optFocus, animation, node.GetUIFirstSwitch());
1734 return false;
1735 }
1736 // disable uifirst when leash window has no app window at recent task scene or split screen scene
1737 if (node.IsLeashWindow() && node.IsScale() && !LeashWindowContainMainWindow(node) &&
1738 (RSUifirstManager::Instance().IsMissionCenterScene() || RSUifirstManager::Instance().IsSplitScreenScene())) {
1739 RS_TRACE_NAME("leash window has no app window, disable uifirst");
1740 return false;
1741 }
1742 return RSUifirstManager::Instance().QuerySubAssignable(node, isDisplayRotation);
1743 }
1744
IsToSubByAppAnimation() const1745 CM_INLINE bool RSUifirstManager::IsToSubByAppAnimation() const
1746 {
1747 for (auto& it : currentFrameEvent_) {
1748 if (std::find(toSubByAppAnimation_.begin(), toSubByAppAnimation_.end(), it.sceneId) !=
1749 toSubByAppAnimation_.end()) {
1750 return true;
1751 }
1752 }
1753 return false;
1754 }
1755
GetSubNodeIsTransparent(RSSurfaceRenderNode & node,std::string & dfxMsg)1756 bool RSUifirstManager::GetSubNodeIsTransparent(RSSurfaceRenderNode& node, std::string& dfxMsg)
1757 {
1758 bool hasTransparent = false;
1759 if (node.IsLeashWindow()) {
1760 for (auto &child : *node.GetSortedChildren()) {
1761 auto childSurfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1762 if (childSurfaceNode == nullptr) {
1763 continue;
1764 }
1765 hasTransparent |= childSurfaceNode->IsAlphaTransparent() || (childSurfaceNode->NeedDrawBehindWindow() &&
1766 !RSSystemProperties::GetUIFirstBehindWindowFilterEnabled());
1767 if (hasTransparent) {
1768 dfxMsg = "childSurfaceNode_NeedDrawBehindWindow: " +
1769 std::to_string(childSurfaceNode->NeedDrawBehindWindow());
1770 break;
1771 }
1772 }
1773 } else {
1774 hasTransparent = node.IsAlphaTransparent() || (node.NeedDrawBehindWindow() &&
1775 !RSSystemProperties::GetUIFirstBehindWindowFilterEnabled());
1776 dfxMsg = "NeedDrawBehindWindow: " + std::to_string(node.NeedDrawBehindWindow());
1777 }
1778 if (!hasTransparent || !IsToSubByAppAnimation()) {
1779 // if not transparent, no need to check IsToSubByAppAnimation;
1780 return hasTransparent;
1781 }
1782
1783 bool isAbilityBgColorTransparent = true;
1784 if (node.IsLeashWindow()) {
1785 for (auto &child : *node.GetSortedChildren()) {
1786 auto childSurfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1787 if (childSurfaceNode == nullptr) {
1788 continue;
1789 }
1790 if (childSurfaceNode->GetAbilityBgAlpha() < UINT8_MAX) {
1791 isAbilityBgColorTransparent = true;
1792 dfxMsg = "AbBgAlpha: " + std::to_string(childSurfaceNode->GetAbilityBgAlpha());
1793 break;
1794 } else {
1795 isAbilityBgColorTransparent = false;
1796 }
1797 }
1798 } else {
1799 isAbilityBgColorTransparent = node.GetAbilityBgAlpha() < UINT8_MAX;
1800 dfxMsg = "AbBgAlpha: " + std::to_string(node.GetAbilityBgAlpha());
1801 }
1802 return isAbilityBgColorTransparent;
1803 }
1804
QuerySubAssignable(RSSurfaceRenderNode & node,bool isRotation)1805 bool RSUifirstManager::QuerySubAssignable(RSSurfaceRenderNode& node, bool isRotation)
1806 {
1807 if (!node.IsFirstLevelNode()) {
1808 return false;
1809 }
1810
1811 auto childHasVisibleFilter = node.ChildHasVisibleFilter();
1812 auto hasFilter = node.HasFilter();
1813 auto globalAlpha = node.GetGlobalAlpha();
1814 auto hasProtectedLayer = node.GetSpecialLayerMgr().Find(SpecialLayerType::HAS_PROTECTED);
1815 std::string dfxMsg;
1816 auto hasTransparentSurface = GetSubNodeIsTransparent(node, dfxMsg);
1817
1818 RS_TRACE_NAME_FMT("SubThreadAssignable node[%lld] hasTransparent: %d, childHasVisibleFilter: %d, hasFilter: %d,"
1819 "isRotation: %d & %d globalAlpha[%f], hasProtectedLayer: %d %s", node.GetId(), hasTransparentSurface,
1820 childHasVisibleFilter, hasFilter, isRotation, RSSystemProperties::GetCacheOptimizeRotateEnable(), globalAlpha,
1821 hasProtectedLayer, dfxMsg.c_str());
1822 bool rotateOptimize = RSSystemProperties::GetCacheOptimizeRotateEnable() ?
1823 !(isRotation && ROSEN_EQ(globalAlpha, 0.0f)) : !isRotation;
1824 return !(hasTransparentSurface && childHasVisibleFilter) && !hasFilter && rotateOptimize && !hasProtectedLayer;
1825 }
1826
ForceUpdateUifirstNodes(RSSurfaceRenderNode & node)1827 bool RSUifirstManager::ForceUpdateUifirstNodes(RSSurfaceRenderNode& node)
1828 {
1829 bool isForceDisabled = (node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_DISABLE);
1830 bool hasProtectedLayer = node.GetSpecialLayerMgr().Find(SpecialLayerType::HAS_PROTECTED);
1831 if (!isUiFirstOn_ || !node.GetUifirstSupportFlag() || isForceDisabled || hasProtectedLayer) {
1832 RS_LOGD("uifirst disabled. id:%{public}" PRIu64 ",uifirstOn:%{public}d,support:%{public}d,"
1833 "forceDisabled:%{public}d,protectLayer:%{public}d",
1834 node.GetId(), isUiFirstOn_, node.GetUifirstSupportFlag(), isForceDisabled, hasProtectedLayer);
1835 UifirstStateChange(node, MultiThreadCacheType::NONE);
1836 // This branch will be discarded
1837 if (!node.isUifirstNode_) {
1838 node.isUifirstDelay_++;
1839 if (node.isUifirstDelay_ > EVENT_STOP_TIMEOUT) {
1840 node.isUifirstNode_ = true;
1841 }
1842 }
1843 return true;
1844 }
1845 // This branch will be discarded
1846 if (node.isForceFlag_ && node.IsLeashWindow()) {
1847 RS_OPTIONAL_TRACE_NAME_FMT("ForceUpdateUifirstNodes: isUifirstEnable: %d", node.isUifirstEnable_);
1848 if (!node.isUifirstEnable_) {
1849 UifirstStateChange(node, MultiThreadCacheType::NONE);
1850 return true;
1851 }
1852 UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1853 return true;
1854 }
1855 if (node.GetUIFirstSwitch() == RSUIFirstSwitch::FORCE_ENABLE && node.IsLeashWindow()) {
1856 RS_OPTIONAL_TRACE_NAME_FMT("ForceUpdateUifirstNodes: nodeName: %s, uiFirstSwitch: %d",
1857 node.GetName().c_str(), node.GetUIFirstSwitch());
1858 if (RSUifirstManager::Instance().GetUiFirstMode() == UiFirstModeType::MULTI_WINDOW_MODE) {
1859 UifirstStateChange(node, MultiThreadCacheType::NONFOCUS_WINDOW);
1860 } else {
1861 UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1862 }
1863 return true;
1864 }
1865 return false;
1866 }
1867
UpdateUifirstNodes(RSSurfaceRenderNode & node,bool ancestorNodeHasAnimation)1868 void RSUifirstManager::UpdateUifirstNodes(RSSurfaceRenderNode& node, bool ancestorNodeHasAnimation)
1869 {
1870 RS_TRACE_NAME_FMT("UpdateUifirstNodes: Id[%llu] name[%s] FLId[%llu] Ani[%d] Support[%d] isUiFirstOn[%d],"
1871 " isForceFlag:[%d], hasProtectedLayer:[%d] switch:[%d] curUifirstWindowNum:[%d] threshold:[%d]", node.GetId(),
1872 node.GetName().c_str(), node.GetFirstLevelNodeId(), ancestorNodeHasAnimation, node.GetUifirstSupportFlag(),
1873 isUiFirstOn_, node.isForceFlag_, node.GetSpecialLayerMgr().Find(SpecialLayerType::HAS_PROTECTED),
1874 node.GetUIFirstSwitch(), curUifirstWindowNums_, uifirstWindowsNumThreshold_);
1875 if (ForceUpdateUifirstNodes(node)) {
1876 return;
1877 }
1878 if (RSUifirstManager::IsLeashWindowCache(node, ancestorNodeHasAnimation)) {
1879 if (RSSystemParameters::GetUIFirstStartingWindowCacheEnabled()) {
1880 if (node.GetLastFrameUifirstFlag() == MultiThreadCacheType::NONE && HasStartingWindow(node)) {
1881 UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1882 } else {
1883 ProcessFirstFrameCache(node, MultiThreadCacheType::LEASH_WINDOW);
1884 }
1885 } else {
1886 UifirstStateChange(node, MultiThreadCacheType::LEASH_WINDOW);
1887 }
1888 return;
1889 }
1890 if (RSUifirstManager::IsNonFocusWindowCache(node, ancestorNodeHasAnimation)) {
1891 ProcessFirstFrameCache(node, MultiThreadCacheType::NONFOCUS_WINDOW);
1892 return;
1893 }
1894 if (RSUifirstManager::IsArkTsCardCache(node, ancestorNodeHasAnimation)) {
1895 ProcessFirstFrameCache(node, MultiThreadCacheType::ARKTS_CARD);
1896 return;
1897 }
1898 UifirstStateChange(node, MultiThreadCacheType::NONE);
1899 }
1900
UifirstStateChange(RSSurfaceRenderNode & node,MultiThreadCacheType currentFrameCacheType)1901 void RSUifirstManager::UifirstStateChange(RSSurfaceRenderNode& node, MultiThreadCacheType currentFrameCacheType)
1902 {
1903 auto lastFrameCacheType = node.GetLastFrameUifirstFlag();
1904 if ((lastFrameCacheType != MultiThreadCacheType::NONE) && (lastFrameCacheType != currentFrameCacheType)) {
1905 // not support cache type switch, just disable multithread cache
1906 currentFrameCacheType = MultiThreadCacheType::NONE;
1907 }
1908 if (lastFrameCacheType == MultiThreadCacheType::NONE) { // likely branch: last is disable
1909 if (currentFrameCacheType != MultiThreadCacheType::NONE) { // switch: disable -> enable
1910 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.shared_from_this());
1911 if (!surfaceNode) {
1912 RS_LOGE("UifirstStateChange surfaceNode is nullptr");
1913 return;
1914 }
1915 RS_TRACE_NAME_FMT("UIFirst_switch disable -> enable %" PRIu64, node.GetId());
1916 RS_LOGI("uifirst disable -> enable. %{public}s id:%{public}" PRIu64, node.GetName().c_str(), node.GetId());
1917 SetUifirstNodeEnableParam(node, currentFrameCacheType);
1918 if (currentFrameCacheType == MultiThreadCacheType::ARKTS_CARD) { // now only update ArkTSCardNode
1919 node.UpdateTreeUifirstRootNodeId(node.GetId());
1920 }
1921 auto func = &RSUifirstManager::ProcessTreeStateChange;
1922 node.RegisterTreeStateChangeCallback(func);
1923 node.SetUifirstStartTime(GetCurSysTime());
1924 AddPendingPostNode(node.GetId(), surfaceNode, currentFrameCacheType); // clear pending reset status
1925 AddCardNodes(node.GetId(), currentFrameCacheType);
1926 node.SetSubThreadAssignable(true);
1927 node.SetNeedCacheSurface(false);
1928 IncreaseUifirstWindowCount(node);
1929 } else { // keep disable
1930 RS_OPTIONAL_TRACE_NAME_FMT("UIFirst_keep disable %" PRIu64, node.GetId());
1931 node.SetSubThreadAssignable(false);
1932 node.SetNeedCacheSurface(false);
1933 }
1934 } else { // last is enable
1935 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.shared_from_this());
1936 if (currentFrameCacheType != MultiThreadCacheType::NONE) { // keep enable
1937 RS_OPTIONAL_TRACE_NAME_FMT("UIFirst_keep enable %" PRIu64, node.GetId());
1938 RS_LOGD("uifirst keep enable. %{public}s id:%{public}" PRIu64, node.GetName().c_str(), node.GetId());
1939 AddPendingPostNode(node.GetId(), surfaceNode, currentFrameCacheType);
1940 IncreaseUifirstWindowCount(node);
1941 } else { // switch: enable -> disable
1942 RS_TRACE_NAME_FMT("UIFirst_switch enable -> disable %" PRIu64, node.GetId());
1943 RS_LOGI("uifirst enable -> disable. %{public}s id:%{public}" PRIu64, node.GetName().c_str(), node.GetId());
1944 node.SetUifirstStartTime(-1); // -1: default start time
1945 AddPendingResetNode(node.GetId(), surfaceNode); // set false onsync when task done
1946 RemoveCardNodes(node.GetId());
1947 node.SetSubThreadAssignable(false);
1948 node.SetNeedCacheSurface(false);
1949
1950 auto tempNodeToClear = pendingNodeBehindWindow_.find(node.GetId());
1951 if (tempNodeToClear != pendingNodeBehindWindow_.end()) {
1952 RS_OPTIONAL_TRACE_NAME_FMT("clear node in pendingNodeBehindWindow %{public}s id:%{public}" PRIu64,
1953 node.GetName().c_str(), node.GetId());
1954 pendingNodeBehindWindow_.erase(tempNodeToClear);
1955 }
1956 DecreaseUifirstWindowCount(node);
1957 }
1958 }
1959 node.SetLastFrameUifirstFlag(currentFrameCacheType);
1960 }
1961
1962 // appwindow will not be traversed in process when cache leashwindow
UpdateChildrenDirtyRect(RSSurfaceRenderNode & node)1963 void RSUifirstManager::UpdateChildrenDirtyRect(RSSurfaceRenderNode& node)
1964 {
1965 RectI rect(0, 0, 0, 0);
1966 if (node.IsLeashWindow()) {
1967 for (auto& child : *(node.GetChildren())) {
1968 if (!child) {
1969 continue;
1970 }
1971 auto surfaceChild = child->ReinterpretCastTo<RSSurfaceRenderNode>();
1972 if (!surfaceChild) {
1973 continue;
1974 }
1975 if (surfaceChild->IsMainWindowType()) {
1976 rect = rect.JoinRect(surfaceChild->GetOldDirtyInSurface());
1977 continue;
1978 }
1979 }
1980 }
1981 node.SetUifirstChildrenDirtyRectParam(rect);
1982 }
1983
ProcessTreeStateChange(RSSurfaceRenderNode & node)1984 void RSUifirstManager::ProcessTreeStateChange(RSSurfaceRenderNode& node)
1985 {
1986 RSUifirstManager::Instance().CheckCurrentFrameHasCardNodeReCreate(node);
1987 // Planning: do not clear complete image for card
1988 if (node.IsOnTheTree()) {
1989 return;
1990 }
1991 RSUifirstManager::Instance().DisableUifirstNode(node);
1992 RSUifirstManager::Instance().ForceClearSubthreadRes();
1993 RSUifirstManager::Instance().RemoveCardNodes(node.GetId());
1994 }
1995
DisableUifirstNode(RSSurfaceRenderNode & node)1996 void RSUifirstManager::DisableUifirstNode(RSSurfaceRenderNode& node)
1997 {
1998 RS_TRACE_NAME_FMT("DisableUifirstNode node[%lld] %s", node.GetId(), node.GetName().c_str());
1999 UifirstStateChange(node, MultiThreadCacheType::NONE);
2000
2001 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.shared_from_this());
2002 pendingResetWindowCachedNodes_.emplace_back(surfaceNode);
2003 }
2004
AddCapturedNodes(NodeId id)2005 void RSUifirstManager::AddCapturedNodes(NodeId id)
2006 {
2007 capturedNodes_.push_back(id);
2008 }
2009
ResetCurrentFrameDeletedCardNodes()2010 void RSUifirstManager::ResetCurrentFrameDeletedCardNodes()
2011 {
2012 currentFrameDeletedCardNodes_.clear();
2013 isCurrentFrameHasCardNodeReCreate_ = false;
2014 }
2015
CheckCurrentFrameHasCardNodeReCreate(const RSSurfaceRenderNode & node)2016 void RSUifirstManager::CheckCurrentFrameHasCardNodeReCreate(const RSSurfaceRenderNode& node)
2017 {
2018 if (node.GetSurfaceNodeType() != RSSurfaceNodeType::ABILITY_COMPONENT_NODE ||
2019 node.GetName().find(ARKTSCARDNODE_NAME) == std::string::npos) {
2020 return;
2021 }
2022 if (!node.IsOnTheTree()) {
2023 currentFrameDeletedCardNodes_.emplace_back(node.GetId());
2024 } else if (std::find(currentFrameDeletedCardNodes_.begin(), currentFrameDeletedCardNodes_.end(),
2025 node.GetId()) != currentFrameDeletedCardNodes_.end()) {
2026 isCurrentFrameHasCardNodeReCreate_ = true;
2027 }
2028 }
2029
CheckMatchAndWaitNotify(const RSRenderParams & params,bool checkMatch)2030 bool RSUiFirstProcessStateCheckerHelper::CheckMatchAndWaitNotify(const RSRenderParams& params, bool checkMatch)
2031 {
2032 if (checkMatch && IsCurFirstLevelMatch(params)) {
2033 return true;
2034 }
2035 return CheckAndWaitPreFirstLevelDrawableNotify(params);
2036 }
2037
CheckAndWaitPreFirstLevelDrawableNotify(const RSRenderParams & params)2038 bool RSUiFirstProcessStateCheckerHelper::CheckAndWaitPreFirstLevelDrawableNotify(const RSRenderParams& params)
2039 {
2040 auto firstLevelNodeId = params.GetFirstLevelNodeId();
2041 auto uifirstRootNodeId = params.GetUifirstRootNodeId();
2042 auto rootId = uifirstRootNodeId != INVALID_NODEID ? uifirstRootNodeId : firstLevelNodeId;
2043 if (rootId == INVALID_NODEID) {
2044 /* uifirst will not draw with no firstlevel node, and there's no need to check and wait for uifirst onDraw */
2045 RS_LOGD("uifirst node %{public}" PRIu64 " uifirstrootNodeId is INVALID_NODEID", params.GetId());
2046 return true;
2047 }
2048
2049 auto uifirstRootNodeDrawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(rootId);
2050 if (!uifirstRootNodeDrawable) {
2051 // drawable may release when node off tree
2052 // uifirst will not draw with null uifirstRootNodeDrawable
2053 RS_LOGW("uifirstnode %{public}" PRIu64 " uifirstroot %{public}" PRIu64 " nullptr", params.GetId(), rootId);
2054 return true;
2055 }
2056
2057 if (UNLIKELY(uifirstRootNodeDrawable->GetNodeType() != RSRenderNodeType::SURFACE_NODE)) {
2058 RS_LOGE("uifirst invalid uifirstrootNodeId %{public}" PRIu64, rootId);
2059 return false;
2060 }
2061 auto uifirstRootSurfaceNodeDrawable =
2062 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(uifirstRootNodeDrawable);
2063
2064 RS_TRACE_NAME_FMT("CheckAndWaitPreFirstLevelDrawableNotify %" PRIu64 " wait for %" PRIu64 "",
2065 params.GetId(), uifirstRootSurfaceNodeDrawable->GetId());
2066
2067 static constexpr auto TIME_OUT = std::chrono::milliseconds(500); // 500ms for timeout
2068 auto pred = [uifirstRootSurfaceNodeDrawable] {
2069 auto curState = uifirstRootSurfaceNodeDrawable->GetRsSubThreadCache().GetCacheSurfaceProcessedStatus();
2070 return curState == CacheProcessStatus::DONE || curState == CacheProcessStatus::UNKNOWN ||
2071 curState == CacheProcessStatus::SKIPPED;
2072 };
2073 std::unique_lock<std::mutex> lock(notifyMutex_);
2074 notifyCv_.wait_for(lock, TIME_OUT, pred);
2075 auto ret = pred();
2076 if (!ret) {
2077 RS_LOGE("uifirst nodeId %{public}" PRIu64
2078 " wait uifirstrootNodeId %{public}" PRIu64 " until 500ms timeout", params.GetId(), rootId);
2079 }
2080 return ret;
2081 }
2082
IsCurFirstLevelMatch(const RSRenderParams & params)2083 bool RSUiFirstProcessStateCheckerHelper::IsCurFirstLevelMatch(const RSRenderParams& params)
2084 {
2085 auto uifirstRootNodeId = params.GetUifirstRootNodeId();
2086 auto firstLevelNodeId = params.GetFirstLevelNodeId();
2087
2088 RS_OPTIONAL_TRACE_NAME_FMT("RSUiFirstProcessStateCheckerHelper IsCurFirstLevelMatch In node[%"
2089 PRIu64 " %" PRIu64"] cur[%" PRIu64 " %" PRIu64 "] in nodeId[%" PRIu64 "]",
2090 uifirstRootNodeId, firstLevelNodeId, curUifirstRootNodeId_, curFirstLevelNodeId_, params.GetId());
2091
2092 if (curUifirstRootNodeId_ == INVALID_NODEID && curFirstLevelNodeId_ == INVALID_NODEID) {
2093 // should draw because uifirst may not inited
2094 return true;
2095 }
2096 auto uiFirstCheckRet = uifirstRootNodeId == curUifirstRootNodeId_ && curUifirstRootNodeId_ != INVALID_NODEID;
2097 auto firstLevelCheckRet = firstLevelNodeId == curFirstLevelNodeId_ && curFirstLevelNodeId_ != INVALID_NODEID;
2098 if (uiFirstCheckRet || firstLevelCheckRet) {
2099 return true;
2100 }
2101 return false;
2102 }
2103
GetCacheSurfaceProcessedStatus(const RSSurfaceRenderParams & surfaceParams)2104 CacheProcessStatus RSUifirstManager::GetCacheSurfaceProcessedStatus(const RSSurfaceRenderParams& surfaceParams)
2105 {
2106 CacheProcessStatus curRootIdState = CacheProcessStatus::UNKNOWN;
2107 auto uifirstRootId = surfaceParams.GetUifirstRootNodeId() != INVALID_NODEID ?
2108 surfaceParams.GetUifirstRootNodeId() : surfaceParams.GetFirstLevelNodeId();
2109 auto uifirstRootNodeDrawable = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(uifirstRootId);
2110 if (uifirstRootNodeDrawable && uifirstRootNodeDrawable->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
2111 auto drawableNode = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(uifirstRootNodeDrawable);
2112 curRootIdState = drawableNode->GetRsSubThreadCache().GetCacheSurfaceProcessedStatus();
2113 }
2114 return curRootIdState;
2115 }
2116
GetUiFirstMode()2117 UiFirstModeType RSUifirstManager::GetUiFirstMode()
2118 {
2119 if (uifirstType_ == UiFirstCcmType::SINGLE) {
2120 return UiFirstModeType::SINGLE_WINDOW_MODE;
2121 }
2122 if (uifirstType_ == UiFirstCcmType::MULTI) {
2123 return UiFirstModeType::MULTI_WINDOW_MODE;
2124 }
2125 if (uifirstType_ == UiFirstCcmType::HYBRID) {
2126 return isFreeMultiWindowEnabled_ ? UiFirstModeType::MULTI_WINDOW_MODE : UiFirstModeType::SINGLE_WINDOW_MODE;
2127 }
2128 return UiFirstModeType::SINGLE_WINDOW_MODE;
2129 }
2130
ReadUIFirstCcmParam()2131 void RSUifirstManager::ReadUIFirstCcmParam()
2132 {
2133 #ifdef ROSEN_EMULATOR
2134 // close uifirst on emulator
2135 isUiFirstOn_ = false;
2136 isCardUiFirstOn_ = false;
2137 #else
2138 isUiFirstOn_ = UIFirstParam::IsUIFirstEnable();
2139 isCardUiFirstOn_ = UIFirstParam::IsCardUIFirstEnable();
2140 #endif
2141 SetUiFirstType(UIFirstParam::GetUIFirstType());
2142 uifirstWindowsNumThreshold_ = UIFirstParam::GetUIFirstEnableWindowThreshold();
2143 RS_LOGI("ReadUIFirstCcmParam isUiFirstOn_=%{public}d isCardUiFirstOn_=%{public}d"
2144 " uifirstType_=%{public}d uiFirstEnableWindowThreshold_=%{public}d",
2145 isUiFirstOn_, isCardUiFirstOn_, static_cast<int>(uifirstType_), uifirstWindowsNumThreshold_);
2146 }
2147
SetUiFirstType(int type)2148 void RSUifirstManager::SetUiFirstType(int type)
2149 {
2150 if (type < (int)UiFirstCcmType::SINGLE || type > (int)UiFirstCcmType::HYBRID) {
2151 return;
2152 }
2153 if (type == (int)UiFirstCcmType::SINGLE) {
2154 uifirstType_ = UiFirstCcmType::SINGLE;
2155 } else if (type == (int)UiFirstCcmType::MULTI) {
2156 uifirstType_ = UiFirstCcmType::MULTI;
2157 } else if (type == (int)UiFirstCcmType::HYBRID) {
2158 uifirstType_ = UiFirstCcmType::HYBRID;
2159 }
2160 }
2161
RefreshUIFirstParam()2162 void RSUifirstManager::RefreshUIFirstParam()
2163 {
2164 RSUifirstManager::Instance().SetPurgeEnable(RSSystemParameters::GetUIFirstPurgeEnabled());
2165 const std::shared_ptr<RSBaseRenderNode> rootNode = RSMainThread::Instance()->GetContext()
2166 .GetGlobalRootRenderNode();
2167 if (!rootNode) {
2168 return;
2169 }
2170 auto firstChildren = rootNode->GetFirstChild();
2171 if (!firstChildren) {
2172 return;
2173 }
2174 auto screenNode = RSBaseRenderNode::ReinterpretCast<RSScreenRenderNode>(firstChildren);
2175 if (!screenNode) {
2176 return;
2177 }
2178 isUiFirstSupportFlag_ = true;
2179 }
2180
IsSubTreeNeedPrepareForSnapshot(RSSurfaceRenderNode & node)2181 bool RSUifirstManager::IsSubTreeNeedPrepareForSnapshot(RSSurfaceRenderNode& node)
2182 {
2183 return RSUifirstManager::Instance().IsRecentTaskScene() &&
2184 (node.IsFocusedNode(RSMainThread::Instance()->GetFocusLeashWindowId()) ||
2185 node.IsFocusedNode(RSMainThread::Instance()->GetFocusNodeId()));
2186 }
2187
IsSubHighPriorityType(RSSurfaceRenderNode & node) const2188 bool RSUifirstManager::IsSubHighPriorityType(RSSurfaceRenderNode& node) const
2189 {
2190 return node.GetName().find("hipreview") != std::string::npos;
2191 }
2192
CheckHwcChildrenType(RSSurfaceRenderNode & node,SurfaceHwcNodeType & enabledType)2193 void RSUifirstManager::CheckHwcChildrenType(RSSurfaceRenderNode& node, SurfaceHwcNodeType& enabledType)
2194 {
2195 if (enabledType == SurfaceHwcNodeType::DEFAULT_HWC_ROSENWEB) {
2196 return;
2197 }
2198 if (node.IsAppWindow()) {
2199 auto hwcNodes = node.GetChildHardwareEnabledNodes();
2200 if (hwcNodes.empty()) {
2201 return;
2202 }
2203 if (IsSubHighPriorityType(node)) {
2204 enabledType = SurfaceHwcNodeType::DEFAULT_HWC_VIDEO;
2205 return;
2206 }
2207 if (node.IsRosenWeb()) {
2208 enabledType = SurfaceHwcNodeType::DEFAULT_HWC_ROSENWEB;
2209 return;
2210 }
2211 for (auto hwcNode : hwcNodes) {
2212 auto hwcNodePtr = hwcNode.lock();
2213 if (!hwcNodePtr) {
2214 continue;
2215 }
2216 if (hwcNodePtr->IsRosenWeb()) {
2217 enabledType = SurfaceHwcNodeType::DEFAULT_HWC_ROSENWEB;
2218 return;
2219 }
2220 if (IsSubHighPriorityType(*hwcNodePtr)) {
2221 enabledType = SurfaceHwcNodeType::DEFAULT_HWC_VIDEO;
2222 return;
2223 }
2224 }
2225 } else if (node.IsLeashWindow()) {
2226 for (auto& child : *(node.GetChildren())) {
2227 auto surfaceNode = child->ReinterpretCastTo<RSSurfaceRenderNode>();
2228 if (surfaceNode == nullptr) {
2229 continue;
2230 }
2231 CheckHwcChildrenType(*surfaceNode, enabledType);
2232 }
2233 }
2234 }
2235
MarkSubHighPriorityType(RSSurfaceRenderNode & node)2236 void RSUifirstManager::MarkSubHighPriorityType(RSSurfaceRenderNode& node)
2237 {
2238 if (uifirstType_ != UiFirstCcmType::MULTI) {
2239 return;
2240 }
2241 SurfaceHwcNodeType preSubHighPriority = SurfaceHwcNodeType::DEFAULT_HWC_TYPE;
2242 CheckHwcChildrenType(node, preSubHighPriority);
2243 RS_OPTIONAL_TRACE_NAME_FMT("SubHighPriorityType::name:[%s] preSub:%d", node.GetName().c_str(), preSubHighPriority);
2244 node.SetPreSubHighPriorityType(preSubHighPriority == SurfaceHwcNodeType::DEFAULT_HWC_VIDEO);
2245 }
2246
RecordScreenRect(RSSurfaceRenderNode & node,RectI rect)2247 void RSUifirstManager::RecordScreenRect(RSSurfaceRenderNode& node, RectI rect)
2248 {
2249 auto stagingSurfaceParams = static_cast<RSSurfaceRenderParams*>(node.GetStagingRenderParams().get());
2250 if (!stagingSurfaceParams) {
2251 RS_LOGE("RecordScreenRect stagingSurfaceParams is nullptr");
2252 return;
2253 }
2254 stagingSurfaceParams->RecordScreenRect(rect);
2255 node.AddToPendingSyncList();
2256 }
2257
RecordDirtyRegionMatrix(RSSurfaceRenderNode & node,const Drawing::Matrix & matrix)2258 void RSUifirstManager::RecordDirtyRegionMatrix(RSSurfaceRenderNode& node, const Drawing::Matrix& matrix)
2259 {
2260 auto stagingSurfaceParams = static_cast<RSSurfaceRenderParams*>(node.GetStagingRenderParams().get());
2261 if (!stagingSurfaceParams) {
2262 RS_LOGE("RecordDirtyRegionMatrix stagingSurfaceParams is nullptr");
2263 return;
2264 }
2265 stagingSurfaceParams->RecordDirtyRegionMatrix(matrix);
2266 node.AddToPendingSyncList();
2267 }
2268
IsFocusedNode(const RSSurfaceRenderNode & node) const2269 bool RSUifirstManager::IsFocusedNode(const RSSurfaceRenderNode& node) const
2270 {
2271 return node.IsFocusedNode(RSMainThread::Instance()->GetFocusNodeId()) ||
2272 node.IsFocusedNode(RSMainThread::Instance()->GetFocusLeashWindowId());
2273 }
2274
IncreaseUifirstWindowCount(const RSSurfaceRenderNode & node)2275 void RSUifirstManager::IncreaseUifirstWindowCount(const RSSurfaceRenderNode& node)
2276 {
2277 if (IsFocusedNode(node) || node.IsAbilityComponent()) {
2278 return;
2279 }
2280 curUifirstWindowNums_++;
2281 }
2282
DecreaseUifirstWindowCount(const RSSurfaceRenderNode & node)2283 void RSUifirstManager::DecreaseUifirstWindowCount(const RSSurfaceRenderNode& node)
2284 {
2285 if (IsFocusedNode(node) || node.IsAbilityComponent()) {
2286 return;
2287 }
2288 if (curUifirstWindowNums_ > 0) {
2289 curUifirstWindowNums_--;
2290 }
2291 }
2292
IsExceededWindowsThreshold(const RSSurfaceRenderNode & node) const2293 bool RSUifirstManager::IsExceededWindowsThreshold(const RSSurfaceRenderNode& node) const
2294 {
2295 // no restriction when threshold is less than or equal to 0
2296 if (uifirstWindowsNumThreshold_ <= 0) {
2297 return false;
2298 }
2299
2300 // do not count focus window
2301 if (IsFocusedNode(node)) {
2302 return false;
2303 }
2304
2305 // Non-focus window, Z/V sequence control
2306 if (curUifirstWindowNums_ < uifirstWindowsNumThreshold_) {
2307 return false;
2308 }
2309 return true;
2310 }
2311
AddMarkedClearCacheNode(NodeId id)2312 void RSUifirstManager::AddMarkedClearCacheNode(NodeId id)
2313 {
2314 RS_TRACE_NAME_FMT("AddMarkedClearCacheNode %" PRIu64, id);
2315 RS_LOGI("AddMarkedClearCacheNode %{public}" PRIu64, id);
2316 if (id == INVALID_NODEID) {
2317 return;
2318 }
2319
2320 markedClearCacheNodes_.insert(id);
2321 }
2322
ProcessMarkedNodeSubThreadCache()2323 void RSUifirstManager::ProcessMarkedNodeSubThreadCache()
2324 {
2325 RS_OPTIONAL_TRACE_NAME_FMT("ProcessMarkedNodeSubThreadCache size:%d", markedClearCacheNodes_.size());
2326 for (auto& markedNode : markedClearCacheNodes_) {
2327 if (subthreadProcessingNode_.find(markedNode) == subthreadProcessingNode_.end()) {
2328 auto drawable = GetSurfaceDrawableByID(markedNode);
2329 if (!drawable) {
2330 RS_LOGE("ProcessMarkedNodeSubThreadCache drawable is null. id:%{public}" PRIu64, markedNode);
2331 continue;
2332 }
2333 if ((pendingPostNodes_.find(markedNode) != pendingPostNodes_.end()) ||
2334 (pendingPostCardNodes_.find(markedNode) != pendingPostCardNodes_.end())) {
2335 continue;
2336 }
2337 RS_TRACE_NAME_FMT("ProcessMarkedNodeSubThreadCache id:%" PRIu64, markedNode);
2338 RS_LOGI("ProcessMarkedNodeSubThreadCache id:%{public}" PRIu64, markedNode);
2339 auto& rsSubThreadCache = drawable->GetRsSubThreadCache();
2340 rsSubThreadCache.ClearCacheSurfaceOnly();
2341 }
2342 }
2343 markedClearCacheNodes_.clear();
2344 }
2345 } // namespace Rosen
2346 } // namespace OHOS
2347