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