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